VS2010中的元帅结构指针

Posted

技术标签:

【中文标题】VS2010中的元帅结构指针【英文标题】:Marshal structure pointer in VS2010 【发布时间】:2010-06-08 16:35:18 【问题描述】:

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

任何帮助将不胜感激,

谢谢大家!

【问题讨论】:

【参考方案1】:

很难看出这在以前是如何发挥作用的。 C++ 声明不声明调用约定,默认为 __cdecl,除非在 C++ 项目中使用 /Gz 编译选项覆盖。你必须告诉 P/Invoke 编组器:

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

【讨论】:

【参考方案2】:

这可能与你如何打包结构有关。默认的包大小是 8,所以它可能认为你有太多字节。尝试将 Pack 大小设置为 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是一个很好的打包参考

【讨论】:

以上是关于VS2010中的元帅结构指针的主要内容,如果未能解决你的问题,请参考以下文章

具有对 C# 的整数引用的元帅结构

C语言如何给指针分配内存?

通过指针访问结构中的值? (C++)

层次结构中的成员函数指针

VS2012 用RasDial结果返回 "检测到一个不正确的结构大小" VS2010正常,怎解?!

返回指向本地结构的指针