Wrapper for DOTNET to native written in C++ CLI BestWay to pass structures?

China☆狼群 提交于 2019-12-06 08:32:07

I wouldn't do any casting. Rather, write a ref class that contains an SDATUM. Expose methods and properties that set the underlying SDATUM. From the C# side, work with this ref class (or better yet, create an interface that this class implements and have the C# side work with the interface). In C++/CLI you can access the native version of class and pass it to native methods as needed.

Beware that copy semantics of C++ and .NET fundamentally differ: .NET use garbage collected shared references and C++ use copy constructors.

C++/CLI won't let you use native objects as members of managed classes, you'll have to use pointers. So I'll use boost shared pointers to mimick the .NET semantics.

This can be abstracted away. Here is the class I use to expose C++ classes to the .NET world:

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(); }
};

Then you can use:

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

internal:
    Handle<Native::MyStruct> handle;
};

and use the handle member variable in your C++ code with no restrictions. It will not be shown in .NET. Then you can expose properties, accessors, operators, etc. in the .NET fashion.

I found another solution which is very easy, short and does not need copying data. You could call native functions which want a C SDATUM in this way:

//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);
}

I tested it and it works because both SDATUM Structs have the same bit structure. Because I only call short native functions I think fragmentation is no problem.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!