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 这个方法