去年用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 = , Y =  };
gPoint p2 = new gPoint() { X = , Y = };
gPoint p3 = new gPoint() { X = , Y = };
gPoint p4 = new gPoint() { X = , Y = };
gPoint p5 = new gPoint() { X = , Y = };
gPolygon polygon = new gPolygon() { count = };
gPoint[] array = new gPoint[] { p1, p2, p3, p4, p5 };
int size = Marshal.SizeOf(typeof(gPoint));
polygon.points = Marshal.AllocHGlobal(size * array.Length);
for (int i = ; 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 = ; 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 = ; i < count; i++)
Console.WriteLine("{0}", polygonToString(results[i]));
for (int i = ; 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 = ; 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 - ) sb.Append(',');
}
sb.Append('}');
return sb.ToString();
}

  

  结果如下

C#调用C dll,结构体传参的更多相关文章

  1. c/c++ 结构体传参问题

    c/c++的结构体传参可以有三种方式: 1.传递结构体变量,值传递 2.传递结构体指针,地址传递 3.传递结构体成员,可是值传递也可以是地址传递 根据代码示例: 1.传递结构体变量 #include& ...

  2. C#调用c++Dll 结构体数组指针的问题

    参考文章http://blog.csdn.net/jadeflute/article/details/5684687 但是这里面第一个方案我没有测试成功,第二个方案我感觉有点复杂. 然后自己写啦一个: ...

  3. C#引用c++DLL结构体数组注意事项(数据发送与接收时)

    本文转载自:http://blog.csdn.net/lhs198541/article/details/7593045 最近做的项目,需要在C# 中调用C++ 写的DLL,因为C# 默认的编码方式是 ...

  4. Java调用动态链接库so文件(传参以及处理返回值问题)

    刚来到公司,屁股还没坐稳,老板把我叫到办公室,就让我做一个小程序.我瞬间懵逼了.对小程序一窍不通,还好通过学习小程序视频,两天的时间就做了一个云开发的小程序,但是领导不想核心的代码被别人看到,给了我一 ...

  5. [教程心得] Flash AIR 调用exe/bat且可以传参

    Flash AIR 如何调用exe/bat?并且有些情况下需要传参,如何传参呢? 看下面例子: cmd传参打开系统软键盘(参考http://bbs.9ria.com/thread-181265-1-1 ...

  6. SpringBoot:使用feign调用restful服务时地址栏传参

    1.服务提供者(controller层) @GetMapping("/user/{id}") public ApiResult getById(@PathVariable(&quo ...

  7. ajax调用WebServices服务方法和传参调用WebServices注意事项

    先演示下ajax是如何调用WebServices中的方法    1.新建一个页面default.aspx,一个Web服务    在页面中引用jQuery文件. <script src=" ...

  8. C#调用SQL Server参数过程传参

    -SQL SERVER生成测试环境: Create database Test; go USE [Test] GO if OBJECT_ID('Tab2','U') is not null drop ...

  9. python调用C++ DLL 传参技巧

    结构体传参:http://www.jb51.net/article/52513.htm 准备工作: C++文件(cpp):(注意在函数声明上加上extern "C" 的修饰) #i ...

随机推荐

  1. 【mybatis】之批量添加

    mybatis批量添加xml <insert id="batchCreate"> INSERT INTO `roomer` (`order`,name,idCard,m ...

  2. Python之re模块 —— 正则表达式操作

    这个模块提供了与 Perl 相似l的正则表达式匹配操作.Unicode字符串也同样适用. 正则表达式使用反斜杠" \ "来代表特殊形式或用作转义字符,这里跟Python的语法冲突, ...

  3. SQL Server 2012 批量重建索引

    关于索引的概念可以看看宋大牛的博客 T-SQL查询高级—SQL Server索引中的碎片和填充因子 整个数据库的索引很多,索引碎片多了,不可能一个个的去重建,都是重复性的工作,所以索性写了个存储过程, ...

  4. 黄聪:wordpress如何获取当前页面的URL

    一行代码搞定 <? echo home_url( add_query_arg( array() ) ); ?>

  5. [转][色彩 A] – 永远不要使用纯黑

    原文地址:http://www.cgjoy.com/forum.php?mod=viewthread&tid=110762&extra=page%3D1%26filter%3Dtype ...

  6. DG_Oracle DataGuard Switchover主备节点切换(案例)

    2014-06-09 Created By BaoXinjian Thanks and Regards http://wenku.baidu.com/view/dc9f00d349649b6648d7 ...

  7. PLSQL_闪回删除FlashBack Drop表误删除如何进行恢复(案例)

    2014-06-25 Created By BaoXinjian

  8. NeHe OpenGL教程 第二十一课:线的游戏

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  9. Redis使用详细教程(转)

    一.Redis基础部分: 1.redis介绍与安装比mysql快10倍以上 *****************redis适用场合**************** 1.取最新N个数据的操作 2.排行榜应 ...

  10. [Flex] PopUpButton系列 —— 弹出菜单的行高设置

    <?xml version="1.0" encoding="utf-8"?> <!--Flex中如何通过variableRowHeight样式 ...