用于DOTNET的包装器用C ++ CLI编写的本机BestWay通过strutures?

然而,我正在为C ++ CLI编写一个包装器,为我们的应用程序提供一些新的部件(用C#编写),可以保存并轻松访问旧的本机库。 因此我需要将一些结构从c#传递给c ++。 这些结构在C ++ Cli(dotnet)和C ++中定义。

例:

\\C+++ typedef struct { INFO16 jahr ; INFO8 monat ; INFO8 tag ; INFO8 stunde ; INFO8 minute ; } SDATUM; \\c++ cli [StructLayout(LayoutKind::Explicit)] public value struct SDATUM { public: [FieldOffset(0)] UInt16 jahr; [FieldOffset(2)] Byte monat; [FieldOffset(3)] Byte tag; [FieldOffset(4)] Byte stunde; [FieldOffset(5)] Byte minute; }; 

现在我在C ++ cli中提供了一些函数,它们以pass by值的forms接受这种类型的dotnet类型SDATUM,引用(sdatum%)和指针sdatum *就像那里有相应的本机函数一样。 转换/转换这些结构需要什么?

我不会做任何演员。 而是编写一个包含SDATUM的ref类。 公开设置基础SDATUM的方法和属性。 从C#端开始,使用这个ref类(或者更好的是,创建一个这个类实现的接口,让C#端与接口一起工作)。 在C ++ / CLI中,您可以访问本机版本的类,并根据需要将其传递给本机方法。

请注意,C ++和.NET的复制语义根本不同:.NET使用垃圾收集共享引用,C ++使用复制构造函数。

C ++ / CLI不允许您将本机对象用作托管类的成员,您必须使用指针。 所以我将使用boost共享指针来模仿.NET语义。

这可以抽象出来。 这是我用来向.NET世界公开C ++类的类:

 template  ref class Handle { boost::shared_ptr* t; !Handle() { if (t != nullptr) { delete t; t = nullptr; } } ~Handle() { this->!Handle(); } public: Handle() : t(new boost::shared_ptr((T*)0)) {} Handle(T* ptr) : t(new boost::shared_ptr(ptr)) {} Handle% operator=(T* p) { if (p != t->get()) t->reset(p); return *this; } T* get() { return t->get(); } // Remember that operators are static in .NET static boost::shared_ptr operator->(Handle% h) { return *ht; } T& reference() { return *t->get(); } T const& const_reference() { return *t->get(); } }; 

然后你可以使用:

 ref class MyStruct { public: // Expose your .NET interface here, make it use the handle variable. internal: Handle handle; }; 

并在C ++代码中使用handle成员变量,没有任何限制。 它不会在.NET中显示。 然后,您可以以.NET方式公开属性,访问器,运算符等。

我找到了另一个非常简单,简单且不需要复制数据的解决方案。 您可以通过这种方式调用需要C SDATUM的本机函数:

 //signature void someFunction(SDATUM datum); void someFunctionWrapper(SDATUM datum){ pin_ptr datum_pin=&datum; //::SDATUM refers to the C-Type someFunction(*(::SDATUM*)datum_pin); } 

我测试了它,它的工作原理是因为两个SDATUM结构具有相同的位结构。 因为我只调用短的本机函数,所以我认为碎片是没有问题的。