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 = , 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 ...
随机推荐
- 【SVN】win7 搭建SVN服务器
介绍 SVN分为客户端和服务端: 服务端: 常用的主要有2个,分别为: 1. VisualSvn Server:免费,集成了Subsersion和Apache,安装使用非常简单: 2. SubVers ...
- IntelliJ IDEA添加过滤文件或目录
Settings→Editor→File Types 在下方的忽略文件和目录(Ignore files and folders)中添加自己需要过滤的内容 下图为我自己添加过滤的内容,例如:*.iml; ...
- update openssl on redhat/centos
$ openssl versionOpenSSL 1.0.1e-fips 11 Feb 2013 $ yum list |grep opensslopenssl.x86_64 1.0.1e-16.el ...
- ultraedit15.00.0.1046注册码
ultraedit注册码,版本:15.00.0.1043·········· 用户名 MAYBELOVE 注册码 LFKKM-KIMMX-OSFEB-PMISO-ELILS-IIIHO-KKHLR ...
- c++中字符串处理函数
c++11中提供了to_string函数,定义在string中, 重载了一大片, std::string to_string( int value ); () (since C++) std::str ...
- 黄聪:jquery mobile通过a标签页面跳转后,样式丢失、js失效的解决方法
问题描述: 用ajax跳转的时候,从a.html跳转到b.html后,b.html的css以及js都失效了. 解决办法1: 将所有的css以及js全部放在div内. 原理: 由于jqm的ajax跳转的 ...
- Win8 安装驱动
从微软的网站上面下载了一些驱动,发现竟然没有Setup或者Install安装程序,囧. 快速查了一下,直接在inf文件右击的菜单里面选择“安装”即可.突然有点out的感觉. 参考:http://dig ...
- Linux Tcpdump 使用举例 ---持续更新
举例: 保存到文件tcpdump -w xxx.cap(默认抓取eth0的包) 抓eth1的包 tcpdump -i eth1 -w /tmp/xxx.cap 抓到完成的数据包(默认只抓前68字节) ...
- vim 学习日志(1):剪切,复制,粘贴,删除,撤销
一:光标命令 左h 上j 下k 右l :goto n 表示跳转到文本的第n个字符 :n 表示跳到第n行 nG n为行数,该命令立即使光标跳到指定行:n为空,光标跳到文件最后一行. Ctrl+G ...
- 【转】C++ 单例模式
http://blog.csdn.net/hackbuteer1/article/details/7460019 单例的一般实现比较简单,下面是代码和UML图.由于构造函数是私有的,因此无法通过构造函 ...