之前说到了如何从C函数声明通过简单的查找替换生成一份C#的静态引用声明(C#与非托管——初体验),因为只是简单说明,所以全部采用的是基础类型匹配和自动封送。自动封送虽然能省去我们不少编码时间,但如果不理解自动封送背后的实际行为,那就如同看魔术师的黑盒子,知其然不知其所以然。而且,自动封送也不是永远有效的万能药,因此这里记录一下封送相关的理解。

非基础类型在C#与Native代码交互时需要进行封送处理,一般的封送处理方式有内存拷贝、固定内存地址,总结如下:

  1. 针对string,可以使用Marshal.StringToHGlobalAnsi、Marshal.StringToHGlobalAuto、Marshal.StringToHGlobalUni把string封送到非托管函数,之后需要调用Marshal.FreeHGlobal释放内存;或者使用Marshal.PtrToStringAnsi、Marshal.PtrToStringAuto、Marshal.PtrToStringUni从非托管函数里面取出string。

  2. 针对byte[](或基础类型的数组),可以使用Marshal.Copy从byte[]拷贝封送到非托管函数或者从非托管函数拷贝封送到byte[]。此外从byte[]封送到非托管函数还可以采取固定内存直接传送byte[]的原始地址(省去了申请内存和拷贝的开销,速度更快),方法是使用GCHandle并指定GCHandleType.Pinned类型。

  3. 针对委托,可以使用Marshal.GetFunctionPointerForDelegate从delegate封送到非托管函数,或者使用Marshal.GetDelegateForFunctionPointer从非托管函数里面取出。和byte[]一样,在封送到非托管函数时需要确保GC不要回收委托(需要保持引用但不需要Pinned)。

  4. 针对结构体,可以在C#中按一样的顺序和对应的数据类型声明一个同样的struct(只能使用基础类型和固定长度的数组),并且标记StructLayout的LayoutKind.Sequential属性,然后使用Marshal.StructureToPtr和Marshal.PtrToStructure进行封送。

  5. C#的对象不能在Native中进行处理,只能保存以待之后再传回给C#调用,保存的方式为C#用GCHandle引用对象,然后把GCHandle转成IntPtr,传给Native作为指针保存。

当C#声明的extern函数返回类型和参数类型中有托管类型时(如string、byte[]、委托等),就会进行自动封送处理,因此可以省写大部分的封送代码。不过有几种情况还是需要手动进行封送的,如:

  1. string的编码是utf8之类的非ansi非utf16编码,则必须手动进行封送同时转换编码。
  2. 委托转换成函数指针的操作比较耗时,如果有频繁的对同一委托进行封送调用,则预存转换后的结果能够很显著的提升性能。

