关于VS2010中的C#:Marshal结构指针

Marshal structure pointer in VS2010

我必须从C#程序中调用C DLL。
我正在尝试使用PInvoke-在VS2005 \\\\ 2008中一切正常,但是在迁移到VS 2010之后,出现了以下异常:

PInvokeStackImbalance was detected
Message: A call to PInvoke function
'sampleFunc' has unbalanced the stack.
This is likely because the managed
PInvoke signature does not match the
unmanaged target signature. Check that
the calling convention and parameters
of the PInvoke signature match the
target unmanaged signature.

这是原始的C原型:

1
2
3
4
5
6
typedef struct {
    unsigned short field1;
    unsigned short field2;
} sInfo;

_declspec(dllexport) int sampleFunc(sInfo *info, char *txt);

这是C#代码:

1
2
3
4
5
6
7
8
9
10
[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进行了尝试,但是得到了相同的结果...

任何帮助将不胜感激,

谢谢大家!


以前很难知道它是如何工作的。 C声明不声明调用约定,除非使用/ Gz compile选项在C项目中覆盖,否则默认值为__cdecl。您必须告诉P / Invoke marshaller:

1
2
    [DllImport("sampleModule.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
    public static extern int sampleFunc(ref SInfo info, string txt);

这可能与打包结构有关。默认的Pack大小为8,因此它可能认为您有太多字节。尝试将Pack大小设置为2(16位对齐),看看是否有帮助:

1
[StructLayout(LayoutKind.Sequential, Pack=2)]

或者,您也可以像这样指定偏移量:

1
2
3
4
5
6
7
8
[StructLayout(LayoutKind.Explicit)]
public struct struct1
{
   [FieldOffset(0)]
   public ushort a;   // 2 bytes
   [FieldOffset(2)]
   public ushort b;    // 2 bytes
}

这里是package的很好的参考