1.   我只是粗浅的学习过一些C++语法, 变量类型等基础内容, 如有不对的地方还望指出. 如果你跟我一样, 对指针操作不了解, 对封装C++动态库头疼的话, 下面内容还是有帮助的.
       转载请注明出处: http://www.cnblogs.com/zaiyuzhong/p/Csharp-package-Cplusplus-dll.html
  2.  
  3.   首先给一个类型转换的表, 这个表可能跟使用时具体情况有关, 仅供参考, 点击这里查看.
  4.  
  5.   1. C++变量类型大小写问题:
      一种是小写的, 比如char. 这种是系统定义的(关键字); 另一种是CHAR, 这个是自定义的, 有说这个是宏, 有说这个在VC++里是.Net定义的, 具体怎样我还没遇到过, 没有例子供研究. C++是大小写敏感的.
  6.  
  7.   2. int的长度问题:
      int的长度和编译器是有关系的. 如果动态库和封装代码由同一个编译器编译运行时, 可以不考虑转换int长度.
      
      3. 结构体成员的长度问题:
    不好描述, 举个例子:
      C++代码:
      typedef struct Result
      {
        char color[8];
      }
      对应C#代码:
      public struct Result
      {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        public byte[] color;
      }
      //C#中public修饰符可根据需要修改为其他访问修饰符.
    在调用前可先对数据长度进行验证后再调用.
      
      4. 指针问题:
      有两种情况, 一种是封装C++函数时, 参数有指针类型的, 如果该参数是引用类型, 那么在C#中使用该参数时传递的也是变量指针(引用), 所以不用处理; 如果该参数是结构类型, 如int* , 封装时需要表示为ref, 例如:
    C++: int InitSDK(Config* pConfig); //Config是结构体;
    C# : public int InitSDK(ref Config pConfig); //int类型是否修改参见上述问题2;
  8.  
  9.   另外一种情况比较麻烦, C++函数需要给他分配一块内存空间:
    C++: int RecogImage(const unsigned char* pbyBits, Result* pResult);
       // pbyBits[in] 指向内存图像数据的指针,数据格式为输入图像的格式;
       // pResult[out] 识别结果数组, 调用方开辟pResult[nResultNum]内存;(注: 这两行注释是文档上的函数说明)
    Result是动态库定义的结构体, nResultNum是自己定义的变量, 数值与这里无关, 测试后发现声明参数类型为数组是不行的.
    C#: [DllImport("dll路径")]
      public static extern int RecogImage(IntPtr pbyBits, IntPtr pResult);
      // 这里的IntPtr虽然也是结构体, 但由于它本身就代表一个指针所以不用ref;
  10.  
  11. 这个方法的调用方法如下, 开辟内存和读取识别结果麻烦点:
  1. using System.Drawing;
  2. using System.Drawing.Imaging;
  3.  
  4. //开辟识别结果数组内存
  5. int nResultNum = ; // 数值与代码无关
  6. var result = new Result();
  7. var rSize = Marshal.SizeOf(result);
  8. var resultsPtr = Marshal.AllocHGlobal(rSize * nResultNum);
  9.  
  10. //获取图像数据指针
  11. var image = new Bitmap("路径");
  12. var bmpData = image.LockBits(new Rectangle(, , image.Width, image.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
  13.  
  14. //识别图像
  15. var r = PlateSDK.RecogImage(bmpData.Scan0, resultsPtr);
  16.  
  17. //读取识别结果
  18. if(r != ) return; // 识别失败, r为错误编号;
  19. else
  20. {
  21. var results = new Result[nResultNum];
  22. for(int i = ; i < nResultNum; i++)
  23. results[i] = (Result)Marshal.PtrToStructure(results + rSize * i, typeof(Result));
  24. } // results 就是识别结果数组
  1.  

嗯, 其中3/4是我遇到比较麻烦的, 需要熟悉 Marshal(msdn), IntPtr(msdn) 和 MarshalAs(msdn).

C#调用C++动态库方法及动态库封装总结的更多相关文章

  1. 三种dedecms调用相关文章的方法

    在文章的末尾或侧边栏添加相关文章可以提高用户的黏度,提高pv,增加se的好印象(哈哈),那么dedecms如何调用相关文章呢?有三种方法可以实现. 第一种dedecms调用相关文章的方法,用默认的li ...

  2. Java调用动态库方法说明-最详细

    Java不能直接调用由c或者c++写得dll(TF_ID.dll),所以只能采用jni得方法,一步一步生成符合规范得dll文件(假设叫FANGJIAN.dll),在FANGJIAN.dll这个文件里来 ...

  3. linux下java调用.so动态库方法2: JNA

    摘自:http://blog.csdn.net/todorovchen/article/details/21319033 另请参见: http://blog.sina.com.cn/s/blog_8c ...

  4. 6.关于QT中的内存管理,动态的制作,动态库的调用,静态库的制作

     一  QT的内存管理 1  QT中的内存管理是QObject来管理的 2  QT中的内存管理没有cocos2dx中的引用计数 3  组件能够指定父对象 QTimer *timer = QTime ...

  5. c++动态库封装及调用(3、windows下动态库调用)

    1.DLL的隐式调用 隐式链接采用静态加载的方式,比较简单,需要.h..lib..dll三件套.新建“控制台应用程序”或“空项目”.配置如下: 项目->属性->配置属性->VC++ ...

  6. windows中静态库lib和动态dll的区别及使用方法

    1. 静态库lib和动态dll的区别 1.1 项目类型 VS在建Win32项目时,有以下选项: windows应用程序控制台应用程序DLL静态库最后两个类型:DLL和静态库,这两种项目类型是不可以单独 ...

  7. 使用runtime给类动态添加方法并调用 - class_addMethod

    上手开发 iOS 一段时间后,我发现并不能只着眼于完成需求,利用闲暇之余多研究其他的开发技巧,才能在有限时间内提升自己水平.当然,“其他开发技巧”这个命题对于任何一个开发领域都感觉不找边际,而对于我来 ...

  8. new关键字在虚方法的动态调用中的阻断作用

    关于new关键字在虚方法动态调用中的阻断作用,也有了更明确的理论基础.在子类方法中,如果标记 new 关键字,则意味着隐藏基类实现,其实就是创建了与父类同名的另一个方法,在编译中这两个方法处于动态方法 ...

  9. Delphi - Windows系统下,Delphi调用API函数和7z.dll动态库,自动把文件压缩成.tar.gz格式的文件

    项目背景 应欧美客户需求,需要将文件压缩成.tar.gz格式的文件,并上传给客户端SFTP服务器. 你懂的,7-Zip软件的显著特点是文件越大压缩比越高,在Linux系统上相当于我们Windows系统 ...

随机推荐

  1. ES6学习笔记一

    块级作用域:在ES5中只有全局作用域与函数作用域,ES6中新增的块级作用域避免变量的覆盖与泄露.考虑到代码运行环境,在块级作用域中应避免声明函数,最好用函数表达式的方式声明. let与const:le ...

  2. 耿丹CS16-2班第五次作业汇总

    Deadline: 2016-10-26 23:59 作业内容 实验4-1 求1到20的阶乘的和,其中求阶乘用函数完成. 实验4-2 写一个判素数的函数,在主函数输入一个整数,输出其是否是素数的信息. ...

  3. mac os设置root密码

    不知怎么忘记mac os系统的root密码了 方法一: 首先,启动机器,启动时按住Apple和S键,以单用户模式(single user mode)进入系统.输入:mount -uw / 然后回车.输 ...

  4. 高性能MySQL(五):查询性能优化

    当向MySQL 发送一个请求的时候MySQL 到底做了什么? 1.客户端发送一条查询给服务器 2.服务器先检查查询缓存,如果命中了缓存,则立即返回存储在缓存中的结果.否则进入下一阶段 3.服务器端进行 ...

  5. php关于ob_start('ob_gzhandler')启用GZIP压缩的bug

    如果使用ob_start("ob_gzhandler"); 则ob_clean()后面的输出将不显示,这是个bug,可以用ob_end_clean();ob_start(" ...

  6. [MySQL]MySQL之权限管理

    一.MySQL权限简介 关于mysql的权限简单的理解就是mysql允许你做你全力以内的事情,不可以越界.比如只允许你执行select操作,那么你就不能执行update操作.只允许你从某台机器上连接m ...

  7. box-shadow、drop-shadow 和 text-shadow

    1. box-shadow 合阴影, 对象选择器 {box-shadow:[投影方式] X轴偏移量 Y轴偏移量阴影模糊半径 阴影扩展半径 阴影颜色} box-shadow属性的参数设置取值: 阴影类型 ...

  8. [转]utf8编码原理详解

    from : http://blog.csdn.net/baixiaoshi/article/details/40786503 很久很久以前,有一群人,他们决定用8个可以开合的晶体管来组合成不同的状态 ...

  9. MongoVue中Collections无法显示的问题

    问题描述: 通过Python向MongoDB写入数据后,MongoVue中Collections无法显示的问题 原因: Mongodb 3.0之后默认的 storageEngine为wiredTige ...

  10. vue2.0环境搭建

    1.安装node.js(官网) 2.安装淘宝镜像  npm install -g cnpm --registry=https://registry.npm.taobao.org 3.安装webpack ...