思路:C++ DLL中结构体的指针成员返回给C#时,其实返回的是一个地址。在C#中使用这个地址来定位在C++ DLL中分配的非托管的内存块,并把其复制到C#中托管的内存中,然后进行需要的操作。
下面以例子来说明:
我的需求是:用C++ DLL中的函数对压缩图片进行解码,并把解出的图片数据返回给C#。
在C++ DLL中定义的存储图片文件的结构是:
1 typedef struct _OGLTexHeader 2 { 3 int target; 4 int width; 5 int height; 6 int depth;
7 int imageSize; 8 unsigned byte *data; 9 } OGLTEXHEADER
在C#中使用四字节的int来接收这个地址(我用的是32位的OS),其代码是:
1 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 2 public struct OGLTEXHEADER 3 { 4 public int target; 5 public int width; 6 public int height; 7 public int depth; 8 public int imageSize; 9 public int data; 10 }
执行完C++ DLL后,结构体中的data成员指向了一个内存块,在返回给C#时,返回其地址。C#中接收data指向的内存块的代码是:
1 IntPtr texInfo = //从C++ DLL中返回的结构体的指针 2 OGLTEXHEADER header = (OGLTEXHEADER)Marshal.PtrToStructure(texInfo, typeof(OGLTEXHEADER)); 3 int width = header.width; 4 int height = heaer.height; 5 6 IntPtr dataAddress = (IntPtr)header.data; //获取地址 7 byte[] data = new byte[width * height * 4]; 8 //使用地址dataAddress来获取需要的内存块中的数据 9 Marshal.Copy(dataAddress, data, 0, width * height * 4);
这样就把指针指向的非托管的内存块中的数据拷贝到了托管的内存中。