目录:

1.非托管方式

2.托管方式

3.介绍 extern "C"

4.介绍   DllImport

1.非托管方式

第一种,非托管方式:调用类和方法https://www.codeproject.com/Articles/18032/How-to-Marshal-a-C-Class

  非托管方式,只能调用函数,并且函数在extern "C"的体里面

  有一下几种方式,把函数都写了,把接口写了。

  1. //创建对象的方法
  2. extern "C" EXAMPLEUNMANAGEDDLL_API CUnmanagedTestClass* CreateTestClass()
  3. {
  4. return new CUnmanagedTestClass();
  5. }
  6. //释放对象
  7. extern "C" EXAMPLEUNMANAGEDDLL_API void DisposeTestClass(CUnmanagedTestClass* pObject)
  8. {
  9. if(pObject != NULL)
  10. {
  11. delete pObject;
  12. pObject = NULL;
  13. }
  14. }
  15. //调用函数
  16. extern "C" EXAMPLEUNMANAGEDDLL_API void CallPassInt(CUnmanagedTestClass* pObject, int nValue)
  17. {
  18. if(pObject != NULL)
  19. {
  20. pObject->PassInt(nValue);
  21. }
  22. }
  23. //调用函数
  24. extern "C" EXAMPLEUNMANAGEDDLL_API void CallPassString(CUnmanagedTestClass* pObject, char* pchValue);
    extern "C"{
  1. EXAMPLEUNMANAGEDDLL_API char* CallReturnString(CUnmanagedTestClass* pObject)
  1. }

C++的调用

  把生成的TestClassDLL.dll放到 bin/Debug/下,然后在C#中调用

  1. public class CSUnmanagedTestClass : IDisposable
  2. {
  3. #region PInvokes
  4. [DllImport("TestClassDLL.dll")]
  5. static private extern IntPtr CreateTestClass();
  6.  
  7. [DllImport("TestClassDLL.dll")]
  8. static private extern void DisposeTestClass(IntPtr pTestClassObject);
  9.  
  10. [DllImport("TestClassDLL.dll")]
  11. static private extern void CallPassInt(IntPtr pTestClassObject, int nValue);
  12. .
  13. .
  14. .
  15. #endregion PInvokes
  16.  
  17. #region Members
  18. private IntPtr m_pNativeObject;
  19. // Variable to hold the C++ class's this pointer
  20. #endregion Members
  21.  
  22. public CSUnmanagedTestClass()
  23. {
  24. // We have to Create an instance of this class through an exported
  25. // function
  26. this.m_pNativeObject = CreateTestClass();
  27. }
  28.  
  29. public void Dispose()
  30. {
  31. Dispose(true);
  32. }
  33.  
  34. protected virtual void Dispose(bool bDisposing)
  35. {
  36. if(this.m_pNativeObject != IntPtr.Zero)
  37. {
  38. // Call the DLL Export to dispose this class
  39. DisposeTestClass(this.m_pNativeObject);
  40. this.m_pNativeObject = IntPtr.Zero;
  41. }
  42.  
  43. if(bDisposing)
  44. {
  45. // No need to call the finalizer since we've now cleaned
  46. // up the unmanaged memory
  47. GC.SuppressFinalize(this);
  48. }
  49. }
  50.  
  51. // This finalizer is called when Garbage collection occurs, but only if
  52. // the IDisposable.Dispose method wasn't already called.
  53. ~CSUnmanagedTestClass()
  54. {
  55. Dispose(false);
  56. }
  57.  
  58. #region Wrapper methods
  59. public void PassInt(int nValue)
  60. {
  61. CallPassInt(this.m_pNativeObject, nValue);
  62. }
  63. .
  64. .
  65. .
  66. #endregion Wrapper methods
  67. }

2.托管方式

我手上有一个C++写的类(NativeClass),想在C#下调用这个类,可是C#是没有简单的像Dllimport这样的方法获取非托管C++ dll里的类。我的解决方法是,生成一个托管C++的dll,然后在C#下引用这个dll。因为托管代码与非托管代码是不能在一个文件里混编的,所以我必须将非托管C++写的NativeClass用托管C++的手段封装一下,然后生成一个dll,以供C#调用。