[原]C#与非托管——封送和自动封送的更多相关文章

  1. [原]C#与非托管——初体验

    P/Invokes初看起来非常简单,利用DllImport进行extern函数的声明,程序就可以在调用extern函数的时候自动查询调用到对应的非托管函数,有些类似Java的native函数,但更为简 ...

  2. [原]C#与非托管——动机

    Unity3D采用C#作为脚本开发语言,本来是可以直接提供代码局部更新机制的,可惜Mono和Unity3D迫于苹果的压力,在iOS上采用AOT模式运行,断绝了代码局部更新的路(任何一个具有很高知名度的 ...

  3. (转)C#调用非托管Win 32 DLL

    转载学习收藏,原文地址http://www.cnblogs.com/mywebname/articles/2291876.html 背景 在项目过程中,有时候你需要调用非C#编写的DLL文件,尤其在使 ...

  4. VB.NET 内存指针和非托管内存的应用

    介绍 Visual Basic 从来不像在C或C++里一样灵活的操纵指针和原始内存.然而利用.NET框架中的structures 和 classes,可以做许多类似的事情.它们包括 IntPtr,   ...

  5. C#引用非托管.dll

    C#里调用非托管的Dll 今天花了一些精力来调查了一下C#里调用非托管的Dll,C#里调用非托管的Dll要使用P/Invoke平台调用技术, 这里先简单介绍一下P/Invoke平台调用技术.    由 ...

  6. 在VS2010上使用C#调用非托管C++生成的DLL文件

    背景 在项目过程中,有时候你需要调用非C#编写的DLL文件,尤其在使用一些第三方通讯组件的时候,通过C#来开发应用软件时,就需要利用DllImport特性进行方法调用.本篇文章将引导你快速理解这个调用 ...

  7. [转]C# 之DLL调用(托管与非托管)

    每种编程语言调用DLL的方法都不尽相同,在此只对用C#调用DLL的方法进行介绍.首先,您需要了解什么是托管,什么是非托管.一般可以认为:非托管代码主要是基于win 32平台开发的DLL,activeX ...

  8. 非托管C++互操作

    .NET简谈互操作(一:开篇介绍) .NET简谈互操作(二:先睹为快) .NET简谈互操作(三:基础知识之DllImport特性) .NET简谈互操作(四:基础知识之Dispose非托管内存) .NE ...

  9. 托管DLL和非托管DLL的区别

    首先解释一下,托管DLL和非托管DLL的区别.狭义解释讲,托管DLL就在Dotnet环境生成的DLL文件.非托管DLL不是在Dotnet环 境生成的DLL文件. 托管DLL文件,可以在Dotnet环境 ...

随机推荐

  1. BZOJ 1009 :[HNOI2008]GT考试(KPM算法+dp+矩阵快速幂)

    这道到是不用看题解,不过太经典了,早就被剧透一脸了 这道题很像ac自动机上的dp(其实就是) 然后注意到n很大,节点很小,于是就可以用矩阵快速幂优化了 时间复杂度为o(m^3 *log n); 蒟蒻k ...

  2. 归纳篇(一)CSS的position定位和float浮动

    近期会更新一系列博客,对基础知识再度做个巩固和梳理. 一.position定位 (一):position的属性 1.absolute:生成绝对定位的元素,相对于最近一级定位不是static的父元素来进 ...

  3. 使用Python以优雅的方式实现根据shp数据对栅格影像进行切割

    目录 前言 涉及到的技术 优雅切割 总结 一.前言        前面一篇文章(使用Python实现子区域数据分类统计)讲述了通过geopandas库实现对子区域数据的分类统计,说白了也就是如何根据一 ...

  4. angular : ng-options

    基本调用,得到name 属性 <select ng-model="target" ng-options="obj.name as obj.name for obj ...

  5. 强化学习读书笔记 - 06~07 - 时序差分学习(Temporal-Difference Learning)

    强化学习读书笔记 - 06~07 - 时序差分学习(Temporal-Difference Learning) 学习笔记: Reinforcement Learning: An Introductio ...

  6. I3D Next-Gen Game Development with Unity3D Vol I学习笔记(上)

    这部教程主题是讲述如何在Unity中安放模型以及对场景进行优化(面对的是次世代平台).第二章看到一半,看不下,索性直接凭借Maya和Torque的经验自己操作. 看教程总结的原则如下(or tips) ...

  7. vbs文件小技巧

    vbs文件介绍: VBS是基于Visual Basic的脚本语言.VBS的全称是:Microsoft Visual Basic Script Editon.(微软公司可视化BASIC脚本版). 可以新 ...

  8. Android -- 仿小红书欢迎界面

    1,觉得小红书的欢迎界面感觉很漂亮,就像来学习学习一下来实现类似于这种效果  原效果图如下: 2,根据效果我们来一点点分析 第一步:首先看一下我们的主界面布局文件视图效果如下: main_activi ...

  9. ionic 添加新module

    angular.module 引入新的module: 1. 在index.html中需要引入必须的js文件2. app.js: angular.module('starter', ['ionic',' ...

  10. Mutillidae在kali linux上的安装

    XAMPP:下载地址(https://www.apachefriends.org/download.html) Mutillidae:下载地址(http://sourceforge.net/proje ...