C# 调用 C++ dll的两种方式
目录:
1.非托管方式
2.托管方式
3.介绍 extern "C"
4.介绍 DllImport
1.非托管方式
第一种,非托管方式:调用类和方法https://www.codeproject.com/Articles/18032/How-to-Marshal-a-C-Class
非托管方式,只能调用函数,并且函数在extern "C"的体里面
有一下几种方式,把函数都写了,把接口写了。
- //创建对象的方法
- extern "C" EXAMPLEUNMANAGEDDLL_API CUnmanagedTestClass* CreateTestClass()
- {
- return new CUnmanagedTestClass();
- }
- //释放对象
- extern "C" EXAMPLEUNMANAGEDDLL_API void DisposeTestClass(CUnmanagedTestClass* pObject)
- {
- if(pObject != NULL)
- {
- delete pObject;
- pObject = NULL;
- }
- }
- //调用函数
- extern "C" EXAMPLEUNMANAGEDDLL_API void CallPassInt(CUnmanagedTestClass* pObject, int nValue)
- {
- if(pObject != NULL)
- {
- pObject->PassInt(nValue);
- }
- }
- //调用函数
- extern "C" EXAMPLEUNMANAGEDDLL_API void CallPassString(CUnmanagedTestClass* pObject, char* pchValue);
extern "C"{
- EXAMPLEUNMANAGEDDLL_API char* CallReturnString(CUnmanagedTestClass* pObject)
- }
C++的调用
把生成的TestClassDLL.dll放到 bin/Debug/下,然后在C#中调用
- public class CSUnmanagedTestClass : IDisposable
- {
- #region PInvokes
- [DllImport("TestClassDLL.dll")]
- static private extern IntPtr CreateTestClass();
- [DllImport("TestClassDLL.dll")]
- static private extern void DisposeTestClass(IntPtr pTestClassObject);
- [DllImport("TestClassDLL.dll")]
- static private extern void CallPassInt(IntPtr pTestClassObject, int nValue);
- .
- .
- .
- #endregion PInvokes
- #region Members
- private IntPtr m_pNativeObject;
- // Variable to hold the C++ class's this pointer
- #endregion Members
- public CSUnmanagedTestClass()
- {
- // We have to Create an instance of this class through an exported
- // function
- this.m_pNativeObject = CreateTestClass();
- }
- public void Dispose()
- {
- Dispose(true);
- }
- protected virtual void Dispose(bool bDisposing)
- {
- if(this.m_pNativeObject != IntPtr.Zero)
- {
- // Call the DLL Export to dispose this class
- DisposeTestClass(this.m_pNativeObject);
- this.m_pNativeObject = IntPtr.Zero;
- }
- if(bDisposing)
- {
- // No need to call the finalizer since we've now cleaned
- // up the unmanaged memory
- GC.SuppressFinalize(this);
- }
- }
- // This finalizer is called when Garbage collection occurs, but only if
- // the IDisposable.Dispose method wasn't already called.
- ~CSUnmanagedTestClass()
- {
- Dispose(false);
- }
- #region Wrapper methods
- public void PassInt(int nValue)
- {
- CallPassInt(this.m_pNativeObject, nValue);
- }
- .
- .
- .
- #endregion Wrapper methods
- }
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,可以是如下的单一语句:
- extern "C" double sqrt(double);
2,可以是复合语句, 相当于复合语句中的声明都加了extern "C"
- extern "C"
- {
- double sqrt(double);
- int min(int, int);
- }
3,可以包含头文件,相当于头文件中的声明都加了extern "C"
- extern "C"
- {
- #include <cmath>
- }
4.介绍 DllImport
https://www.cnblogs.com/fer-team/archive/2017/12/13/8033413.html
要使用DllImport需要引用命名空间: System.Runtime.InteropServices;
DllImport 属性定义
如下:
- namespace System.Runtime.InteropServices
- {
- [AttributeUsage(AttributeTargets.Method)]
- public class DllImportAttribute: System.Attribute
- {
- public DllImportAttribute(string dllName){...} //定位参数为dllName
- public CallingConvention CallingConvention; //入口点调用约定
- public CharSet CharSet; //入口点采用的字符接
- public string EntryPoint; //入口点名称
- public bool ExactSpelling; //是否必须与指示的入口点拼写完全一致,默认false
- public bool PreserveSig; //方法的签名是被保留还是被转换
- public bool SetLastError; //FindLastError方法的返回值保存在这里
- public string Value {get {...}}
- }
- }
说明:
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的两种方式的更多相关文章
- C#动态调用WCF接口,两种方式任你选。
写在前面 接触WCF还是它在最初诞生之处,一个分布式应用的巨作. 从开始接触到现在断断续续,真正使用的项目少之又少,更谈不上深入WCF内部实现机制和原理去研究,最近自己做一个项目时用到了WCF. 从这 ...
- SoapUI调用webservice实现的两种方式
SoapUI用来做测试,已经是很多人做过的事情了,而且网上教程也很多.不过还是写下来,对比webservice协议与http协议脚本编写的不同. 首先测接口得有一个服务,刚好笔者所在项目做ESB集成. ...
- C++调用C代码的两种方式
由于C++支持函数重载,在编译函数代码的时候会加上参数类型的信息,而C编译只有函数名信息,导致C++直接调用C代码在链接的时候会出现函数未定义的问题.解决这种问题有两种方法.方法一:在写C代码的时候考 ...
- Delphi 调用Dll的两种方式
unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System ...
- vc导出调用dll的两种方式
一.stdcall 1. #define DLLEXPORT _declspec(dllexport) _stdcall, int DLLEXPORT func(const char *peer,u ...
- javascript消除字符串两边空格的两种方式,面向对象和函数式编程。python oop在调用时候的优点
主要是javascript中消除字符串空格,比较两种方式的不同 //面向对象,消除字符串两边空格 String.prototype.trim = function() { return this.re ...
- 在基于MVC的Web项目中使用Web API和直接连接两种方式混合式接入
在我之前介绍的混合式开发框架中,其界面是基于Winform的实现方式,后台使用Web API.WCF服务以及直接连接数据库的几种方式混合式接入,在Web项目中我们也可以采用这种方式实现混合式的接入方式 ...
- WCF 客户端调用服务操作的两种方法
本节的主要内容:1.通过代理类的方式调用服务操作.2.通过通道的方式调用服务操作.3.代码下载 一.通过代理类的方式调用服务操作(两种方式添加代理类) 1.手动编写代理类,如下: 客户端契约: usi ...
- java中调用本地动态链接库(*.DLL)的两种方式详解和not found library、打包成jar,war包dll无法加载等等问题解决办法
我们经常会遇到需要java调用c++的案例,这里就java调用DLL本地动态链接库两种方式,和加载过程中遇到的问题进行详细介绍 1.通过System.loadLibrary("dll名称,不 ...
随机推荐
- 冰多多团队-第五次Scrum会议
冰多多团队-第五次Scrum会议 工作情况 团队成员 已完成任务 待完成任务 zpj 部分Action整合, 接入语音接口,整合项目解决兼容性问题 ASR bug修复 牛雅哲 跑通了科大讯飞语法识别的 ...
- 【JavaScript】frame跨域访问元素
什么是跨frame访问元素呢?比如main.html中有如下代码: <frameset cols="50%,*"> <frame src="frame1 ...
- jetty源码下载
jetty下载地址:https://www.eclipse.org/jetty/download.html Release 9.4.20.v20190813 .zip .tgz api ...
- Linux如何将未分配的硬盘挂载出来
情景说明 客户给了几台服务器,说500G硬盘,但到手操作的时候,使用命令查看,发现只有不到200的硬盘 [root@localhost ~]# df -h Filesystem Size Used A ...
- python 3环境下,离线安装模块(modules)
说明: 需要在环境中安装python的模块,但是无法联网,就通过在Pypi上下载离线模块的包进行安装 安装过程: 1.下载模块,如PyMySQL-0.9.3.tar.gz,下载地址:https://f ...
- 重温RabbitMQ
RabbitMQ是用Erlang语言实现的,它有几个概念broker:消息队列服务器实体exchange:消息交换机,它指定消息按什么规则,路由到哪个队列queue:消息队列,每个消息都会被投入到一个 ...
- Deploy a plain HTTP registry
当docker pull a.b.com/ubuntu:14.04的时候,如果提示:“Docker x509 insecure registry”之类的,说这个registry不安全的,如果就是想在a ...
- 没有可用的软件包 xxx,但是它被其它的软件包引用了
在linux下apt安装软件,弹出这个错. 解决,更新下资源: sudo apt-get update
- OpenStack(二)——使用Kolla部署OpenStack-allinone云平台
(1).Kolla概述 Kolla是OpenStack下用于自动化部署的一个项目,它基于docker和ansible来实现,其中docker主要负责镜像制作和容器管理,ansible主要负责环境的部署 ...
- Linux下查看占用CPU资源最多的几个进程
linux下获取占用CPU资源最多的10个进程: ps aux|head -1;ps aux|grep -v PID|sort -rn -k +3|head linux下获取占用内存资源最多的10个进 ...