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

      

      结果如下

     

  • 相关阅读:
    临时表空间占用大量空间(新建)
    学习总结
    sql:表关联方式
    11gR2 Clusterware 和 Grid Home
    sql分析常用查询
    通过 SSH 实现 TCP / IP 隧道(端口转发):使用 OpenSSH 可能的 8 种场景
    Fabric部署环境初始化(Centos 7)
    Fabric 学习路线
    代币智能合约(go)
    springboot切面编程范例
  • 原文地址:https://www.cnblogs.com/Fuss/p/5230452.html
Copyright © 2020-2023  润新知