https://www.cnblogs.com/stemon/p/4246165.html

3.介绍 extern "C"

:https://www.cnblogs.com/xiangtingshen/p/10980055.html

extern "C"包含双重含义

  • 被extern "C"修饰的变量和函数是按照C语言方式进行编译和链接的:这点很重要!!!!
  • extern "C"的使用要点总结

    1,可以是如下的单一语句:

    1. extern "C" double sqrt(double);

    2,可以是复合语句, 相当于复合语句中的声明都加了extern "C"

    1. extern "C"
    2. {
    3. double sqrt(double);
    4. int min(int, int);
    5. }

    3,可以包含头文件,相当于头文件中的声明都加了extern "C" 

  1. extern "C"
  2. {
  3. include <cmath>
  4. }

  

4.介绍   DllImport

  https://www.cnblogs.com/fer-team/archive/2017/12/13/8033413.html

要使用DllImport需要引用命名空间: System.Runtime.InteropServices;
DllImport 属性定义
如下:

  1. namespace System.Runtime.InteropServices
  2. {
  3.   [AttributeUsage(AttributeTargets.Method)]
  4.   public class DllImportAttribute: System.Attribute
  5.   {
  6. public DllImportAttribute(string dllName){...} //定位参数为dllName
  7. public CallingConvention CallingConvention; //入口点调用约定
  8. public CharSet CharSet; //入口点采用的字符接
  9. public string EntryPoint; //入口点名称
  10. public bool ExactSpelling; //是否必须与指示的入口点拼写完全一致,默认false
  11. public bool PreserveSig; //方法的签名是被保留还是被转换
  12. public bool SetLastError; //FindLastError方法的返回值保存在这里
  13. public string Value {get {...}}
  14.   }
  15. }

说明:
1、DllImport只能放置在方法声明上。
2、DllImport具有单个定位参数:指定包含被导入方法的 dll 名称的 dllName 参数。
3、DllImport具有五个命名参数:
a、CallingConvention 参数指示入口点的调用约定。如果未指定CallingConvention,则使用默认值CallingConvention.Winapi。
b、CharSet参数指定用在入口点的字符集。如果未指定CharSet,则使用默认值CharSet.Auto。
c、EntryPoint参数给出dll中入口点的名称。如果未指定EntryPoint,则使用方法本身的名称。
d、ExactSpelling参数指示EntryPoint是否必须与指示的入口点的拼写完全匹配。如果未指定ExactSpelling,则使用默认值false。
e、PreserveSig参数指示方法的签名被保留还是被转换。当签名被转换时,它被转换为一个具有HRESULT返回值和该返回值的一个名为retval的附加输出参数的签名。如果未指定PreserveSig,则使用默认值true。
f、SetLastError参数指示方法是否保留Win32“上一错误”。如果未指定SetLastError,则使用默认值false。
4、它是一次性属性类。
5、用DllImport属性修饰的方法必须具有extern修饰符。

