c# 平台调用复杂结构体 非托管 DLL
C结构体定义:
typedef struct _IntImage
{
int height; //图像的高
int width; //宽
int **data; //data:图像二维指针,用法为char** data = new char*[height];
//for (int i=0; i< height; i++)
//data[i] = &(buf[i*width]);
int *buf; //buf:图像数据区,按行存储,buf[0] —buf[width*height]
int variance;
int label;
int bFlip;
}IntImage;
我在C#里定义结构体为:
[DllImport("FaceLib.dll", EntryPoint = "saveIntImage", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int saveIntImage(string filename, ref IntImage intImg);
[StructLayout(LayoutKind.Sequential)]
public unsafe struct IntImage
{
[MarshalAs(UnmanagedType.I4)]
public int height;
[MarshalAs(UnmanagedType.I4)]
public int width;
[MarshalAs(UnmanagedType.ByValArray)]
public IntPtr[] data;
[MarshalAs(UnmanagedType.SysUInt)]
public IntPtr buf;
[MarshalAs(UnmanagedType.I4)]
public int variance;
[MarshalAs(UnmanagedType.I4)]
public int label;
[MarshalAs(UnmanagedType.I4)]
public int bFlip;
}
不知道定义的是否正确?关键是int** data和int* buf两项的定义我不太清除怎么处理。我用了IntPtr buf指向图像存储的缓冲区,IntPtr [] data指向每行数据的首地址。
C里面的调用函数:
int setIntImage(IntImage* img, int value);
我在c#里面由一个由Bitmap图像转换为上述格式定义的图像的函数:
public static void Convert_to_IntImage2(ref IntImage intImage, Bitmap bmp)
{
int i = 0, j = 0, m = 0, n = 0, k = 0;
intImage.height = bmp.Height;
intImage.width = bmp.Width;
Color c = new Color();
int size = (intImage.width) * (intImage.height);
byte[] buffer = new byte[size];
for (i = 0; i < bmp.Width; i++)
for (j = 0; j < bmp.Height; j++)
{
c = bmp.GetPixel(i, j);
buffer[m] = (byte)((39 * c.R + 11 * c.G + 50 * c.B) / 100);
m++;
}
intImage.buf = Marshal.AllocHGlobal(size);
Marshal.Copy(buffer,0,intImage.buf,size);
intImage.data=new IntPtr[bmp.Width];
for (i = 0; i < bmp.Width; i++)
{
intImage.data[i]= Marshal.UnsafeAddrOfPinnedArrayElement(buffer,i*bmp.Height); //获取指定数组指定索引处的地址
}
}
}
在该转换函数里面,不知道结构体中的buf和data如何分配空间和赋值?才能使得给c里面的函数传递参数?出现“
尝试读取或写入受保护的内存,这通常指示其他的内存已破坏”。
请问如何平台调用来传递这些复杂的结构体?
------解决方案--------------------
你的代码有两个问题:
1、intImage.data=new IntPtr[bmp.Width]; 这个要改成 intImage.data=Marshal.AllocHGlobal(bmp.Width);
2、intImintImage.bufage.data[i]= Marshal.UnsafeAddrOfPinnedArrayElement(buffer,i*bmp.Height);
Marshal.UnsafeAddrOfPinnedArrayElement 这个方法要求:该数组在被传递给此方法之前必须使用 GCHandle 固定。
buffer 这个数组! 要用 GCHandle.Alloc 这个方法