Search code examples
visual-c++dllc++-cliinteropmixed-mode

Returning a vector from a native C++ dll into a managed C++/CLI dll


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.


Solution

  • 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;
        }
    };