C#:向C++封送结构体数组

在使用第三方的非托管API时,我们经常会遇到参数为指针或指针的指针这种情况,

一般我们会用IntPtr指向我们需要传递的参数地址;

 

但是当遇到这种一个导出函数时,我们如何正确的使用IntPtr呢,

extern "C" __declspec(dllexport) int GetClass(Class pClass[50]) ;

 

由于这种情况也经常可能遇到,所以我制作了2个示例程序来演示下如何处理这种非托管函数的调用!

 

首先创建一个C++ 的DLL  设置一个如上的导出函数

#include <Windows.h> 
#include <stdio.h>typedef struct Student 
{ char name[20]; int age; double scores[32];
}Student;typedef struct Class
{int number;Student students[126]; 
}Class;extern "C" __declspec(dllexport)int GetClass(Class pClass[50])
{     for(int i=0;i<50;i++)     {        pClass[i].number=i;        for(int j=0;j<126;j++)        {            memset(pClass[i].students[j].name,0,20);       sprintf(pClass[i].students[j].name,"name_%d_%d",i,j);   pClass[i].students[j].age=j%2==0?15:20;       }     }     return 0;30 
}

 

上面DLL 的导出函数要求传递的参数为它自定义的Class结构体数组, 那么我们在C#调用它时也要自定义对应的结构体了,

我们可以定义为如下:

[StructLayout(LayoutKind.Sequential)]struct Student{[MarshalAs(UnmanagedType.ByValTStr,SizeConst=20)]public string name;public int age;[MarshalAs(UnmanagedType.ByValArray,SizeConst=32)]public double[] scores;}[StructLayout(LayoutKind.Sequential)]struct Class{public int number;[MarshalAs(UnmanagedType.ByValArray,SizeConst=126)]public Student[] students;}

 

需要注意的是,这2个结构体中的数组大小一定要跟C++中的限定一样大小哦,接下来如何使用这个API来正确的获取数据呢,大多数人可能想到像这样的处理方式

Class myclass = new Class();
IntPtr ptr=Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Class)));
GetClass(ptr);
Marshal.FreeHGlobal(ptr);

 

没错,这样的处理是没问题的,但是我们的API的参数是Class数组,这种处理方式只是传递一个Class结构体参数,所以这种方式在这里就不太合适了,!

 那大家就想到先Class[] myclass = new Class[MaxClass]; 然后在用Marshal.AllocHGlobal 来获取myclass 数据的指针,

其实这样也是错的, 因为 Class结构中包含了,不能直接封送的Student结构,所以无论如何上面的想法是错误的!

那要怎么办呢,其实很简单,就是先分配一段非托管内存,并调用API后,再将非托管内容数据读取到托管结构体数据中!

 

static void Main(string[] args)
{int size = Marshal.SizeOf(typeof(Class)) * 50;byte[] bytes = new byte[size];IntPtr pBuff = Marshal.AllocHGlobal(size);Class[] pClass = new Class[50];GetClass(pBuff);for (int i = 0; i < 50; i++){IntPtr pPonitor = new IntPtr(pBuff.ToInt64() + Marshal.SizeOf(typeof(Class)) * i);pClass[i] = (Class)Marshal.PtrToStructure(pPonitor, typeof(Class));}Marshal.FreeHGlobal(pBuff);Console.ReadLine();
}

 

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

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

相关文章

其它综合-CentOS7 忘记root密码

CentOS7 忘记root密码 长时间不用的 CentOS 机器再次开机的时候忽然忘记了密码&#xff0c;总不能就重装一台吧&#xff0c;还有好多服务在机器上&#xff0c;于是决定重置root的密码。   如果是已经开启的机器&#xff0c;需要进行关闭&#xff0c;重新启动。在启动选择内核…

left join on and 与 left join on where的区别

数据库在通过连接两张或多张表来返回记录时&#xff0c;都会生成一张中间的临时表&#xff0c;然后再将这张临时表返回给用户。 在使用left jion时&#xff0c;on和where条件的区别如下&#xff1a; 1、 on条件是在生成临时表时使用的条件&#xff0c;它不管on中的条件是否为真…

spring boot高性能实现二维码扫码登录(中)——Redis版

前言 本打算用CountDownLatch来实现&#xff0c;但有个问题我没有考虑&#xff0c;就是当用户APP没有扫二维码的时候&#xff0c;线程会阻塞5分钟&#xff0c;这反而造成性能的下降。好吧&#xff0c;现在回归传统方式&#xff1a;前端ajax每隔1秒或2秒发一次请求&#xff0c;去…

C# :socket 通讯基础使用实例

们在讲解Socket编程前&#xff0c;先看几个和Socket编程紧密相关的概念&#xff1a; TCP/IP层次模型当然这里我们只讨论重要的四层 01&#xff0c;应用层(Application)&#xff1a;应用层是个很广泛的概念&#xff0c;有一些基本相同的系统级TCP/IP应用以及应用协议&#xff0…

IBM发表论文:可能已找到处理量子计算退相干的方法

在《自然》杂志最近发表的一篇论文中&#xff0c;IBM和其他机构的研究人员设计了两种量子算法&#xff0c;利用变分量子电路和量子核估计器来训练一种支持向量机分类器。这两种算法背后的关键思想是使用量子状态空间作为特征空间表示&#xff0c;有效地构建映射&#xff0c;从原…

PHP + NGINX 控制视频文件播放,并防止文件下载

