C# 调用c++报错可能性分析
1.在调用之前,可以用工具(Dependency)检测下c++库所依赖的文件,看是否有错误。如果有错误,请先下补充所需运行环境。
2.如果c++ 函数 形参需要C#传入结构体,可如下:
1 [StructLayout(LayoutKind.Sequential)]//作用:按顺序排列,防止C#编译器打乱,起到与C++那边保持一致。 2 public struct mwEdgeFileHeader 3 { 4 uint type; //切面数据文件头类型固定为0xFF0000F1 5 uint version; //初始版本为1,更改后依次提升 6 uint length; //头信息的长度,字节为单位,此为20 7 uint content_offset; //存储的数据起始在文件中的偏移量,此为20+1 8 uint content_length; //存储的数据长度 9 };
如果 上面结构体中有数组,C#定义结构体,必须指明结构体的长度。注意:c++端必须指明数组长度,不可使用动态长度(目前我测试的时候是这样子,可能不全,希望有遇到能动态的朋友,私信我,大家一起探讨下,谢谢!)
c++代码:
1 typedef struct _edgefile{ 2 char name[512]; //此数据对应图像文件的名字 3 uint32_t width; //图像的宽度 4 uint32_t height; //图像的高度 5 double center_x; //瞳孔X轴方向位置 6 double center_y; //瞳孔Y轴方向位置 7 double pupils_dia; //瞳孔的直径 8 double coef[9]; //侧面图像校正矩阵 9 double ratio[2]; //侧面图像和正面图像的像素长 10 uint32_t info_count; //所包含的边缘信息的数量 11 }mwEdgeContents;
C#转换代码:
1 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 2 public struct mwEdgeContents 3 { 4 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)] 5 public char[] name; //此数据对应图像文件的名字 6 public UInt32 width; //图像的宽度 7 public UInt32 height; //图像的高度 8 public double center_x; //瞳孔X轴方向位置 9 public double center_y; //瞳孔Y轴方向位置 10 public double pupils_dia; //瞳孔的直径 11 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 9)] 12 public double[] coef; //侧面图像校正矩阵 13 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] 14 public double[] ratio; //侧面图像和正面图像的像素长 15 public UInt32 info_count; //所包含的边缘信息的数量 16 };
3.如果c++ 函数 返回值是结构体指针,C# 请用intptr接收,然后C#再把intptr转结构体,如下:
C#翻译的结构体:
1 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 2 public struct MwEdges 3 { 4 UInt32 count; 5 UInt32 lenght; 6 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1280)] 7 double[] p11; 8 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1280)] 9 double[] p12; 10 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1280)] 11 double[] p21; 12 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1280)] 13 double[] p22; 14 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1280)] 15 double[] p31; 16 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1280)] 17 double[] p32; 18 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1280)] 19 double[] p41; 20 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1280)] 21 double[] p42; 22 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1280)] 23 double[] p51; 24 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1280)] 25 double[] p52; 26 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] 27 Point[] poiAngle; 28 double dAngle; 29 };
C#调用该结构体:
1 string filename = (Directory.GetCurrentDirectory() + "\\20140707143436\\result\\" + "flank01L.edg"); 2 MwEdges picCfg = new MwEdges(); 3 int size = Marshal.SizeOf(picCfg); 4 byte[] bPicCfg = new byte[size]; 5 6 //即调用某个函数从C++的Dll获取到结构体的bPicCfg,如果这个函数调用失败或者不调用,则不会出现问题。 7 IntPtr ipPicCfg = Marshal.AllocHGlobal(size); 8 Marshal.Copy(bPicCfg, 0, ipPicCfg, bPicCfg.Length); 9 10 //问题出现在这里。运行时报 引发类型为“System.ExecutionEngineException”的异常。 这个错误。 11 IntPtr data = ReadEdgeDatas(filename); 12 picCfg = (MwEdges)Marshal.PtrToStructure(data, picCfg.GetType());
文章写的有点乱,但主要目的还是为了解决C#调用c++库问题,如果文章还是没有看懂的,请各位朋友自行下载源代码,调试看看。