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为输出的凸多边形

 

下面是C#中的调用方式 

[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来实现对结构体指针的操作

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

  

  结果如下

 

posted @ 2016-03-01 13:46  峰顶飞龙  阅读(4647)  评论(0编辑  收藏  举报