gpt4 book ai didi

c# - 如何从C#调用DLL中的C函数?

转载 作者:行者123 更新时间:2023-11-30 14:41:56 25 4
gpt4 key购买 nike

我需要通过在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 时抛出异常:

A call to PInvoke function 'Voicemeter!Voicemeter.Program::VBVMR_Input_GetDeviceDescA' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.

最佳答案

如果您的导出函数在导出它的 DLL 中使用调用约定 __stdcall 声明,则需要使用 CallingConvention.StdCall 在 C# 代码中导入它,而不是Cdecl

此调用约定不匹配出现有关“堆栈不平衡”的错误的原因是,在调用 cdecl 函数之后,调用代码预计会在函数之后调整堆栈指针寄存器call 从堆栈中删除传递给函数的参数。但是,由于您的函数实际上是一个 stdcall 函数,因此它本身在它使用的 ret imm16 指令中执行此操作,因此当调用代码“清理堆栈”时,您的堆栈会下溢“也是。

下一个问题是 C# 中的 long 和 MSVC 中的 long 的大小不同,因此即使使用 stdcall 调用约定,被调用的函数弹出与它认为参数列表的正确大小相对应的字节数,但由于 C# 的 long 与 MSVC 的 long 大小不同,因此堆栈为在 DLL 函数末尾的 ret imm16 指令之后仍然不平衡。然而,C# 的 int 类型对应于 long

关于c# - 如何从C#调用DLL中的C函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54692022/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com