【发布时间】:2019-02-14 13:51:54
【问题描述】:
我需要通过在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 签名的调用约定和参数是否与目标非托管签名匹配。
【问题讨论】:
-
不应该是
__cdecl,而不是__stdcall吗? docs.microsoft.com/en-us/cpp/cpp/cdecl?view=vs-2017 -
是dll中的__stdcall。我已使用以下内容进行导入。 [DllImport("VoicemeeterRemote.dll", EntryPoint = "VBVMR_Input_GetDeviceDescA", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)]
-
您的问题中有
CallingConvention = CallingConvention.Cdecl。除此之外,C 的long是C# 的int。最重要的是,您应该使用CharSet.AnsiandStringBuilder作为char * szDeviceName, char * szHardwareId。 -
将其更改为 CallingConvention.StdCall 的响应相同
-
@UmairAsghar 解决其他两个问题。