c++ - Contradictory behavior in C to C# array marshalling -
c++ - Contradictory behavior in C to C# array marshalling -
i have 2 illustration same code. can retrieve info of 1 c# , failed have right info other. here are:
works good
c++ part:
__declspec(dllexport) void** enumeratedevices(int *disize){ array<deviceinfo> diarray; framewoek::enumeratedevices(&diarray); *disize = diarray.getsize(); deviceinfo dp[255]; (int = 0; < diarray.getsize(); i++) dp[i] = diarray[i]; void* p = dp; homecoming &p; }
c# part:
[dllimport("wrapper.dll")] static extern intptr enumeratedevices(out int devicessize); public static deviceinfo[] enumeratedevices() { int devicessize; intptr arraypointer = enumeratedevices(out devicessize); intptr[] array = new intptr[devicessize]; marshal.copy(arraypointer, array, 0, devicessize); deviceinfo[] arrayobjects = new deviceinfo[devicessize]; (int = 0; < devicessize; i++) arrayobjects[i] = new deviceinfo(array[i]); homecoming arrayobjects; }
don't works expected
c++ part:
__declspec(dllexport) void** sensorinfo_getsupportedvideomodes(sensorinfo* si, int *disize){ const array<videomode>& diarray = si->getsupportedvideomodes(); *disize = diarray.getsize(); videomode dp[255]; (int = 0; < diarray.getsize(); i++) dp[i] = diarray[i]; void* p = dp; homecoming &p; }
c# part:
[dllimport("wrapper.dll")] static extern intptr sensorinfo_getsupportedvideomodes(intptr objecthandler, out int arraysize); public videomode[] getsupportedvideomodes() { int arraysize; intptr arraypointer = sensorinfo_getsupportedvideomodes(this.handle, out arraysize); intptr[] array = new intptr[arraysize]; marshal.copy(arraypointer, array, 0, arraysize); videomode[] arrayobjects = new videomode[arraysize]; (int = 0; < arraysize; i++) arrayobjects[i] = new videomode(array[i]); homecoming arrayobjects; }
as can see want pointer of objects. sec illustration give me invalid pointers. don't know why. big library trying create .net wrapper , works except function.
note: array<> template class containing 2 field, size , array , couple of methods.
*edit: know local variable (even vs give me warning), why first 1 works then?!
*edit 2:
i solved sec problem using @jefferythomas answer. , has no problem: c++ side:
__declspec(dllexport) void* sensorinfo_getsupportedvideomodes(sensorinfo* si, int *disize){ const array<videomode>& diarray = si->getsupportedvideomodes(); *disize = diarray.getsize(); videomode** dp = new videomode*[255]; (int = 0; < diarray.getsize(); i++) dp[i] = const_cast<videomode*>(&(diarray[i])); homecoming dp; } __declspec(dllexport) void sensorinfo_destroyvideomodesarray(videomode** dp){ delete[] dp; }
currently have problem changing first function @jefferythomas suggested. let's take code tell u problem. c++ side:
__declspec(dllexport) void** framework_enumeratedevices(int *disize){ array<deviceinfo> diarray; framework::enumeratedevices(&diarray); *disize = diarray.getsize(); deviceinfo* dp = new deviceinfo[255]; (int = 0; < diarray.getsize(); i++) dp[i] = diarray[i]; void** p = new void*; *p = dp; homecoming p; } __declspec(dllexport) void framework_destroydevicesarray(void **p){ deviceinfo *dp = (deviceinfo *)*p; //delete [] dp; delete p; }
c# side:
[dllimport("wrapper.dll")] static extern intptr framework_enumeratedevices(out int devicessize); [dllimport("wrapper.dll")] static extern intptr framework_destroydevicesarray(intptr arraypointer); public static deviceinfo[] enumeratedevices() { int devicessize; intptr arraypointer = framework_enumeratedevices(out devicessize); intptr[] array = new intptr[devicessize]; marshal.copy(arraypointer, array, 0, devicessize); deviceinfo[] arrayobjects = new deviceinfo[devicessize]; (int = 0; < devicessize; i++) arrayobjects[i] = new deviceinfo(array[i]); framework_destroydevicesarray(arraypointer); homecoming arrayobjects; }
and problems:
i cant maintain "delete [] dp" in destroy function. not delete array, delete info well. i can have first pointer (first item of array) correctly. other pointers incorrect. don't know why. tried changing deviceinfo array of pointers instead of array of object straight (like sec function) , still no success.currently think because of array<> class dispose , destroy everything.
edit 3: found solution first problem my-self. jeff putting me in right direction.
the problem here returning stack variable. bad idea.
both videomode dp[255];
, deviceinfo dp[255];
destroyed when function returns. happens memory has not been overwritten in first case, not lucky in sec case.
in past i've allocated heap , provided sec releasexxxx method free memory up.
__declspec(dllexport) void** enumeratedevices(int *disize){ array<deviceinfo> diarray; framewoek::enumeratedevices(&diarray); *disize = diarray.getsize(); deviceinfo *dp = new deviceinfo[255]; (int = 0; < diarray.getsize(); i++) dp[i] = diarray[i]; void** p = new void*; *p = dp; homecoming p; } __declspec(dllexport) void releaseenumeratedevices(void **p){ deviceinfo *dp = (deviceinfo *)*p; delete [] dp; delete p; }
c#
[dllimport("wrapper.dll")] static extern intptr enumeratedevices(out int devicessize); static extern void releaseenumeratedevices(intptr arraypointer); public static deviceinfo[] enumeratedevices() { int devicessize; intptr arraypointer = enumeratedevices(out devicessize); intptr[] array = new intptr[devicessize]; marshal.copy(arraypointer, array, 0, devicessize); deviceinfo[] arrayobjects = new deviceinfo[devicessize]; (int = 0; < devicessize; i++) arrayobjects[i] = new deviceinfo(array[i]); releaseenumeratedevices(arraypointer); homecoming arrayobjects; }
c# c++ pinvoke marshalling
Comments
Post a Comment