我有两个几乎相同代码的例子。我可以从C#中检索一个数据,但我没有为另一个人提供正确的数据。他们在这里:
效果很好
C ++ Part:
__declspec(dllexport) void** enumerateDevices(int *dIsize){
Array<DeviceInfo> dIArray;
Framewoek::enumerateDevices(&dIArray);
*dIsize = dIArray.getSize();
DeviceInfo dP[255];
for (int i = 0; i < dIArray.getSize(); i++)
dP[i] = dIArray[i];
void* p = dP;
return &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];
for (int i = 0; i < devicesSize; i++)
arrayObjects[i] = new DeviceInfo(array[i]);
return arrayObjects;
}
不按预期工作
C ++ Part:
__declspec(dllexport) void** SensorInfo_getSupportedVideoModes(SensorInfo* si, int *dIsize){
const Array<VideoMode>& dIArray = si->getSupportedVideoModes();
*dIsize = dIArray.getSize();
VideoMode dP[255];
for (int i = 0; i < dIArray.getSize(); i++)
dP[i] = dIArray[i];
void* p = dP;
return &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];
for (int i = 0; i < arraySize; i++)
arrayObjects[i] = new VideoMode(array[i]);
return arrayObjects;
}
正如你所看到的,我只想要对象的指针。但第二个例子给了我无效的指针。我不知道为什么。这是一个很大的库我试图创建一个.net包装器,除了这个功能外,一切都很好。
注意:数组&lt;&gt;是一个模板类,包含两个字段,大小和数组以及几种方法。
*编辑:我知道这是一个局部变量(甚至VS给我警告),但是为什么第一个有效呢?!
*编辑2:
我使用@JefferyThomas答案解决了第二个问题。它现在看起来像这样,没有问题: C ++方面:
__declspec(dllexport) void* SensorInfo_getSupportedVideoModes(SensorInfo* si, int *dIsize){
const Array<VideoMode>& dIArray = si->getSupportedVideoModes();
*dIsize = dIArray.getSize();
VideoMode** dP = new VideoMode*[255];
for (int i = 0; i < dIArray.getSize(); i++)
dP[i] = const_cast<VideoMode*>(&(dIArray[i]));
return dP;
}
__declspec(dllexport) void SensorInfo_destroyVideoModesArray(VideoMode** dP){
delete[] dP;
}
目前我在改变我的第一个功能时遇到了问题,就像@JefferyThomas建议的那样。我们来看看代码然后我会告诉你问题在哪里。 C ++方:
__declspec(dllexport) void** Framework_enumerateDevices(int *dIsize){
Array<DeviceInfo> dIArray;
Framework::enumerateDevices(&dIArray);
*dIsize = dIArray.getSize();
DeviceInfo* dP = new DeviceInfo[255];
for (int i = 0; i < dIArray.getSize(); i++)
dP[i] = dIArray[i];
void** p = new void*;
*p = dP;
return 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];
for (int i = 0; i < devicesSize; i++)
arrayObjects[i] = new DeviceInfo(array[i]);
Framework_destroyDevicesArray(arrayPointer);
return arrayObjects;
}
问题:
目前我认为这是因为Array&lt;&gt;处理和摧毁一切的阶级。
编辑3:我找到了第一个问题的解决方案。谢谢杰夫让我走上了正确的方向。
答案 0 :(得分:5)
这里的问题是你要返回一个堆栈变量。这是一个坏主意。
函数返回时,VideoMode dP[255];
和DeviceInfo dP[255];
都被销毁。恰好在第一种情况下,记忆没有被覆盖,在第二种情况下你不是那么幸运。
过去我从堆中分配并提供了第二个releaseXXXX方法来释放内存。
__declspec(dllexport) void** enumerateDevices(int *dIsize){
Array<DeviceInfo> dIArray;
Framewoek::enumerateDevices(&dIArray);
*dIsize = dIArray.getSize();
DeviceInfo *dP = new DeviceInfo[255];
for (int i = 0; i < dIArray.getSize(); i++)
dP[i] = dIArray[i];
void** p = new void*;
*p = dP;
return 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];
for (int i = 0; i < devicesSize; i++)
arrayObjects[i] = new DeviceInfo(array[i]);
releaseEnumerateDevices(arrayPointer);
return arrayObjects;
}