zoukankan      html  css  js  c++  java
  • C#调用C和C++函数的一点区别

    最近做U800电话的二次开发,需要调用厂商的C函数库来打电话,后来想加入通话录音功能,但发现程序默认生产的WAV文件过大,又找了个WAV转MP3的C++函数库程序,出了点问题。下面是转MP3的程序接口(头文件):

    #ifndef _MP3ENC_H_
    #define _MP3ENC_H_
    
    int mp3_enc(const char* inWavName,int nRate,const char* outMP3Name);
    
    #endif

    按照C#调用非托管程序的约定,声明一个对应的C#函数接口:

     [DllImport("mp3enc.dll", CharSet = CharSet.Ansi)]
     public static extern int mp3_enc(string inWavName, int nRate, string outMP3Name);

    然后这样调用改函数:

     mp3_enc(txtWavFile.Text, 32, "222.mp3");

    结果出现这样的异常信息:

    1 对 PInvoke 函数“U800Test!U800Test.Form1::mp3_enc”的调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。请检查 PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配。

    跟原来调用C函数库的方法仔细对比,发现没有区别,而C函数代码却可以正常使用:
    打电话的C函数接口:

    USBDLL_API int _stdcall StartDial(int iDevIdx,const char* szDest);    //发送拨号命令

    对应的C#函数接口:

      [DllImport("UsbDll.dll", CharSet = CharSet.Ansi)]
      public static extern int StartDial(int iDevIdx,string szDest);


    再看看C++的调用函数的错误信息,难道是C++字符串类型不一致?需要C++使用Unicode 字符?于是将C#的函数接口改成:

     [DllImport("mp3enc.dll", CharSet = CharSet.Unicode)]
    public static extern int mp3_enc(string inWavName, int nRate, string outMP3Name);

    结果C#程序直接崩溃,连Try....Catch.... 都没用。

    最后,在网上搜索了半天,发现有这个说法:

    DllImport还有一个CallingConvention的属性,默认值是CallingCovention.Stdcall,  此处更改成Cdecl(c/c++默认调用方式)就可以了。VS2010下必须得指定这个属性才能运行, 同样的代码在VS2008下却不存在这样的问题, 奇怪 ...

    正确的C++ 函数C#调用接口应该是这样:

    [DllImport("mp3enc.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
     public static extern int mp3_enc(string inWavName, int nRate, string outMP3Name);
  • 相关阅读:
    linux 如何使用密钥登录 (CentOs)
    linux修改ssh端口 以及禁止root远程登录 (实验机 CentOs)
    查看Windows端口及端口关闭方法
    使用 Linux 终端 SSH 登录 VPS
    修改Chrome默认搜索引擎为Google.com
    Windows 小技巧: 變更輸入法順序
    CentOS 安装BitTorrent Sync详细步骤
    Android手机部分名词浅谈
    PPTP模式跟L2TP模式有什么不同
    .CO域名快被这帮搞IT的玩坏了……
  • 原文地址:https://www.cnblogs.com/jordan2009/p/3248821.html
Copyright © 2011-2022 走看看