C#-调用传递LPVARIANT的非托管C++函数

本文关键字:C++ 函数 调用 LPVARIANT C#- | 更新日期: 2023-09-27 17:59:45

我想从我的托管代码中调用以下函数:

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);

我试着调用传递随机数的函数,结果稍微好了一点,我刚刚收到一个错误"内存访问违规"。很明显,因为随机数不是一个有效的地址。

有人知道这个问题的解决办法吗?

感谢您提供任何有用的信息。

C#-调用传递LPVARIANT的非托管C++函数

您创建的访问冲突也好不到哪里去。它还防止生成MDA警告。除了参数类型错误之外,int16看起来很奇怪,最有可能的问题是由CallingConvention引起的。尝试StdCall。

并将第二个参数声明为"object",其默认封送处理为VARIANT。用"ref"关键字声明它以获得LPVARIANT。

"调用LS_LoadConfig函数使堆栈不平衡,请检查参数是否与非托管签名匹配"。

这通常意味着您在本机代码和托管代码之间使用了冲突的调用约定。默认情况下,C#使用stdcall,而C/C++使用cdecl。尝试指定CallingConvention=CalingConvention。Cdecl。