質問

I'm writing a CLI/C++ wrapper around a native C++ dll which can not be changed. One of the functions of the native DLL returns a vector of unmanaged objects. What would be the best way to wrap this vector in my CLI wrapper? The CLI wrapper is going to be used by a C# application.

class __declspec(dllexport) Instrument
{
  public:
        Instrument();
        ~Instrument();
        string _type;
        unsigned int _depth;
}

The native DLL has the function getInstruments() which is what I'm trying to wrap

 class __declspec(dllexport) InstrumentList
   {
       InstrumentList();
       ~InstrumentList();
       vector<Instrument*> getInstruments();
   }

So I need to wrap the instrument class in a managed class and wrap InstrumentList class in a managed class. I have the Instrument class wrapped, but need to convert the vector returned by getInstruments() into something equivalent that the CLI wrapper for InstrumentList can return.

役に立ちましたか?

解決

Unless you want to delay the marshaling of Instrument::_type until its managed facade is accessed, this should get you started:

public ref class InstrumentM
{
    String^ _type;
    unsigned _depth;

internal:
    explicit InstrumentM(Instrument const& i)
      : _type(gcnew String(i._type.c_str())),
        _depth(i._depth)
    { }

public:
    property String^ Type { String^ get() { return _type; } }
    property unsigned Depth { unsigned get() { return _depth; } }
};

public ref class InstrumentListM
{
    InstrumentList* _list;

public:
    InstrumentListM() : _list(new InstrumentList()) { }
    ~InstrumentListM() { this->!InstrumentListM(); }
    !InstrumentListM()
    {
        delete _list;
        _list = nullptr;
    }

    array<InstrumentM^>^ GetInstruments()
    {
        if (!_list)
            throw gcnew ObjectDisposedException(L"_list");

        vector<Instrument*> const& v = _list->getInstruments();
        array<InstrumentM^>^ ret = gcnew array<InstrumentM^>(v.size());
        for (int i = 0, i_max = ret->Length; i != i_max; ++i)
            if (v[i])
                ret[i] = gcnew InstrumentM(*v[i])
        return ret;
    }
};

他のヒント

You may not want to wrap the InstrumentList at all.

Just use one of the stock .NET collections (which you can access from C++/CLI) and make a collection of your Instrument wrappers. I've been using ObservableCollection since I want to databind to my collections.

Example:

public ref class MyManagedType
{
    public:
        MyManagedType(MyNativeType* pObject) { m_pObject = pObject };

    private:
        MyNativeType* m_pObject;
}

Then create the managed collection like this:

ObservableCollection<MyManagedType^>^ managedCollection = gcnew ObservableCollection<MyManagedType^>();

Finally, add objects to the collection:

managedCollection->Add(gcnew MyManagedType(pNativeObject));

It's a bit of effort to keep the native and managed collections in sync, but it works well.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top