簡體   English   中英

如何從C#調用DLL中的C函數?

[英]How to call C function in DLL from C#?

我需要通過在C#中導入DLL來調用C的以下函數,但是會出現以下錯誤。

我已導入DLL並成功執行了其他功能,而此功能引發錯誤。

C方法:

long __stdcall VBVMR_Input_GetDeviceDescA(long zindex, long * nType, char * szDeviceName, char * szHardwareId);

C#代碼:

[DllImport("VoicemeeterRemote.dll", EntryPoint = "VBVMR_Input_GetDeviceDescA", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]
private static extern int VBVMR_Input_GetDeviceDescA(long zindex, ref long nType, [Out] byte[] szDeviceName, [Out] byte[] szHardwareId);

long nType = 0;
byte[] c = new byte[100];
byte[] b = new byte[100];
long i=0;

int rep = VBVMR_Input_GetDeviceDescA(i,ref nType, c, b);

在執行VBVMR_Input_GetDeviceDescA引發異常:

調用PInvoke函數'Voicemeter!Voicemeter.Program::VBVMR_Input_GetDeviceDescA'已使堆棧不平衡。 這可能是因為托管PInvoke簽名與非托管目標簽名不匹配。 檢查PInvoke簽名的調用約定和參數是否與目標非托管簽名匹配。

如果導出的函數是在導出該函數的DLL中使用調用約定__stdcall聲明的,則需要使用CallingConvention.StdCall而不是Cdecl將其導入C#代碼中。

此調用約定不匹配會顯示有關“堆棧不平衡”的錯誤的原因是,在調用cdecl函數后,期望調用代碼在函數調用后調整棧指針寄存器,以從中刪除傳遞給函數的參數。堆棧。 但是,由於您的函數實際上是stdcall函數,因此它會在所使用的ret imm16指令中自行執行ret imm16操作,因此,當調用代碼“清理堆棧”時,堆棧也會下溢。

接下來的問題是, long在C#和long在MSVC的大小不同,所以即使與stdcall調用約定,被調用函數彈出對應於它的想法是對的參數列表中正確大小的字節數,但由於C#的long與MSVC的long大小不同,在DLL函數末尾的ret imm16指令后,堆棧仍然不平衡。 C#的int類型對應於long

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM