c 调用c语言dll数组,C#调用C类型dll入参为struct的问题详解

前言

C# 可以通过 DllImport 的方式引用 C 类型的 dll。但很多 dll 的参数不会是简单的基础类型,而是结构体 struct 。因此就需要在 C# 端定义同样的结构体类型,才能实现调用 C 类型 dll。这里例举几种不同的结构体情况,以及其对应的解决方案。

基础调用方式

对于一个结构体类型:

typedef struct DATA

{

int nNumber;

float fDecimal;

};

在 C# 端就需要定义为

[StructLayout(LayoutKind.Sequential)]

public struct DATA

{

public int nNumber;

public float fDecimal;

}

包含字符数组

对于一个包含字符数组的结构体类型:

typedef struct DATA

{

int nNumber;

float fDecimal;

char szString[256];

};

在 C# 端就需要使用 Marshal 设置数据空间大小,同时最好定义一个初始化函数与 get 的定义

[StructLayout(LayoutKind.Sequential)]

public struct DATA

{

void alloc() {

szString = new char[256];

}

string sString {

get {

int nLength = 256;

string sData = "";

for (int i = 0; i < nLength; i++)

{

if (szData[i] == '\0') break;

sData += szData[i];

}

return sData;

}

}

public int nNumber;

public float fDecimal;

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]

char[] szString;

}

包含字符二维数组

对于一个包含字符二维数组的结构体类型:

typedef struct DATA

{

int nNumber;

float fDecimal;

char szString[6][256];

};

在 C# 端同样需要使用 Marshal 设置数据空间大小,需要将两个 Size 相乘,并定义一个初始化函数。同时在做一个 get 的定义。

[StructLayout(LayoutKind.Sequential)]

public struct DATA

{

void alloc() {

szString = new char[256 * 6];

}

public string[] sStrings

{

get {

int nSize = 6, nLength = 256;

string[] sDatas = new string[nSize];

for (int i = 0; i < nSize; i++)

{

for (int j = 0; j < nLength; j++)

{

if (szData[i * nLength + j] == '\0') break;

sData += szData[i * nLength + i];

}

sDatas[i] = sData;

}

return sDatas;

}

}

public int nNumber;

public float fDecimal;

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256 * 6)]

char[] szStrings;

}

dll 入参为结构体数组

若有一个这样的 C dll 函数定义:

void FnCall(DATA* datas);

// 调用方式

DATA datas[10];

fnCall(datas);

那么,在 C# 中要实现等价调用:

// 首先 Import 函数

[DllImport("Module.dll")]

public static extern void FnCall(IntPtr pInfo); // 注意入参要定义为指针

// 再定义定义结构体数组

int nCount = 10;

DATA datas = new DATA[nCount];

// 再分配内存空间

int nSize = Marshal.SizeOf(typeof(DEVICE_INFO));

IntPtr Dataptr = Marshal.AllocHGlobal(nSize * nCount);

// 调用函数

FnCall(Dataptr);

// 复制数据到结构体中

for (int i = 0; i < nCount; i++)

{

IntPtr ptr = (IntPtr)((UInt32)Dataptr + i * size);

datas[i] = (DEVICE_INFO)Marshal.PtrToStructure(ptr, typeof(DEVICE_INFO));

}

// 释放内存空间

Marshal.FreeHGlobal(Dataptr);

另外,如果你要调用的 dll 是非 C 类型 dll,而是 C++ Class。那么我们就可以将其再包装一层,转换为 C 类型 dll。

例如:

class Example {

public:

int MethodCall();

};

那么就可以编写 C 类型的 dll。

extern "C" {

Example* Example_New() {

return new Example();

}

int Example_MethodCall(Example* p) {

return p->MethodCall();

}

void Example_Delete(Example* p) {

delete p;

}

}

C# 那边就这样导入

[DllImport("Module.dll")]

public static extern IntPtr Example_Create();

[DllImport("Module.dll")]

public static extern int Example_MethodCall(IntPtr value);

[DllImport("Module.dll")]

public static extern void Example_Delete(IntPtr value);

// 调用方式

IntPtr p = Example_Create();