C# 调用 C++ dll的两种方式的更多相关文章

  1. C#动态调用WCF接口,两种方式任你选。

    写在前面 接触WCF还是它在最初诞生之处,一个分布式应用的巨作. 从开始接触到现在断断续续,真正使用的项目少之又少,更谈不上深入WCF内部实现机制和原理去研究,最近自己做一个项目时用到了WCF. 从这 ...

  2. SoapUI调用webservice实现的两种方式

    SoapUI用来做测试,已经是很多人做过的事情了,而且网上教程也很多.不过还是写下来,对比webservice协议与http协议脚本编写的不同. 首先测接口得有一个服务,刚好笔者所在项目做ESB集成. ...

  3. C++调用C代码的两种方式

    由于C++支持函数重载,在编译函数代码的时候会加上参数类型的信息,而C编译只有函数名信息,导致C++直接调用C代码在链接的时候会出现函数未定义的问题.解决这种问题有两种方法.方法一:在写C代码的时候考 ...

  4. Delphi 调用Dll的两种方式

    unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System ...

  5. vc导出调用dll的两种方式

    一.stdcall 1. #define  DLLEXPORT _declspec(dllexport) _stdcall, int DLLEXPORT func(const char *peer,u ...

  6. javascript消除字符串两边空格的两种方式,面向对象和函数式编程。python oop在调用时候的优点

    主要是javascript中消除字符串空格,比较两种方式的不同 //面向对象,消除字符串两边空格 String.prototype.trim = function() { return this.re ...

  7. 在基于MVC的Web项目中使用Web API和直接连接两种方式混合式接入

    在我之前介绍的混合式开发框架中,其界面是基于Winform的实现方式,后台使用Web API.WCF服务以及直接连接数据库的几种方式混合式接入,在Web项目中我们也可以采用这种方式实现混合式的接入方式 ...

  8. WCF 客户端调用服务操作的两种方法

    本节的主要内容:1.通过代理类的方式调用服务操作.2.通过通道的方式调用服务操作.3.代码下载 一.通过代理类的方式调用服务操作(两种方式添加代理类) 1.手动编写代理类,如下: 客户端契约: usi ...

  9. java中调用本地动态链接库(*.DLL)的两种方式详解和not found library、打包成jar,war包dll无法加载等等问题解决办法

    我们经常会遇到需要java调用c++的案例,这里就java调用DLL本地动态链接库两种方式,和加载过程中遇到的问题进行详细介绍 1.通过System.loadLibrary("dll名称,不 ...

随机推荐

  1. 冰多多团队-第五次Scrum会议

    冰多多团队-第五次Scrum会议 工作情况 团队成员 已完成任务 待完成任务 zpj 部分Action整合, 接入语音接口,整合项目解决兼容性问题 ASR bug修复 牛雅哲 跑通了科大讯飞语法识别的 ...

  2. 【JavaScript】frame跨域访问元素

    什么是跨frame访问元素呢?比如main.html中有如下代码: <frameset cols="50%,*"> <frame src="frame1 ...

  3. jetty源码下载

    jetty下载地址:https://www.eclipse.org/jetty/download.html Release         9.4.20.v20190813 .zip .tgz api ...

  4. Linux如何将未分配的硬盘挂载出来

    情景说明 客户给了几台服务器,说500G硬盘,但到手操作的时候,使用命令查看,发现只有不到200的硬盘 [root@localhost ~]# df -h Filesystem Size Used A ...

  5. python 3环境下,离线安装模块(modules)

    说明: 需要在环境中安装python的模块,但是无法联网,就通过在Pypi上下载离线模块的包进行安装 安装过程: 1.下载模块,如PyMySQL-0.9.3.tar.gz,下载地址:https://f ...

  6. 重温RabbitMQ

    RabbitMQ是用Erlang语言实现的,它有几个概念broker:消息队列服务器实体exchange:消息交换机,它指定消息按什么规则,路由到哪个队列queue:消息队列,每个消息都会被投入到一个 ...

  7. Deploy a plain HTTP registry

    当docker pull a.b.com/ubuntu:14.04的时候,如果提示:“Docker x509 insecure registry”之类的,说这个registry不安全的,如果就是想在a ...

  8. 没有可用的软件包 xxx,但是它被其它的软件包引用了

    在linux下apt安装软件,弹出这个错. 解决,更新下资源: sudo apt-get update

  9. OpenStack(二)——使用Kolla部署OpenStack-allinone云平台

    (1).Kolla概述 Kolla是OpenStack下用于自动化部署的一个项目,它基于docker和ansible来实现,其中docker主要负责镜像制作和容器管理,ansible主要负责环境的部署 ...

  10. Linux下查看占用CPU资源最多的几个进程

    linux下获取占用CPU资源最多的10个进程: ps aux|head -1;ps aux|grep -v PID|sort -rn -k +3|head linux下获取占用内存资源最多的10个进 ...