去年用wpf弄了個航線規劃軟件,用於生成無人機噴灑農藥的做業航線,裏面包含了很多算法。年後這幾天將其中的算法移植到C,以便其餘同事調用。昨天在用C#調用生成的dll時,遇到一些問題,折騰了很久才解決。這裏就其中的一個函數作個記錄,或許有人會遇到相似的問題。算法
C裏面相關的結構和函數原型函數
/** * 平面點、向量 */ typedef struct { double X; double Y; } gPoint, gVector; /** * 平面直線 */ typedef struct gLine { gPoint startPoint; gPoint endPoint; } gLine; /** * 平面多邊形 */ typedef struct gPolygon { gPoint *points; int count; } gPolygon;
#define DllExport __declspec(dllexport)
/* 根據反轉點用平移直線將多邊形分割 */ DllExport int splitPolygon(gPolygon polygon, gLine moveline, gPolygon results[]);
上面的函數,將凹多邊形根據切割方向和凹點切割成多個凸多邊形,results爲輸出的凸多邊形ui
下面是C#中的調用方式 spa
[StructLayout(LayoutKind.Sequential)] struct gPoint { public double X; public double Y; } [StructLayout(LayoutKind.Sequential)] struct gLine { public gPoint startPoint; public gPoint endPoint; } [StructLayout(LayoutKind.Sequential)] struct gPolygon { public IntPtr points; public int count; }
使用 Marshal.AllocHGlobal、Marshal.FreeHGlobal來分配、釋放非託管內存;使用Marshal.StructureToPtr、Marshal.PtrToStructure來實現對結構體指針的操做3d
gPoint p1 = new gPoint() { X = 0, Y = 0 }; gPoint p2 = new gPoint() { X = 0, Y = 100 }; gPoint p3 = new gPoint() { X = 100, Y = 100 }; gPoint p4 = new gPoint() { X = 50, Y = 50 }; gPoint p5 = new gPoint() { X = 100, Y = 0 }; gPolygon polygon = new gPolygon() { count = 5 }; gPoint[] array = new gPoint[5] { p1, p2, p3, p4, p5 }; int size = Marshal.SizeOf(typeof(gPoint)); polygon.points = Marshal.AllocHGlobal(size * array.Length); for (int i = 0; i < array.Length; i++) { IntPtr ptr = new IntPtr(polygon.points.ToInt64() + i * size); Marshal.StructureToPtr(array[i], ptr, false); } gLine ml = new gLine() { startPoint = p1, endPoint = p2 }; gPolygon[] results = new gPolygon[array.Length]; for (int i = 0; i < array.Length; i++) results[i].points = Marshal.AllocHGlobal(size * array.Length); int count = splitPolygon(polygon, ml, results); Console.WriteLine("多邊形 {0} 可切割成{1}個凸多邊形", polygonToString(polygon), count); for (int i = 0; i < count; i++) Console.WriteLine("{0}", polygonToString(results[i])); for (int i = 0; i < array.Length; i++) Marshal.FreeHGlobal(results[i].points); Marshal.FreeHGlobal(polygon.points);
static string polygonToString(gPolygon polygon) { StringBuilder sb = new StringBuilder(); sb.Append('{'); int size = Marshal.SizeOf(typeof(gPoint)); for (int i = 0; i < polygon.count; i++) { IntPtr p = new IntPtr(polygon.points.ToInt64() + size * i); gPoint tempgp = (gPoint)Marshal.PtrToStructure(p, typeof(gPoint)); sb.AppendFormat("({0},{1})", tempgp.X, tempgp.Y); if (i < polygon.count - 1) sb.Append(','); } sb.Append('}'); return sb.ToString(); }
結果以下指針