最简单的方法是使用NGINX的 internal 功能 server { listen 80; server_name www.xxx.com;  location / { index index.php index.html index.htm; root /xxx; if (!-e $request_filename) { rewrite ^/index.php(.*)$ /index.php?s$…

可视化调试工具

rosrun rqt_console rqt_console # 查看日志消息&#xff0c;可filter、highlight指定级别。 rosrun rqt_logger_level rqt_logger_level # 可设在日志记录器的严重级别 rosrun rqt_topic rqt_topic # 显示topic调试信息 rosrun rqt_publisher rqt_publisher # 在界面中管理ro…

C#:委托基础与事件

通过以下思维导图&#xff0c;学习委托的基本概念&#xff0c;后面着重讲解委托的运用&#xff0c;希望通过最简单的方式收获更多的知识。 1.委托的各种写法 1、委托 委托名new 委托&#xff08;会调用的方法名); 委托名&#xff08;参数&#xff09;; 2、委托 委托名 会调用…

Git Bash关键命令

1.默认目录是C:\Users\用户名 2.切换目录&#xff1a;$cd c:\\windows 3.切换到上级目录&#xff1a;cd ..&#xff0c;中间有空格 4.列出某目录所有文件&#xff0c;相当于DOS下的dir&#xff1a;ls c:\\windows 5.查看配置信息&#xff1a;git config --list 以下是显示信息 …

C#:invoke 与 BeginInvoke使用区别

invoke和begininvoke 区别 一直对invoke和begininvoke的使用和概念比较混乱&#xff0c;这两天看了些资料&#xff0c;对这两个的用法和原理有了些新的认识和理解。 首先说下&#xff0c;invoke和begininvoke的使用有两种情况&#xff1a; 1. control中的invoke、begininvoke。…

Django基本命令

Django基本命令 1.创建一个Django 项目 django_admin.py startproject mysite当前目录下会生成mysite的工程&#xff0c;目录结构如下&#xff1a; manage.py ----- Django项目里面的工具&#xff0c;通过它可以调用django shell和数据库等。settings.py ---- 包含了项目的默认…

Git忽略规则.gitignore梳理

对于经常使用Git的朋友来说&#xff0c;.gitignore配置一定不会陌生。废话不说多了&#xff0c;接下来就来说说这个.gitignore的使用。首先要强调一点&#xff0c;这个文件的完整文件名就是".gitignore"&#xff0c;注意最前面有个“.”。 一般来说每个Git项目中都需…

第二周CoreIDRAW课总结

1.这节课学到了什么知识&#xff1f; 学到了图像的复制&#xff0c;再制鼠标复制&#xff0c;重复&#xff0c;还有对象的对齐&#xff0c;对象的分布顺序。 2.有哪些心得体会&#xff1f; 做了课本的练习&#xff0c;会用窗口里面的泊坞窗造型命令也作出了一个作品。 3.这节课…

axios关于针对请求时长策略设计的思考

前言 在我们的业务请求中&#xff0c;有很多时候会针对有不同时长的需求策略性设置。这里针对这个需求进行详细的展开。 针对这种情况&#xff0c;我们的timout的一般是根据请求地址来的&#xff0c;所以核心处理技巧便是如何根据不同的request地址去设置不同的timeout. 我们之…

C#:WinForm无边框窗体移动方法、模仿鼠标单击标题栏移动窗体位置

方法一&#xff1a;直接通过修改窗体位置从而达到移动窗体的效果 方法二&#xff1a;直接伪装发送单击任务栏消息&#xff0c;让应用程序误以为单击任务栏从而移动窗体 方法一 1.定义一个位置信息Point用于存储鼠标位置 private Point mPoint; 2.给窗体等控件增加MouseDown…

Python 字典删除元素clear、pop、popitem

同其它python内建数据类型一样&#xff0c;字典dict也是有一些实用的操作方法。这里我们要说的是字典删除方法&#xff1a;clear()、pop()和popitem()&#xff0c;这三种方法的作用不同&#xff0c;操作方法及返回值都不相同。接下来就来查看下这些字典特定方法的具体用法是什么…

reactor模式:多线程的reactor模式

上文说到单线程的reactor模式 reactor模式&#xff1a;单线程的reactor模式 单线程的reactor模式并没有解决IO和CPU处理速度不匹配问题&#xff0c;所以多线程的reactor模式引入线程池的概念&#xff0c;把耗时的IO操作交由线程池处理&#xff0c;处理完了之后再同步到selecti…

Elasticsearch实战篇——Spring Boot整合ElasticSearch

2019独角兽企业重金招聘Python工程师标准>>> 当前Spring Boot很是流行&#xff0c;包括我自己&#xff0c;也是在用Spring Boot集成其他框架进行项目开发&#xff0c;所以这一节&#xff0c;我们一起来探讨Spring Boot整合ElasticSearch的问题。 本文主要讲以下内容…

C#:Dockpanel的一些入门的基本操作

原文链接&#xff1a; 一、引用&#xff1a; 1.建立一个WinForm工程&#xff0c;默认生成了一个WinForm窗体Form1&#xff08;此处默认为主窗体&#xff09;。 2.引用—>添加引用—>浏览—>weiFenLuo.winFormsUI.Docking.dll。 3.设置Form1窗体属性IsMdiContainer…

MyBatis中if,where,set标签

<if>标签 <select id"findActiveBlogWithTitleLike"resultType"Blog">SELECT * FROM BLOG WHERE state ‘ACTIVE’ <if test"title ! null">AND title like #{title}</if> </select> if标签通常伴随着where,set…