因为数组是引用类型,所以数组的处理根据数组元素的类型是否为“可直接传递到非托管代码”的类型而分为两种情况。主要目标是看内存是怎么变化的,是复制还是锁定。

数组中的元素是"可直接传递到非托管代码中"的类型

  这种类型很多,比如 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碎片--对数组的封送处理的更多相关文章

  1. p/invoke碎片--对类的封送处理

    主要是看默认封送处理行为 按类成员的类型是否为“可直接传递到非托管内存”的类型来分类;按照成员中是否有“可直接传递到非托管内存”的类型来讨论. 所有成员都是“可直接传递到非托管内存”的类型 托管代码和 ...

  2. C#调用C/C++动态库 封送结构体,结构体数组

    一. 结构体的传递 #define JNAAPI extern "C" __declspec(dllexport) // C方式导出函数 typedef struct { int ...

  3. C#调用C/C++动态库 封送结构体,结构体数组

    因为实验室图像处理的算法都是在OpenCV下写的,还有就是导航的算法也是用C++写的,然后界面部分要求在C#下写,所以不管是Socket通信,还是调用OpenCV的DLL模块,都设计到了C#和C++数 ...

  4. p/invoke 碎片-- 对字符串的处理

    字符串在内存中的的几种风格 字符串作为参数和返回值 参考 字符串在内存中的几种风格 所谓的风格,也就是字符串在内存中的存在形式.如何存放的,占据内存的大小,还有存放顺序等.在不同的编程语言和不同的平台 ...

  5. p/invoke碎片,对结构体的处理

    结构体的一些相关知识 可直接转换类类型,比如int类型,在托管代码和非托管代码中占据内存大小 和意义都是一个样的. 结构体封送的关键是:在托管代码和非托管代码中定义的一致性.什么是定义的一致性?包括结 ...

  6. [原]C#与非托管——封送和自动封送

    之前说到了如何从C函数声明通过简单的查找替换生成一份C#的静态引用声明(C#与非托管——初体验),因为只是简单说明,所以全部采用的是基础类型匹配和自动封送.自动封送虽然能省去我们不少编码时间,但如果不 ...

  7. C# 互操作性入门系列(三):平台调用中的数据封送处理

    好文章搬用工模式启动ing ..... { 文章中已经包含了原文链接 就不再次粘贴了 言明 改文章是一个系列,但只收录了2篇,原因是 够用了 } --------------------------- ...

  8. [转]C# 互操作性入门系列(三):平台调用中的数据封送处理

    参考网址:https://www.cnblogs.com/FongLuo/p/4512738.html C#互操作系列文章: C# 互操作性入门系列(一):C#中互操作性介绍 C# 互操作性入门系列( ...

  9. C 碎片五 数组

    构造类型数据是有基本类型数据按照一定规则组成的.数组,结构体,共用体都属于构造类型的数据.数组是有序数据的集合,C语言数组中的每一个元素都属于同一个数据类型,用数组名和下标来唯一确定数组中的元素. 一 ...

随机推荐

  1. 用SVN check out项目后第三方库丢失

    曾经用Cornerstone check out 一份项目下来,但其中第三方.a库始终丢失,项目报错,研究后找到了以下解决方法: 首先,Xcode默认忽略.a 文件.所以无法提交到svn服务器,但是很 ...

  2. nodejs---修改文件名字

    D:\node\update_name目录有如下文件: 1:文件夹:icons 2:js文件:update-name.js js文件代码: // 引入fs文件处理模块var fs = require( ...

  3. The user specified as a definer ('root'@'%') does not exist 异常解决

    参考:http://www.cnblogs.com/Magicam/archive/2013/07/22/3207382.html 权限问题,授权 给 root  所有sql 权限 mysql> ...

  4. python快速生成注释文档的方法

    python快速生成注释文档的方法 今天将告诉大家一个简单平时只要注意的小细节,就可以轻松生成注释文档,也可以检查我们写的类方法引用名称是否重复有问题等.一看别人专业的大牛们写的文档多牛多羡慕,不用担 ...

  5. Jsoup问题---获取http协议请求失败 org.jsoup.UnsupportedMimeTypeException: Unhandled content type. Must be text/*, application/xml, or application/xhtml+xml.

    Jsoup问题---获取http协议请求失败 1.问题:用Jsoup在获取一些网站的数据时,起初获取很顺利,但是在访问某浪的数据是Jsoup报错,应该是请求头里面的请求类型(ContextType)不 ...

  6. 2-kvm创建快照以及网卡绑定

    kvm创建快照以及网卡绑定 创建node1 查看node1 进入到kvm的配置文件里 将rhcs文件复制一份取名为node1.xml 通过这个命令随机生成一个uuid 然后就进入node1.xml里修 ...

  7. 关闭selinux

    1.查看SELinux状态:getenforce Enforcing(启动) disable(禁用) 1.禁用SELinux(重启后依然生效) 修改 vi /etc/sysconfig/selinux ...

  8. Spring 事务详解

    实现购买股票案例: 一.引入JAR文件: 二.开始搭建分层架构---创建账户(Account)和股票(Stock)实体类 Account: ? 1 2 3 4 5 6 7 8 9 10 11 12 1 ...

  9. Dijkstra算法(三)之 Java详解

    http://www.cnblogs.com/skywang12345/p/3711516.html

  10. 解读ASP.NET 5 & MVC6系列(9):日志框架

    框架介绍 在之前的.NET中,微软还没有提供过像样的日志框架,目前能用的一些框架比如Log4Net.NLog.CommonLogging使用起来多多少少都有些费劲,和java的SLF4J根本无法相比. ...