C#調用C dll,結構體傳參

  去年用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();
}

  

  結果以下指針

 

相關文章
相關標籤/搜索