﻿ C#调用C dll，结构体传参 - 鸿网互联

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

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

结果如下

<