VS2010中的元帅结构指针

时间:2010-06-08 16:35:18

标签: c# visual-studio-2010 pinvoke marshalling

我必须从我的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,但得到的结果相同......

任何帮助将不胜感激,

谢谢大家!

2 个答案:

答案 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是关于打包的好参考