C#-调用非托管C++;函数传递变量
我想从托管代码调用以下函数:C#-调用非托管C++;函数传递变量,c#,pointers,structure,unmanaged,variant,C#,Pointers,Structure,Unmanaged,Variant,我想从托管代码调用以下函数: short LS_LoadConfig(LS_ID SensorID,LPVARIANT varConfigPathFile,BOOL bInit) 下面是我在C#类中声明extern函数的方式: 下面是如何创建VARIANT实例并获取指向它的指针。然后我调用C#函数: string filepath = @"C:\Windows\ ..."; IntPtr variantFilePath = Marshal.AllocCoTaskMem(200); Marsha
short LS_LoadConfig(LS_ID SensorID,LPVARIANT varConfigPathFile,BOOL bInit)
下面是我在C#类中声明extern函数的方式:
下面是如何创建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);
我试图调用传递一个随机数的函数,结果稍微好了一点,我刚刚收到一个错误“内存访问冲突”。显然是因为随机数不是一个有效的地址
有人知道这个问题的解决办法吗
感谢您提供的有用信息。您创建的访问冲突并没有更好。它还可以防止生成MDA警告。除了参数类型错误之外,int16看起来很奇怪,最有可能的问题是调用约定造成的。试试StdCall
并将第二个参数声明为“object”,其默认封送处理是到一个变量。使用“ref”关键字声明它以获得LPVARIANT。您创建的访问冲突并不好。它还可以防止生成MDA警告。除了参数类型错误之外,int16看起来很奇怪,最有可能的问题是调用约定造成的。试试StdCall 并将第二个参数声明为“object”,其默认封送处理是到一个变量。使用“ref”关键字声明它以获得LPVARIANT “调用LS_LoadConfig函数会导致堆栈失衡,请检查参数是否与非托管签名匹配” 这通常意味着您在本机代码和托管代码之间使用了冲突的调用约定。默认情况下,C#使用stdcall,C/C++使用cdecl。尝试指定CallingConvention=CallingConvention.Cdecl “调用LS_LoadConfig函数会导致堆栈失衡,请检查参数是否与非托管签名匹配”
这通常意味着您在本机代码和托管代码之间使用了冲突的调用约定。默认情况下,C#使用stdcall,C/C++使用cdecl。请尝试指定CallingConvention=CallingConvention.Cdecl。问题在于调用约定必须设置为Cdecl。因此[DllImport(“LineSensor.dll”,EntryPoint=“#16”,CallingConvention=CallingConvention.Cdecl)]修复了所有问题@Hans传递ref对象与传递LPVARIANT是一样的,但比我的解决方案更优雅。问题是调用约定必须设置为Cdecl。因此[DllImport(“LineSensor.dll”,EntryPoint=“#16”,CallingConvention=CallingConvention.Cdecl)]修复了所有问题@Hans传递ref对象与传递LPVARIANT是一样的,但比我的解决方案更优雅。
[DllImport("LineSensor.dll", EntryPoint = "#16")]
private static extern Int16 LS_LoadConfig(
Int16 deviceId,
int variantFilePath,
int init);