Example_MethodCall(p);

Example_Delete(p);

至于 C 类型 dll 中其他类型变量在 C# 的对应,则可以参考 Microsoft 的 文档 。

总结

到此这篇关于C#调用C类型dll入参为struct问题的文章就介绍到这了,更多相关C#调用C类型dll入参内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/334231.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Slackware Linux 的发展历程

目前可供Linux用户使用的 发行版有很多种&#xff0c;它们虽基于共同的内核&#xff0c;但在安装、提供的应用程序、服务等方面各具特色&#xff0c;并拥有各自的用户群体。Slackware Linux是一个历史比较悠久的发行版&#xff0c;它的存在见证了Linux的发展历程&#xff0c;它…

golang 泛型_Golang 1.x版本泛型编程

本文介绍了Golang 1.x版本的泛型编程。往期回顾&#xff1a;浅谈动态追踪技术Go是一门天生为服务器程序设计的简洁的语言&#xff0c;因此Go的设计原则聚焦在可扩展性、可读性和并发性&#xff0c;而多态性并不是这门语言的设计初衷&#xff0c;因此就被放在了一边。虽然在2.0版…

jwt令牌_JWT令牌的秘密轮换

jwt令牌当您使用JSON Web令牌 &#xff08; JWT &#xff09;或需要对有效载荷信息进行签名或加密的任何其他令牌技术时&#xff0c;设置令牌的到期日期很重要&#xff0c;因此&#xff0c;如果令牌到期&#xff0c;则可以假定这可能被视为安全漏洞&#xff0c;您拒绝使用此令牌…

linux android build tools,build.gradle 文件中的 Android SDK Build Tools version

build.gradle 文件中的 Android SDK Build Tools versionAndroid,Gradle,SDK2018.07.17在 Android Gradle Plugin 3.0.1 中&#xff0c;最低的 Android SDK Build Tools 是 26.0.2&#xff0c;而我声明的 25.0.0 将被忽略掉。今天新建了一个 Android 项目的时候&#xff0c;无意…

Linux 常用的软件包管理器/软件包管理工具

文章目录RPMYUMDNFDPKGPacmanZypperPortageEopkgUrpmiRPM 代表系统&#xff1a;RHEL、CentOS、Fedora、openSUSE、SUSE企业版、PCLinuxOS、Mandriva Linux、Mageia 等 主命令&#xff1a;rpm YUM 代表系统&#xff1a;RHEL、CentOS 主命令&#xff1a;yum DNF 这是基于 RP…

怎样用C语言实现五子棋,C语言实现五子棋

可以称得上史上最简单的五子棋版本了。可以使用curses库来改进页面和下棋方式。并且对于输入的坐标没有进行鉴别&#xff0c;如果输入的坐标超过棋盘大小&#xff0c;就会段错误退出。我改进了一点&#xff0c;但是还是没有完全避免这个问题。/**Gobang.c*/#include#include#de…

jasperreports_JasperReports:棘手的部分

jasperreports如果您使用Java进行编程的时间足够长&#xff0c;则有可能需要为业务用户生成报告。 就我而言&#xff0c;我已经看到几个项目使用JasperReportsLibrary来生成PDF和其他文件格式的报告。 最近&#xff0c;我荣幸地观察了Mike和他的团队使用上述报告库以及他们所面…

电脑运行adb闪退_adb+python进阶使用

之前文章有提到过使用python加adb刷视频&#xff0c;今天带来进阶版——无线多台手机。首先要使用adb连接多台手机&#xff0c;手机和电脑肯定要在统一局域网内。1.打开手机开发者模式&#xff0c;并通过USB接口链接电脑。2.打开cmd&#xff1a;输入adb tcpip 5555, 会得到相关…

MacBook 强制关机的四种方法

文章目录一、强制关机二、强制断电三、安全关闭&#xff08;老款 MacBook&#xff09;四、强制关闭一、强制关机 长按电源键&#xff0c;5 秒左右 二、强制断电 ShiftControlOption电源键 三、安全关闭&#xff08;老款 MacBook&#xff09; ControlOptionCommand电源键。…

