1

I have a C++\CLI wrapper to a C++ API of a commercial program. A certain wrapper function looks like this:

int ReleaseObject(WDataObject^ object) {
    return (m_api->ReleaseObject(object->m_object));
};

On the previous version of the API, the C++ side was:

m_api->ReleaseObject(const api:DataObject *object)

And in the current API version the function has changed to:

m_api->ReleaseObject(const api:DataObject *&object)

My knowledge on C++\CLI is none and my C++ knowledge is very basic, and I have no clue on how to modify the wrapper function to make it compile.

I'd like to know how to modify the wrapper c++\CLI function to pass the object by reference according to what the C++ API expects.

EDIT:

Error when compiling:

Error   3   error C2664: 'int api::Api::ReleaseObject(api::DataObject *&)' : cannot convert argument 1 from 'api::DataObject *' to 'api::DataObject *&' ...\pf_api_test - 15.2.2\libs\digapiwrapper15.1_64bit\digApiWrapper.h   851 1   digApiWrapper

EDIT 2:

    [SerializableAttribute]
        public ref class WDataObject {
            public:

            api::DataObject* m_object;

            WApi^ t_api;

            String^  Name;
            int  Class;
            String^ key;

            WDataObject(api::DataObject* obj) { m_object = obj; };

            ~WDataObject();

 /*HERE GOES ALL THE FUNCTIONS WHICH I'M NOT SURE IF THEY ARE RELEVANT*/
    }
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
Santi Peñate-Vera
  • 1,053
  • 4
  • 33
  • 68

2 Answers2

1

You have to pass a pointer to your m_object variable. You did not quote the compiler error message, but it is somewhat guessable, it will not allow you to pass a pointer to a member of a managed class. That tends to end very poorly when the garbage collector moves the object while the native code is executing.

You must create a stable pointer reference, the simplest way to do so is by copying the pointer to a local variable. Like this:

int ReleaseObject(WDataObject^ object) {
    api:DataObject* arg = object->m_object;
    int retval = m_api->ReleaseObject(&arg);
    object->m_object = arg;
    return retval;
}

Which also fixes a likely bug in your original code, you probably should have set m_object to NULL yourself so you don't release it again. Be sure to check for NULL in your destructor and finalizer and don't call ReleaseObject() again.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Thanks for the reply, but it doesn't work yet. on [api:DataObject* arg = object->m_object;] the error is [ an ordinary pointer to a C++/CLI ref class or interface class is not allowed] and in [int retval = m_api->ReleaseObject(&arg);] the error is [initial value of reference to non-const must be an lvalue]. I believe it has to do with the fact that * is for C++ and not for C++\CLI. – Santi Peñate-Vera May 27 '15 at 08:18
0

After a lot of trial and error, I got the answer of Hans Passant to work:

int ReleaseObject(WDataObject^ object) {
    //Before: return (m_api->ReleaseObject(object->m_object));
    api::DataObject* obj = object->m_object;
    int val = m_api->ReleaseObject(obj);
    object->m_object = obj;
    return val;
};

I'll give his answer as correct.

Santi Peñate-Vera
  • 1,053
  • 4
  • 33
  • 68