p/invoke碎片--对数组的封送处理
因为数组是引用类型,所以数组的处理根据数组元素的类型是否为“可直接传递到非托管代码”的类型而分为两种情况。主要目标是看内存是怎么变化的,是复制还是锁定。
数组中的元素是"可直接传递到非托管代码中"的类型
这种类型很多,比如 int double 等。
完成的托管代码和非托管代码如下:
///////////////////////非托管代码
extern "C" __declspec(dllexport) void DoArray(int a[],int length)
{
for(int i=;i<length;i++)
{
printf("%d\n",a[i]);
a[i]=;
}
}
////////////////////////////托管代码
[DllImport(@"C:\Users\Administrator\Desktop\pInvoke\CPPDLL\Debug\CPPDLL.dll")]
private static extern void DoArray(int []arr,int length); int[] arr = new int[] {,,,,,, };
DoArray(arr,arr.Length);//断点
foreach(int a in arr)
{
Console.WriteLine(a);
}
跟踪过程:断点先下在托管代码调用函数的地方--DoArray处。这是看一下数组的内存情况如下,
0x01FABAA4 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 ................
0x01FABAB4 05 00 00 00 06 00 00 00 07 00 00 00 00 00 00 00 ................
可以看到7个数字情况。地址是0x01fabaa4.记下这个地址,继续。。。
来到非托管代码中,发现a的地址如图:
可以看到,和托管代码中数组的地址是一样的。再执行,打印结果:
1 2 3 4 5 6 7 99 99 99 99 99 99 99.
结论:如果数组中的元素是“可直接传递到非托管代码”中的类型时。默认的封送方式是采用了[In,Out]修饰的,传递是一个指针,先锁定内存再传递指针,并且非托管代码对数组的修改会反映到托管代码中。
数组的元素是“非可直接传递到非托管代码中”的类型
托管内存中数组元素是char类型,是一种“非可直接传递到非托管代码中”的类型。看看内存的情况吧。
private static extern void DoArray2(char [] arr, int length);
static void Main(string[] args)
char[] carry = new char[] { 'a','b','c'};
DoArray2(carry, carry.Length);
foreach (char c in carry)
{
Console.Write(c + "\t");
}
////////////////////////非托管代码
extern "C" __declspec(dllexport) void DoArray2(char carry[],int length)
{
for(int i=;i<length;i++)
{
printf("%c\t",carry[i]);
carry[i]='?';
}
}
断点跟踪,断在DoArray2(carry,carry.Length)调用处, carry在非托管代码中的分布如下:
0x01D4BAB8 61 00 62 00 63 00 00 00 00 00 00 00 00 00 00 00 a.b.c...........
接着断在非托管代码领域,数组carry地址显示为:
0x004ADC70 61 62 63 00 00 00 3d 00 d8 dd 4a 00 3d 00 22 00 abc...=.??J.=.".
显然,不是一块地址,结果可想而知,修改也不会反映到托管内存中了。
结果:a b c a b c .
结论:当数组中的元素是“非可直接传递到非托管代码中”的类型时,这时的封送过程:先在非托管内存申请一块内存,把托管内存中字符串的数据传递复制过去,再把新内存的指针作为参数传递给函数,函数对数组的操作都是基于新内存,结果不会返回到托管代码中。另外值得一说的是,当调用完成后,非托管内存中的数据没有被释放掉。
使用IntPtr来封送数组
p/invoke碎片--对数组的封送处理的更多相关文章
- p/invoke碎片--对类的封送处理
主要是看默认封送处理行为 按类成员的类型是否为“可直接传递到非托管内存”的类型来分类;按照成员中是否有“可直接传递到非托管内存”的类型来讨论. 所有成员都是“可直接传递到非托管内存”的类型 托管代码和 ...
- C#调用C/C++动态库 封送结构体,结构体数组
一. 结构体的传递 #define JNAAPI extern "C" __declspec(dllexport) // C方式导出函数 typedef struct { int ...
- C#调用C/C++动态库 封送结构体,结构体数组
因为实验室图像处理的算法都是在OpenCV下写的,还有就是导航的算法也是用C++写的,然后界面部分要求在C#下写,所以不管是Socket通信,还是调用OpenCV的DLL模块,都设计到了C#和C++数 ...
- p/invoke 碎片-- 对字符串的处理
字符串在内存中的的几种风格 字符串作为参数和返回值 参考 字符串在内存中的几种风格 所谓的风格,也就是字符串在内存中的存在形式.如何存放的,占据内存的大小,还有存放顺序等.在不同的编程语言和不同的平台 ...
- p/invoke碎片,对结构体的处理
结构体的一些相关知识 可直接转换类类型,比如int类型,在托管代码和非托管代码中占据内存大小 和意义都是一个样的. 结构体封送的关键是:在托管代码和非托管代码中定义的一致性.什么是定义的一致性?包括结 ...
- [原]C#与非托管——封送和自动封送
之前说到了如何从C函数声明通过简单的查找替换生成一份C#的静态引用声明(C#与非托管——初体验),因为只是简单说明,所以全部采用的是基础类型匹配和自动封送.自动封送虽然能省去我们不少编码时间,但如果不 ...
- C# 互操作性入门系列(三):平台调用中的数据封送处理
好文章搬用工模式启动ing ..... { 文章中已经包含了原文链接 就不再次粘贴了 言明 改文章是一个系列,但只收录了2篇,原因是 够用了 } --------------------------- ...
- [转]C# 互操作性入门系列(三):平台调用中的数据封送处理
参考网址:https://www.cnblogs.com/FongLuo/p/4512738.html C#互操作系列文章: C# 互操作性入门系列(一):C#中互操作性介绍 C# 互操作性入门系列( ...
- C 碎片五 数组
构造类型数据是有基本类型数据按照一定规则组成的.数组,结构体,共用体都属于构造类型的数据.数组是有序数据的集合,C语言数组中的每一个元素都属于同一个数据类型,用数组名和下标来唯一确定数组中的元素. 一 ...
随机推荐
- SQL Server会话KILL不掉,一直处于KILLED /ROLLBACK状态情形浅析
今天遇到一个很奇怪的情况,发现一个会话异常,这个会话只是在执行一个简单的存储过程,里面使用了链接服务器(Linked Server)查询另外一台服务器数据(存储过程里面没有任何显性事务.UPDATE. ...
- 0035 Java学习笔记-注解
什么是注解 注解可以看作类的第6大要素(成员变量.构造器.方法.代码块.内部类) 注解有点像修饰符,可以修饰一些程序要素:类.接口.变量.方法.局部变量等等 注解要和对应的配套工具(APT:Annot ...
- 将自己的项目上传到github保管
一.首先需要生成gey-gen,因为github跟本地计算机要通过ssh传输的,详情见官方教程. 二.本地已有项目的情况:现在本地将项目git innit 初始化好,然后去到github上面初始化一个 ...
- [Penetration Testing Devil Training Camp Based on Metasploit] Learn & Practice
- Dipole Antenna : 2
Characteristics of dipole antenna. %% % characteristics of dipole antenna % author : Leon % email:ya ...
- Ioc和Ao使用扩展
一.Bean作用域 spring容器创建的时候,会将所有配置的bean对象创建出来,默认bean都是单例的.代码通过getBean()方法从容器获取指定的bean实例,容器首先会调用Bean类的无参构 ...
- BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2545 Solved: 1419[Submit][Sta ...
- python flask (一)
from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello World ...
- Asp.net 设置GridView自适应列宽不变形
动态绑定的GridView由于列数不固定,而列又太多,这样设置GridView固定宽度就不能满足需求了.为此整理了两种方法来达到GridView自适应列宽不变形的效果. //在GridView的行数据 ...
- .Net Core Logger 实现log写入本地文件系统
.net core 自带一个基础的logger框架Microsoft.Extensions.Logging. 微软默认实现了Microsoft.Extensions.Logging.Console.d ...