Я только что закончил проверку концепции или, как мне показалось, подачи Microsoft Visual Studio 2010 некоторого кода C ++ в качестве консольной программы. Скомпилированный код C ++ приведен ниже:
#include "stdafx.h"#include <stdio.h>
#include <Windows.h>
#include <stdlib.h>
#include <sndfile.h>//The following libraries are related to parsing the text files
#include <iostream> //Open the file
#include <fstream> //Reading to and from files//The following libraries are for conducting the DTW analysis
#include "dtw.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
printf("This is a test\n");//This will be the length of the buffer used to hold samples while the program processes them.//A SNDFILE is like FILE in a standard C library. Consequently, the sf_open_read and sf_open_write functions will return an
//SNDFILE* pointer when they successfully open the specified file.
SNDFILE* sf = NULL;
/*SF_INFO will obtain information of the file we wish to load into our program. */
SF_INFO info;
/*The following is descriptive information to obtain from wave files. These are declarations*/
int num_channels;
double num, num_items;S
double *buf;
int f, sr, c;
int i,j;
FILE *out;/*This is where the program will open the WAV file */
info.format = 0;
sf = sf_open("C:\\Users\\GeekyOmega\\Desktop\\gameon.wav", SFM_READ, &info);
if(sf == NULL)
{
printf("Failed to open the file.\n");
getchar();
exit(-1);
}
/*Print some file information */
f = info.frames;
sr = info.samplerate;
c = info.channels;
/*Print information related to file*/
printf("frames = %d\n",f);
printf("sample rate = %d\n",sr);
printf("channels = %d\n",c);
/*Calculate and print the number of items*/
num_items = f*c;
printf("Read %lf items\n", num_items);
/*Allocate space for the data to be read*/
buf = (double *) malloc(num_items*sizeof(double));
num = sf_read_double(sf,buf,num_items);
sf_close(sf);
/*print the information*/
printf("Read %lf items\n", num);/*Write the data to the filedata.out*/
out = fopen("filedata.txt", "w");
for(i = 0; i < num; i+=c)
{
for(j = 0; j < c; ++j)
{
fprintf(out, "%lf ", buf[i +j]);
}
fprintf(out,"\n");
}
fclose(out);
}
Итак, далее, и это очень важно, я хочу, чтобы это работало с графическим интерфейсом. То есть я загружаю любой файл, который мне нужен, и он преобразует этот файл в текстовый формат. Я предоставляю этот код ниже:
#pragma once
//Libraries required for libsndfile
#include <sndfile.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <fstream>namespace WaveGui {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
using namespace System::Runtime::InteropServices;using namespace std;
/// <summary>
/// Summary for Form1
/// </summary>
Я отредактировал это для удобства чтения. Это была стандартная форма MSVS2010. Я только добавил кнопку и открыть диалоговое окно файла.
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e)
{
if(openFileDialog1->ShowDialog() == System::Windows::Forms::DialogResult::OK)
{
//Note: Ask Gustafson how we might free the memory for this strign
// http://support.microsoft.com/?id=311259
char* str2 = (char*)(void*)Marshal::StringToHGlobalAnsi(openFileDialog1->FileName);
SNDFILE* sf = NULL;
SF_INFO info;
/*The following is descriptive information to obtain from wave files. These are declarations*/
int num_channels;
double num, num_items;
double *buf;
int f, sr, c;
int i,j;
FILE *out;/*This is where the program will open the WAV file */
info.format = 0;
sf = sf_open(str2, SFM_READ, &info);
if(sf == NULL)
{
exit(-1);
}
/*Print some file information */
f = info.frames;
sr = info.samplerate;
c = info.channels;
/*Calculate and print the number of items*/
num_items = f*c;
/*Allocate space for the data to be read*/
buf = (double *) malloc(num_items*sizeof(double));
num = sf_read_double(sf,buf,num_items);
sf_close(sf);
/*Write the data to the filedata.out*/
out = fopen("filedata.txt", "w");
for(i = 0; i < num; i+=c)
{
for(j = 0; j < c; ++j)
{
fprintf(out, "%lf ", buf[i +j]);
}
fprintf(out,"\n");
}
fclose(out);}}
};
}
В коде для кнопки я преобразовываю системную строку в обычную строку, а затем пытаюсь использовать приведенный выше код C ++ для преобразования моего волнового файла в текстовую информацию. Я знаю, что код преобразования работает, и я знаю, что код кнопки работает, поскольку я тестировал их отдельно. Однако моя библиотека sndfile.h действительно умирает, когда я пытаюсь использовать ее сейчас.
Ошибка, которую я получаю при добавлении библиотек stdio.h, Windows.H, stdlib.h, iostream, fstream, выглядит следующим образом:
1>WaveGui.obj : error LNK2031: unable to generate p/invoke for "extern "C" int __clrcall sf_close(struct SNDFILE_tag *)" (?sf_close@@$$J0YMHPAUSNDFILE_tag@@@Z); calling convention missing in metadata
1>WaveGui.obj : error LNK2031: unable to generate p/invoke for "extern "C" __int64 __clrcall sf_read_double(struct SNDFILE_tag *,double *,__int64)" (?sf_read_double@@$$J0YM_JPAUSNDFILE_tag@@PAN_J@Z); calling convention missing in metadata
1>WaveGui.obj : error LNK2031: unable to generate p/invoke for "extern "C" struct SNDFILE_tag * __clrcall sf_open(char const *,int,struct SF_INFO *)" (?sf_open@@$$J0YMPAUSNDFILE_tag@@PBDHPAUSF_INFO@@@Z); calling convention missing in metadata
1>WaveGui.obj : warning LNK4248: unresolved typeref token (01000027) for 'SNDFILE_tag'; image may not run
1>WaveGui.obj : error LNK2028: unresolved token (0A000022) "extern "C" int __clrcall sf_close(struct SNDFILE_tag *)" (?sf_close@@$$J0YMHPAUSNDFILE_tag@@@Z) referenced in function "private: void __clrcall WaveGui::Form1::button1_Click(class System::Object ^,class System::EventArgs ^)" (?button1_Click@Form1@WaveGui@@$$FA$AAMXP$AAVObject@System@@P$AAVEventArgs@4@@Z)
1>WaveGui.obj : error LNK2028: unresolved token (0A000023) "extern "C" __int64 __clrcall sf_read_double(struct SNDFILE_tag *,double *,__int64)" (?sf_read_double@@$$J0YM_JPAUSNDFILE_tag@@PAN_J@Z) referenced in function "private: void __clrcall WaveGui::Form1::button1_Click(class System::Object ^,class System::EventArgs ^)" (?button1_Click@Form1@WaveGui@@$$FA$AAMXP$AAVObject@System@@P$AAVEventArgs@4@@Z)
1>WaveGui.obj : error LNK2028: unresolved token (0A000025) "extern "C" struct SNDFILE_tag * __clrcall sf_open(char const *,int,struct SF_INFO *)" (?sf_open@@$$J0YMPAUSNDFILE_tag@@PBDHPAUSF_INFO@@@Z) referenced in function "private: void __clrcall WaveGui::Form1::button1_Click(class System::Object ^,class System::EventArgs ^)" (?button1_Click@Form1@WaveGui@@$$FA$AAMXP$AAVObject@System@@P$AAVEventArgs@4@@Z)
1>WaveGui.obj : error LNK2019: unresolved external symbol "extern "C" int __clrcall sf_close(struct SNDFILE_tag *)" (?sf_close@@$$J0YMHPAUSNDFILE_tag@@@Z) referenced in function "private: void __clrcall WaveGui::Form1::button1_Click(class System::Object ^,class System::EventArgs ^)" (?button1_Click@Form1@WaveGui@@$$FA$AAMXP$AAVObject@System@@P$AAVEventArgs@4@@Z)
1>WaveGui.obj : error LNK2019: unresolved external symbol "extern "C" __int64 __clrcall sf_read_double(struct SNDFILE_tag *,double *,__int64)" (?sf_read_double@@$$J0YM_JPAUSNDFILE_tag@@PAN_J@Z) referenced in function "private: void __clrcall WaveGui::Form1::button1_Click(class System::Object ^,class System::EventArgs ^)" (?button1_Click@Form1@WaveGui@@$$FA$AAMXP$AAVObject@System@@P$AAVEventArgs@4@@Z)
1>WaveGui.obj : error LNK2019: unresolved external symbol "extern "C" struct SNDFILE_tag * __clrcall sf_open(char const *,int,struct SF_INFO *)" (?sf_open@@$$J0YMPAUSNDFILE_tag@@PBDHPAUSF_INFO@@@Z) referenced in function "private: void __clrcall WaveGui::Form1::button1_Click(class System::Object ^,class System::EventArgs ^)" (?button1_Click@Form1@WaveGui@@$$FA$AAMXP$AAVObject@System@@P$AAVEventArgs@4@@Z)
1>c:\users\geekyomega\documents\visual studio 2010\Projects\WaveGui\Debug\WaveGui.exe : fatal error LNK1120: 6 unresolved externals
Насколько я могу судить, я правильно установил библиотеку. В конце концов, это прекрасно работает с этими библиотеками в консольной ситуации. Однако, когда я пытаюсь использовать точно такой же код и библиотеки с моей формой графического интерфейса, кажется, что библиотеки не очень хорошо играют друг с другом, и в результате я не могу правильно прочитать мой файл .h и структуры доступа, такие как SNDFILE. ,
Может кто-нибудь, пожалуйста, дайте мне знать, что идет не так? Я потратил на это часы и надеюсь, что мне не придется пересматривать библиотеку libsndfile. Я действительно хочу заставить его работать с MSVS2010, с графическим интерфейсом, и, насколько я могу судить, нет причин, по которым это не должно работать. Но вы знаете, что они говорят, компьютеры не лгут.
Как всегда, спасибо за помощь пациента.
GeekyOmega
Итак, ваше консольное приложение является собственным кодом, но ваше приложение с графическим интерфейсом управляется C ++. Было ли это преднамеренным, или вы намеревались, чтобы ваше приложение с графическим интерфейсом тоже было нативным (Win32) кодом?
Я думаю, вам повезет больше, если вы будете использовать 100% нативный код или, возможно, создадите DLL для инкапсуляции вашего нативного кода и вызовите ее через P / Invoke из вашего .NET GUI. Вот пример использования P / Invoke:
http://manski.net/2012/05/29/pinvoke-tutorial-basics-part-1/
Других решений пока нет …