C ++函数原型是;
/************************************************************************
parameters[in]:
void *handle,
char *jpeg_buf,
jpeg_buf jpeg_buf
parameters[out]:
listSize: result list size, max <= 1000;
list: result
************************************************************************/
int getInfo(void *handle,unsigned char* jpeg_buf, unsigned int jpeg_len, int& list_size, Info *info_list);
C ++类型;
typedef struct
{
int dot_x;
int dot_y;
} Attr;
typedef struct
{
int left;
int top;
int right;
int bottom;
} Rect_S;
typedef struct
{
Rect_S rect;
Attr attr;
} Info;
C#DLL导入;
[DllImport("sample.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern int getInfo(IntPtr handle, byte[] jpeg_buf, uint jpeg_len, out int listSize, out IntPtr List);
结构在C#中;
internal struct Attr
{
public int dot_x;
public int dot_y;
};
internal struct Rect_S
{
public int left;
public int top;
public int right;
public int bottom;
};
internal struct Info
{
public Rect_S rect;
public Attr attr;
};
C#GetInfo函数;
public Info[] getInfo(byte[] scan0)
{
Info[] retVal = null;
IntPtr structPtr = IntPtr.Zero;
int size;
int ret = EFEngine.getInfo(this.Engine, scan0, (uint)scan0.Length, out size, out structPtr);
if (ret >= 0)
{
retVal = new Info[size];
int sizePointerInfo = Marshal.SizeOf(new EFaceInfo());
for (int i = 0; i < size; i++)
{
retVal[i] = (Info)Marshal.PtrToStructure(new IntPtr(structPtr.ToInt64() + (i * sizePointerInfo)), typeof(Info));
}
}
return retVal;
}
我收到错误“附加信息:尝试读取或写入受保护的内存。这通常表示其他内存已损坏。”当调用“Marshal.PtrToStructure”时。
有什么不对?
C ++测试代码;
int getInfoTest(void *handle, unsigned char* jpeg_buf, unsigned int jpeg_len, int& list_size, FaceInfo *face_rect_list)
{
int nSizeNum = 0;
Info* List = new Info[32];
int nRet = getInfo(handle, jpeg_buf, jpeg_len, nSizeNum, List);
if (nRet != 0)
{
fprintf(stderr, "error: getInfo failed\n");
}
delete[] List;
delete[] jpeg_buf;
return nRet;
}
答案 0 :(得分:0)
正如您在上一个问题中所发生的那样,问题中提供的信息不完整。当我试图向你解释时,C ++原型并没有完全指定C ++函数的语义。正如我之前向您解释的那样,您应该包含那些语义,或至少一些示例C ++代码来调用该函数。
但是,问题很可能是最终参数。期望调用者分配内存并将其地址传递给函数。它看起来非常像这个最终参数实际上是一个数组。根据这个假设,p / invoke声明应该是:
[DllImport("sample.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern int getInfo(IntPtr handle, byte[] jpeg_buf,
uint jpeg_len, ref int listSize, [Out] Info[] List);
您可以像这样调用函数:
int listSize = ...; // you have to somehow work out what to put here
Info[] List = new Info[listSize];
int retval = getInfo(handle, jpeg_buf, jpeg_len, ref listSize, List);
// check retval
当然,由于列表大小参数是通过引用传递的,这表明该函数可以告诉您需要多大的数组。所以呼叫序列也许应该是:
int listSize = 0;
int retval = getInfo(handle, jpeg_buf, jpeg_len, ref listSize, null);
// check retval
Info[] List = new Info[listSize];
int retval = getInfo(handle, jpeg_buf, jpeg_len, ref listSize, List);
// check retval