python存储和读取数据时出现错误_python读取json文件存sql及codecs读取大文件问题...

preface: 最近帮师兄处理json文件&#xff0c;需要读到数据库里面&#xff0c;以备其后续从数据库读取数据。数据是关于yelp网站里面的: https://github.com/Yelp/dataset-examples&#xff0c;http://www.yelp.com/dataset_challenge/. 涉及到一些json和sql的问题&#xff0c;…

Mac OS/macOS 关机的命令

文章目录一、立即关机二、10 分钟后关机三、晚上 8 点关机四、立即重启一、立即关机 sudo halt 或者 sudo shutdown -h now 二、10 分钟后关机 sudo shutdown -h 10 三、晚上 8 点关机 sudo shutdown -h 20:00 四、立即重启 sudo reboot 或者 sudo shutdown -r now

使用枚举映射_用EnumMaps映射枚举键

使用枚举映射这是一种在JDK中存在很长时间的类型&#xff0c;当我们要定义以枚举类型作为键的映射时&#xff0c;这种类型会派上用场&#xff1a; EnumMap是一种特殊的Map 。 我们将为给定的枚举创建一个映射&#xff1a; public enum CoffeeType {ESPRESSO, POUR_OVER, FREN…

linux 划ext4,linux – 有没有像ext4这样的’快速’格式?

严格的答案像-E lazy_itable_init这样的解决方案不会改变结果,只会加快进程.这是明确要求的,在许多情况下人们需要更多.额外奖励在大多数情况下,您实际上需要一些与您的使用模式匹配的选项,不仅可以加快文件系统的创建速度,还可以加快使用速度并增加可用空间.我刚做了一个测试.…

java office在线编辑_国外10个最受欢迎的 Java 开发的 CMS 系统

CMS是Content Management System的缩写&#xff0c;意为"内容管理系统"&#xff0c;它具有许多基于模板的优秀设计&#xff0c;可以加快网站开发的速度和减少开发的成本。CMS的功能并不只限于文本处理&#xff0c;它也可以处理图片、Flash动画、声像流、图像甚至电子…

apache kafka_Apache Kafka简介

apache kafka什么是Apache Kafka&#xff1f; Apache Kafka是一个分布式流系统&#xff0c;具有发布和订阅记录流的功能。 在另一方面&#xff0c;它是企业消息传递系统。 它是一个快速&#xff0c;水平可扩展和容错的系统。 Kafka有四个核心API&#xff0c; 生产者API&#x…

Mac OS 查看系统版本信息/硬件信息的命令

文章目录一、查看硬盘信息二、查看系统内核信息三、查看 OS 版本信息一、查看硬盘信息 liaowenxiongdeMacBook-Air:~ liaowenxiong$ system_profiler SPHardwareDataType Hardware:Hardware Overview:Model Name: MacBook AirModel Identifier: MacBookAir7,2Processor Name: …

人脸特征值能存放在sql server中吗_SQL运行内幕:从执行原理看调优的本质

原文链接&#xff1a;https://www.cnblogs.com/arthinking/p/13205303.html相信大家看过无数的MySQL调优经验贴了&#xff0c;会告诉你各种调优手段&#xff0c;如&#xff1a;避免 select *&#xff1b;join字段走索引&#xff1b;慎用in和not in&#xff0c;用exists取代in&a…

rest资源设计_REST资源何时应获得其自己的地址?

rest资源设计在纯粹的REST方法中&#xff0c;所有端点&#xff08;起始端点除外&#xff09;都是不透明的&#xff0c;因此不需要发布其各种详细信息。 即使使用这种方法&#xff0c;本文中的要点也很重要&#xff0c;因为服务器逻辑将必须确定何时需要结束点。 介绍 在REST体…

百度地图android绘图类,Class:android总类/android离线地图类

出自百度地图API跳转到&#xff1a;导航,搜索com.baidu.mapapi类 MKOfflineMapjava.lang.Object∟ com.baidu.mapapi.MKOfflineMappublic class MKOfflineMapextends java.lang.Object离线地图类(只支持老版离线地图)。字段摘要方法摘要返回类型方法booleanstart(int cityID)启…