C#调用C dll,结构体传参

时间:2023-01-16 12:47:25

  去年用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 dll,结构体传参的更多相关文章

  1. c&sol;c&plus;&plus; 结构体传参问题

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

  2. C&num;调用c&plus;&plus;Dll 结构体数组指针的问题

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

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

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

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

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

  5. &lbrack;教程心得&rsqb; Flash AIR 调用exe&sol;bat且可以传参

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

  6. SpringBoot&colon;使用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=&quot ...

  8. C&num;调用SQL Server参数过程传参

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

  9. python调用C&plus;&plus; DLL 传参技巧

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

随机推荐

  1. struts2 Result Type四个常用转跳类型

    Result的四个常用转跳类型分别为 Dispatcher 用来转向页面,是Struts的默认形式 Redirect   重定向到一个URL Chain  用来处理Action链 RedirectAc ...

  2. poj1142&period;Smith Number(数学推导)

    Smith Number Time Limit: 1 Sec  Memory Limit: 64 MB Submit: 825  Solved: 366 Description While skimm ...

  3. Oracle-11g 数据库启动时,报错&quot&semi;ORA-01092&quot&semi;及&quot&semi;ORA-18008&colon; cannot find OUTLN schema&quot&semi;

    适用情形: Oracle-11g 数据库启动时,出现类似如下错误. ORA-01092: ORACLE instance terminated. Disconnection forced ORA-18 ...

  4. How to Change Default Web ADI Upload Parameters for FlexField Import &sol; Validation

    How to Change Default Web ADI Upload Parameters for FlexField Import / Validation (文档 ID 553345.1) 转 ...

  5. ucli tcl cmd

    ucli接口与tcl 8.6兼容:vcs中要调用ucli接口,执行脚本,必须在compile的时候,加入debug的权限: -debug,-debug_pp,-debug_all,-debug_acc ...

  6. linux基础之网络基础配置

    基础命令:ifconfig/route/netstat,ip/ss,nmcli 一.ifconfig/route/netstat相关命令 1.  ifconfig - configure a netw ...

  7. Application Constants

    Application: Application类是Android框架中提供的一个类.本身程序员不需要创建它,只需要继承它既可.并在manifest中进行注册. 它给我们提供了一个一般不会被销毁的全局 ...

  8. Miller&lowbar;Rabbin算法判断大素数,Pollard&lowbar;rho算法进行质因素分解

    Miller-rabin算法是一个用来快速判断一个正整数是否为素数的算法.它利用了费马小定理,即:如果p是质数,且a,p互质,那么a^(p-1) mod p恒等于1.也就是对于所有小于p的正整数a来说 ...

  9. js-NodeList对象和HTMLCollection对象

    getElementsByName()和getElementsByTagName()都返回NodeList对象,而类似document.images和document.forms的属性为HTMLCol ...

  10. linux手动安装flash插件

    下载好之后,将解压的文件 1,将libflashplayer.so拷到firefox的插件目录/usr/lib/firefox/browser/plugin/ sudo cp libflashplay ...