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

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM