将 C++ 类编组为结构

Posted

技术标签:

【中文标题】将 C++ 类编组为结构【英文标题】:Marshalling C++ class as structure 【发布时间】:2012-01-28 13:20:40 【问题描述】:

在 C++ 方面,我有以下类声明:

class MyClass 
    ...fields
    MyClass();
    ~MyClass(); ;

这个类用在dll里面的一些方法中。它传递给他们并从他们那里返回。 我如何在 C# 中表示它?我需要让它与 C++ dll 完全兼容。

这个类没有方法,只定义了无参数的构造函数和析构函数。任何想法如何编组它?不幸的是,我不能使用 C++\CLI,但我希望可以使用 C#。

我只有一个想法是将其表示为 C# 端的结构(不幸的是,我无法访问 C++ 代码)并尝试使用 Marshal.PtrToStructure。但我不确定它是否会起作用。

有什么建议吗?谢谢。

【问题讨论】:

所以这个类只用于它的字段?身份不重要?析构函数是做什么的? 可以用 Marshal.PtrToStructure 编组,用属性和构造函数定义类,析构函数:[StructLayout(LayoutKind.Sequential)] public class MyClass ...fields MyClass(); ~MyClass(); @pistipanko,非常感谢!我会试试的。 @svick 是的,它被视为结构。构造函数使用默认值初始化字段,析构函数将它们归零。 这是不可能的,C# 不能创建类的实例,也不能销毁它。非托管内存分配器、对象的大小以及构造函数和析构函数的地址是 C++ 编译器的实现细节,您无法在 C# 中获得这些细节。需要 C++/CLI 包装器。或者您可以通过 COM 公开 C++ 类。 【参考方案1】:

这在 C# 中是不可能的。它可以在托管和本机之间映射数据片段,但不能映射行为。 C++ 类固有地提供行为,因此不能直接编组。

您可以做的是将IntPtr 编组到本机对象并创建一个薄PInvoke 层,该层仅使用IntPtr 来访问该类型的数据片段。例如,假设我有以下 C++ 类。

class MyClass 
public:
  int Field;
;

我可以使用以下一组 C 函数来公开它的行为。

extern "C" 

  void* MyClass_Create() 
    return new MyClass();
  

  void MyClass_Delete(void* pValue) 
    delete reinterpret_cast<MyClass*>(pValue);
  

  int MyClass_GetField(void* pValue) 
    return reinterpret_cast<MyClass*>(pValue)->Field;
  

  void MyClass_SetField(void* pValue, int field) 
    reinterpret_cast<MyClass*>(pValue)->Field = field;
  

现在我已经通过 C 函数公开了它,我可以在它之上创建一个瘦托管包装器

internal static class NativeMethods 
  [DllImport("example.dll")]
  internal static extern IntPtr MyClass_Create();

  [DllImport("example.dll")]
  internal static extern void MyClass_Destroy(IntPtr ptr);

  [DllImport("example.dll")]
  internal static extern int MyClass_GetField(IntPtr prt);

  [DllImport("example.dll")]
  internal static extern void MyClass_SetField(IntPtr ptr, int field);



public class MyClass : IDisposable 
  private readonly IntPtr m_pointer;

  public int Field 
    get  return NativeMethods.MyClass_GetField(m_pointer); 
    set  NativeMethods.MyClass_SetField(m_pointer, value); 
  

  public MyClass() 
    m_pointer = NativeMethods.MyClass_Create();
  

  // Create from existing 
  public MyClass(IntPtr pointer) 
    m_pointer = pointer;
  

  public void Dispose() 
    NativeMethods.MyClass_Destroy(m_pointer);
  

【讨论】:

C++ DLL 的所有非纯虚拟和非模板方法都被导出,因为它们也必须从 C++ 本机代码中使用,因此,您当然可以使用调用从 C# 调用它们ThisCall 的约定。您不必将它们包装在 c 样式方法中。

以上是关于将 C++ 类编组为结构的主要内容,如果未能解决你的问题,请参考以下文章

直接将 C++ 浮点数组成员编组到 C#,无需复制

将结构数组从 C#(.NET Core) 传递到 C++(未管理)

将具有 int* 成员的 C++ 结构编组到 C#

将包含 int 和 int[] 的结构从 C# 编组到 C++

将复杂结构编组到 C#

传递结构时可以将指针编组到数组吗?