MSVS2010 C++ Console Code Ported to MSVS2010 C++ GUI is Failing. Why?

血红的双手。 提交于 2020-01-06 11:46:39

问题


I just completed a proof of concept, or so I thought, of feeding Microsoft Visual Studio 2010 some C++ code as a console program. The C++ code that compiled is given below:

#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);

}

So next, and this is critical, I want this to work with a GUI. That is, I load in any file I want and it converts that wav file to text. I provide that code below:

#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>

I edited this for readability. It was a standard MSVS2010 form. I only added a button and open file dialog.

    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);



                 }




             }
    };
}

In the code for the button, I convert from a system string to regular string and then try to use the C++ code above to convert my wave file to txt information. I know the conversion code works, and I know the button code works as I have tested them separately. However, my library sndfile.h really dies when I try to use it now.

The error it gives me when I added the libraries stdio.h, Windows.H, stdlib.h, iostream, fstream is as follows:

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

As near as I can tell, I installed the library right. After all, it works perfectly fine with these libraries in a console situation. However, when I try to use the exact same code and libraries with my GUI form, it seems that the libraries are not playing nice with each other and as a result, I can't read my .h file right and access structs like SNDFILE.

Can someone please let me know what is going wrong? I have spent hours on this and I hope I don't have to scrap the libsndfile library. I really want to get it to work with MSVS2010, with the GUI and as far as I can tell, there is no reason this shouldn't be working. But you know what they say, computers don't lie.

As always, thanks for your patient help. GeekyOmega


回答1:


So, your console app is native code, but your GUI app is managed C++. Was that intentional, or did you intend for your GUI app to be native (Win32) code too?

I think you'll have better luck if you either go with 100% native code, or perhaps create a DLL to encapsulate your native code and call that via P/Invoke from your .NET GUI. Here's an example of using P/Invoke:

http://manski.net/2012/05/29/pinvoke-tutorial-basics-part-1/



来源:https://stackoverflow.com/questions/13189650/msvs2010-c-console-code-ported-to-msvs2010-c-gui-is-failing-why

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!