去年用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,结构体传参的更多相关文章
-
c/c++ 结构体传参问题
c/c++的结构体传参可以有三种方式: 1.传递结构体变量,值传递 2.传递结构体指针,地址传递 3.传递结构体成员,可是值传递也可以是地址传递 根据代码示例: 1.传递结构体变量 #include& ...
-
C#调用c++Dll 结构体数组指针的问题
参考文章http://blog.csdn.net/jadeflute/article/details/5684687 但是这里面第一个方案我没有测试成功,第二个方案我感觉有点复杂. 然后自己写啦一个: ...
-
C#引用c++DLL结构体数组注意事项(数据发送与接收时)
本文转载自:http://blog.csdn.net/lhs198541/article/details/7593045 最近做的项目,需要在C# 中调用C++ 写的DLL,因为C# 默认的编码方式是 ...
-
Java调用动态链接库so文件(传参以及处理返回值问题)
刚来到公司,屁股还没坐稳,老板把我叫到办公室,就让我做一个小程序.我瞬间懵逼了.对小程序一窍不通,还好通过学习小程序视频,两天的时间就做了一个云开发的小程序,但是领导不想核心的代码被别人看到,给了我一 ...
-
[教程心得] Flash AIR 调用exe/bat且可以传参
Flash AIR 如何调用exe/bat?并且有些情况下需要传参,如何传参呢? 看下面例子: cmd传参打开系统软键盘(参考http://bbs.9ria.com/thread-181265-1-1 ...
-
SpringBoot:使用feign调用restful服务时地址栏传参
1.服务提供者(controller层) @GetMapping("/user/{id}") public ApiResult getById(@PathVariable(&quo ...
-
ajax调用WebServices服务方法和传参调用WebServices注意事项
先演示下ajax是如何调用WebServices中的方法 1.新建一个页面default.aspx,一个Web服务 在页面中引用jQuery文件. <script src=" ...
-
C#调用SQL Server参数过程传参
-SQL SERVER生成测试环境: Create database Test; go USE [Test] GO if OBJECT_ID('Tab2','U') is not null drop ...
-
python调用C++ DLL 传参技巧
结构体传参:http://www.jb51.net/article/52513.htm 准备工作: C++文件(cpp):(注意在函数声明上加上extern "C" 的修饰) #i ...
随机推荐
-
struts2 Result Type四个常用转跳类型
Result的四个常用转跳类型分别为 Dispatcher 用来转向页面,是Struts的默认形式 Redirect 重定向到一个URL Chain 用来处理Action链 RedirectAc ...
-
poj1142.Smith Number(数学推导)
Smith Number Time Limit: 1 Sec Memory Limit: 64 MB Submit: 825 Solved: 366 Description While skimm ...
-
Oracle-11g 数据库启动时,报错";ORA-01092";及";ORA-18008: cannot find OUTLN schema";
适用情形: Oracle-11g 数据库启动时,出现类似如下错误. ORA-01092: ORACLE instance terminated. Disconnection forced ORA-18 ...
-
How to Change Default Web ADI Upload Parameters for FlexField Import / Validation
How to Change Default Web ADI Upload Parameters for FlexField Import / Validation (文档 ID 553345.1) 转 ...
-
ucli tcl cmd
ucli接口与tcl 8.6兼容:vcs中要调用ucli接口,执行脚本,必须在compile的时候,加入debug的权限: -debug,-debug_pp,-debug_all,-debug_acc ...
-
linux基础之网络基础配置
基础命令:ifconfig/route/netstat,ip/ss,nmcli 一.ifconfig/route/netstat相关命令 1. ifconfig - configure a netw ...
-
Application Constants
Application: Application类是Android框架中提供的一个类.本身程序员不需要创建它,只需要继承它既可.并在manifest中进行注册. 它给我们提供了一个一般不会被销毁的全局 ...
-
Miller_Rabbin算法判断大素数,Pollard_rho算法进行质因素分解
Miller-rabin算法是一个用来快速判断一个正整数是否为素数的算法.它利用了费马小定理,即:如果p是质数,且a,p互质,那么a^(p-1) mod p恒等于1.也就是对于所有小于p的正整数a来说 ...
-
js-NodeList对象和HTMLCollection对象
getElementsByName()和getElementsByTagName()都返回NodeList对象,而类似document.images和document.forms的属性为HTMLCol ...
-
linux手动安装flash插件
下载好之后,将解压的文件 1,将libflashplayer.so拷到firefox的插件目录/usr/lib/firefox/browser/plugin/ sudo cp libflashplay ...