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

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

  这种类型很多,比如 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. yii2 RESTful api的详细使用

    作者:白狼 出处:http://www.manks.top/yii2-restful-api.html 本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则 ...

  2. sqoop:Failed to download file from http://hdp01:8080/resources//oracle-jdbc-driver.jar due to HTTP error: HTTP Error 404: Not Found

    环境:ambari2.3,centos7,sqoop1.4.6 问题描述:通过ambari安装了sqoop,又添加了oracle驱动配置,如下: 保存配置后,重启sqoop报错:http://hdp0 ...

  3. shell 脚本之循环使用 for while 详解

    任何一种编程语言中循环是比不可少的,当然 shell 脚本也少不了循环语句,包括 for 语句. while 语句.文中主要以实际用例来说明 for while 都有哪些常见的使用方法和技巧. 一.f ...

  4. how2heap分析系列:2_fastbin_dup

    源码 #include <stdio.h> #include <stdlib.h> int main() { printf("This file demonstrat ...

  5. Tensorflow 官方版教程中文版

    2015年11月9日,Google发布人工智能系统TensorFlow并宣布开源,同日,极客学院组织在线TensorFlow中文文档翻译.一个月后,30章文档全部翻译校对完成,上线并提供电子书下载,该 ...

  6. C#基础---Queue(队列)的应用

       Queue队列,特性先进先出. 在一些项目中我们会遇到对一些数据的Check,如果数据不符合条件将会把不通过的信息返回到界面.但是对于有的数据可能会Check很多条件,如果一个数据一旦很多条件不 ...

  7. [LeetCode] Best Time to Buy and Sell Stock III 买股票的最佳时间之三

    Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...

  8. VS2015下如何用编译、调试程序。

    VS2015下如何用编译.调试程序. (通过实践给出截图) 安装步骤: 下载安装网址[VS2015下载地址](http://www.ithome.com/html/win10/164028.htm) ...

  9. 深入理解numpy

    一.为啥需要numpy python虽然说注重优雅简洁,但它终究是需要考虑效率的.别说运行速度不是瓶颈,在科学计算中运行速度就是瓶颈. python的列表,跟java一样,其实只是一维列表.一维列表相 ...

  10. from表单提交数组

    页面代码: function submitForm(){ var categoryArray = new Array(); var $ss = $("select[name=industry ...