将 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#(.NET Core) 传递到 C++(未管理)