C# - 调用非托管 C++函数传递 LPVARIANT
我想从托管代码中调用以下函数:
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);
我尝试调用传递随机数的函数,情况稍好一些,我刚刚收到错误“内存访问冲突”。显然是因为随机数不是有效地址。
有人知道这个问题的解决办法吗?
感谢您提供任何有用的信息。
I want to call the following function from my managed code:
short LS_LoadConfig(LS_ID SensorID,LPVARIANT varConfigPathFile,BOOL bInit)
Here is how I declare the extern function in my C# class:
[DllImport("LineSensor.dll", EntryPoint = "#16")]
private static extern Int16 LS_LoadConfig(
Int16 deviceId,
IntPtr variantFilePath,
int init);
And here is how I create the VARIANT instance and I obtain a pointer to it. Then I call the C# function:
string filepath = @"C:\Windows\ ...";
IntPtr variantFilePath = Marshal.AllocCoTaskMem(200);
Marshal.GetNativeVariantForObject(filepath, variantFilePath);
LS_LoadConfig(device.Id, variantFilePath, initLineSensor);
The problem is that I keep receiving error messages such as "calling the LS_LoadConfig function has unbalanced the stack, check that parameters match the unmanaged signature".
It seems that the problem is caused by the second argument "variantFilePath", like it is not properly marshaled and its size on the unmanaged heap doesn't correspond to the one of an address (32-bit in my case). I tried to change the type in the C# function signature from IntPtr to int as follows:
[DllImport("LineSensor.dll", EntryPoint = "#16")]
private static extern Int16 LS_LoadConfig(
Int16 deviceId,
int variantFilePath,
int init);
I tried to call the function passing a random number and it got slightly better, I have just received an error "memory access violation". Obviously because the random number wasn't a valid address.
Does anybody knows the solution to this problem?
Thank you for any helpful information.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您创建的访问冲突并没有更好。它还可以防止生成 MDA 警告。除了参数类型错误之外,int16 看起来很奇怪,最有可能的问题是由 CallingConvention 引起的。尝试StdCall。
并将第二个参数声明为“对象”,其默认封送处理为 VARIANT。使用“ref”关键字声明它以获取 LPVARIANT。
The access violation you created is not better. It also prevents the MDA warning from being generated. Short from the argument types being wrong, the int16 looks pretty weird, the most likely trouble is caused by the CallingConvention. Try StdCall.
And declare the 2nd argument as "object", its default marshaling is to a VARIANT. Declare it with the "ref" keyword to get an LPVARIANT.
这通常意味着您在本机代码和托管代码之间使用了冲突的调用约定。 C#默认使用stdcall,c/c++默认使用cdecl。尝试指定 CallingConvention = CallingConvention.Cdecl。
This usually means that you're using conflicting calling conventions between your native and managed code. C# by default uses stdcall, and c/c++ uses cdecl. Try specifying CallingConvention = CallingConvention.Cdecl.