我认为我很接近,我敢打赌解决方案是愚蠢的。
我有一个C ++本机DLL,我定义了以下函数:
DllExport bool __stdcall Open(const char* filePath, int *numFrames, void** data);
{
//creates the list of arrays here... don't worry, lifetime is managed somewhere else
//foreach item of the list:
{
BYTE* pByte = GetArray(i);
//here's where my problem lives
*(data + i * sizeofarray) = pByte;
}
*numFrames = total number of items in the list
return true;
}
基本上,给定文件路径,此函数会创建一个字节数组列表(BYTE *),并应通过数据参数返回指针列表。每个指向不同的字节数组。
我想从C#传递一个IntPtr数组,并且能够按顺序编组每个单独的数组。这是我正在使用的代码:
[DllImport("mydll.dll",EntryPoint = "Open")]
private static extern bool MyOpen(
string filePath, out int numFrames, out IntPtr[] ptr);
internal static bool Open(
string filePath, out int numFrames, out Bitmap[] images)
{
var ptrList = new IntPtr[512];
MyOpen(filePath, out numFrames, out ptrList);
images = new Bitmap[numFrames];
var len = 100; //for sake of simplicity
for (int i=0; i<numFrames;i++)
{
var buffer = new byte[len];
Marshal.Copy(ptrList[i], buffer, 0, len);
images[i] = CreateBitmapFromBuffer(buffer, height, width);
}
return true;
}
我的C ++代码存在问题。当我指定*(data + i * sizeofarray)= pByte;它破坏了指针数组......我做错了什么?
更新: 刚开始创建一个新的解决方案来隔离概念,已经发现了一些非常奇怪的东西。看看:
C#代码
class Program
{
[DllImport("ArrayProvider.dll")]
private static extern bool Open(out int n, ref IntPtr[] ptr);
static void Main(string[] args)
{
int n;
var pList = new IntPtr[10];
Program.Open(out n, ref pList);
foreach (var p in pList)
{
Debug.WriteLine(p.ToInt32().ToString("X"));
}
}
}
C ++代码
#include "stdafx.h"
#define DllExport __declspec( dllexport )
extern "C" {
DllExport bool __stdcall Open(int *n, void** data)
{
return true;
}
}
在调用本机代码之前,pList有10个IntPtr.Zero元素。从本机调用返回后,它只有一个......出错了......如果我用BYTE替换void **也会发生这种情况**
答案 0 :(得分:4)
在接收非托管数组时,运行时将无法确定数组的长度,您需要将MarshalAsAttribute与SizeParamIndex字段结合使用以指定数组的长度。有一个例子here。
您也不需要将方法签名定义为数组的ref IntPtr [],使用InAttribute和OutAttribute。
E.x:
private static extern bool Open(out int n,[MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] [In,Out] IntPtr[] ptr);
答案 1 :(得分:2)
尝试更改
out IntPtr[] ptr
到
ref IntPtr[] ptr
2之间存在细微差别。
更新
尝试:
data[i] = pByte
答案 2 :(得分:2)
如何在数据为void*
类型
//you cannot do such pointer arithmetic on void* type.
*(data + i * sizeofarray) = pByte;
将其更改为char*
或int*
。
此外,请使用ref
代替out
作为最后一个参数:
MyOpen(filePath, out numFrames, out ptrList); //wrong
这已得到纠正:
MyOpen(filePath, out numFrames, ref ptrList); //correct
您必须相应地更改方法签名。
答案 3 :(得分:1)
我想你想要
*(data + i * sizeofarray) = pByte;
更像是
data[i] = pByte;
因此,您将在data
所指向的任何指针中存储指针数组。