我必须从我的C#程序中调用C ++ DLL。 我正在尝试使用PInvoke - 在VS2005 \ 2008中一切正常,但在迁移到VS 2010后,我得到了这个例外:
检测到PInvokeStackImbalance 消息:调用PInvoke函数 'sampleFunc'使堆栈失衡。 这可能是因为托管 PInvoke签名与 非托管目标签名。检查一下 调用约定和参数 PInvoke签名的匹配 目标非托管签名。
这是原始的C ++原型:
typedef struct {
unsigned short field1;
unsigned short field2;
} sInfo;
_declspec(dllexport) int sampleFunc(sInfo *info, char *txt);
这是C#代码:
[StructLayout(LayoutKind.Sequential)]
struct SInfo
{
//[MarshalAs(UnmanagedType.U1)] //also tried with the MarshalAs attr. Didn't help.
public ushort field1;
//[MarshalAs(UnmanagedType.U1)]
public ushort field2;
};
[DllImport("sampleModule.dll", CharSet=CharSet.Ansi)]
public static extern int sampleFunc(ref SInfo info, [MarshalAs(UnmanagedType.LPStr)] string txt);
我也尝试使用IntPtr而不是ref SInfo,但得到的结果相同......
任何帮助将不胜感激,
谢谢大家!
答案 0 :(得分:2)
很难看出它之前是如何起作用的。 C ++声明不声明调用约定,默认为__cdecl,除非在C ++项目中使用/ Gz编译选项覆盖。你必须告诉P / Invoke marshaller:
[DllImport("sampleModule.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern int sampleFunc(ref SInfo info, string txt);
答案 1 :(得分:1)
这可能与你如何打包结构有关。默认的包大小是8,所以它可能认为你有太多的字节。尝试将包大小设置为2(16位对齐)并查看是否有帮助:
[StructLayout(LayoutKind.Sequential, Pack=2)]
或者,您可以指定偏移量:
[StructLayout(LayoutKind.Explicit)]
public struct struct1
{
[FieldOffset(0)]
public ushort a; // 2 bytes
[FieldOffset(2)]
public ushort b; // 2 bytes
}
Here是关于打包的好参考