我想从托管代码中调用以下函数:
short LS_LoadConfig(LS_ID SensorID,LPVARIANT varConfigPathFile,BOOL bInit)
以下是我在C#类中声明extern函数的方法:
[DllImport("LineSensor.dll", EntryPoint = "#16")]
private static extern Int16 LS_LoadConfig(
Int16 deviceId,
IntPtr variantFilePath,
int init);
以下是我如何创建VARIANT实例并获取指向它的指针。然后我调用C#函数:
string filepath = @"C:\Windows\ ...";
IntPtr variantFilePath = Marshal.AllocCoTaskMem(200);
Marshal.GetNativeVariantForObject(filepath, variantFilePath);
LS_LoadConfig(device.Id, variantFilePath, initLineSensor);
问题是我一直收到错误消息,例如“调用LS_LoadConfig函数使堆栈不平衡,检查参数是否与非托管签名匹配”。
似乎问题是由第二个参数“variantFilePath”引起的,就像它没有正确编组并且它在非托管堆上的大小不对应于地址之一(在我的情况下是32位)。我尝试将C#函数签名中的类型从IntPtr更改为int,如下所示:
[DllImport("LineSensor.dll", EntryPoint = "#16")]
private static extern Int16 LS_LoadConfig(
Int16 deviceId,
int variantFilePath,
int init);
我试图调用函数传递一个随机数,它稍微好一点,我刚刚收到错误“内存访问冲突”。显然是因为随机数不是有效地址。
有人知道这个问题的解决方案吗?
感谢您提供任何有用的信息。
答案 0 :(得分:1)
您创建的访问冲突并不是更好。它还可以防止生成MDA警告。由于参数类型错误,int16看起来很奇怪,最可能的麻烦是由CallingConvention引起的。试试StdCall。
并将第二个参数声明为“object”,其默认编组是VARIANT。使用“ref”关键字声明它以获取LPVARIANT。
答案 1 :(得分:0)
“调用LS_LoadConfig函数使堆栈失衡,检查参数是否与非托管签名匹配”。
这通常意味着您在本机代码和托管代码之间使用了冲突的调用约定。 C#默认使用stdcall,而c / c ++使用cdecl。尝试指定CallingConvention = CallingConvention.Cdecl。