0

我有一个 c++ dll,它有一些外部函数。它看起来像这样

//C++ Code
void GetData(byte * pData)
{
  byte a[] = {3,2,1};
  pData = a;
}

我已经在 C# 端使用此代码来获取数据:

//C# Code
[DllImport(UnmanagedDLLAddress)]
public static extern void GetData(ref IntPtr pData);

//and use it like
IntPtr pointer = IntPtr.Zero;
GetData(ref pointer);
byte[] data = new byte[3] // <===== think we know size
Marshal.Copy(pointer,data ,0,3);

但总是“指针”为零,所以 Marshal.Copy 在我做错的地方抛出空异常?泰

4

2 回答 2

5

首先,您的 C++ 代码将数组放入堆栈。您需要以其他方式分配它,文档从这里开始:http: //msdn.microsoft.com/en-us/library/aa366533%28VS.85%29.aspx

其次,pData 是一个“正常”值参数,实际上是一个局部变量。您分配给它,然后当函数返回时它会被遗忘。如果您希望它是“输出参数”返回一个值,您需要它是对指针的引用或指向指针的指针。如果要将数组内容实际复制到 pData 指向的缓冲区,则需要使用memcpy函数 from #include <cstring>

于 2012-11-01T08:55:00.797 回答
3

实际上,就像 hyde 所说的那样,使用 pData 作为“out”参数。因为它显然是引用类型而不是值类型,所以被调用的方法应该注意内存分配。我仅将“ref”用于值类型,例如整数 - 例如从非托管方法获取数组的长度。

这种方式对我来说很好,此外,我使用“cdecl”调用约定。

IntPtr aNewIntArray;
uint aNewIntArrayCount = 0;

NativeMethods.getEntityFieldIntArray(out aNewIntArray, ref aNewIntArrayCount);

int[] aNewIntArrayResult = new int[aNewIntArrayCount];
Marshal.Copy(aNewIntArray, aNewIntArrayResult, 0, (int)aNewIntArrayCount);

方法声明:

[DllImport(SettingsManager.PathToDLL, EntryPoint = "getEntityFieldIntArray", CallingConvention = CallingConvention.Cdecl)]
public static extern ErrorCode getEntityFieldIntArray(out IntPtr aNewIntArray, ref UInt32 aNewIntArrayCount);
于 2012-11-01T10:00:59.447 回答