用于DOTNET的包装器用C ++ CLI BestWay编写的本机来传递结构?

问题描述 投票:2回答:3

然而,我正在为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值的形式接受这种类型的dotnet类型SDATUM,引用(sdatum%)和指针sdatum *就像那里有相应的本机函数一样。我需要转换/转换这些结构?

c# c++-cli native wrapper
3个回答
2
投票

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


2
投票

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

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

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

template <typename T>
ref class Handle
{
    boost::shared_ptr<T>* t;

    !Handle() 
    {
        if (t != nullptr)
        {
            delete t;
            t = nullptr;
        }
    }

    ~Handle() { this->!Handle(); }

public:
    Handle() : t(new boost::shared_ptr<T>((T*)0)) {}

    Handle(T* ptr) : t(new boost::shared_ptr<T>(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<T> operator->(Handle% h) { return *h.t; }

    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<Native::MyStruct> handle;
};

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


0
投票

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

//signature
void someFunction(SDATUM datum);

void someFunctionWrapper(SDATUM datum){
pin_ptr<SDATUM>  datum_pin=&datum;


//::SDATUM refers to the C-Type
someFunction(*(::SDATUM*)datum_pin);
}

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

© www.soinside.com 2019 - 2024. All rights reserved.