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名称,不 ...
随机推荐
- c++字符串输入格式总结
最近的几次笔试中,常常遇到一些输入的问题.下面说明一下几种情况. 1. 第一种就是常见的,输入数字序列,用空格分隔开,直到回车结束.这个之前一开始遇到的时候都是利用getline直接作为字符读入一行处 ...
- JPA的一对多,多对多用法
一.@OneToOne关系映射 JPA使用@OneToOne来标注一对一的关系. 实体 People :用户. 实体 Address:家庭住址. People 和 Address 是一对一的关系. 这 ...
- MySQL数据库索引的底层原理(二叉树、平衡二叉树、B-Tree、B+Tree)
1.MySQL数据库索引的底层原理 https://mp.weixin.qq.com/s/zA9KvCkkte2mTWTcDv7hUg
- springboot装配OkHttp组件
在SpringBoot应用中,发送Http通常我们使用RestTemplate,但有部分组件底层是使用OkHttp进行Http的操作,而且OKHttp也是一个很优秀的HTTP组件. RestTempa ...
- Android ANR log trace日志文件分析
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/qq_25804863/article/ ...
- sails 相关软件下载地址及命令
vscode1.40 https://vscode.cdn.azure.cn/stable/f359dd69833dd8800b54d458f6d37ab7c78df520/VSCodeUserS ...
- libFFM 与 python-libffm 安装遇到的一系列问题-解决方案
mac os x 环境下 libFFM 与 python-libffm的安装问题 Gcc 版本问题 : brew Clang 版本问题 : brew upgrade llvm 编译参数: 多核运行 o ...
- scrapy中的middleware
反反爬虫相关机制 Some websites implement certain measures to prevent bots from crawling them, with varying d ...
- Centos7.6使用yum安装PHP7.2
Centos7.6使用yum安装PHP7.2 1.安装源 安装php72w,是需要配置额外的yum源地址的,否则会报错不能找到相关软件包. php高版本的yum源地址,有两部分,其中一部分是epel- ...
- 脚本备份MySQL数据库和binlog日志
用Mysqldump实现全库备份+binlog的数据还原 首先是为mysql做指定库文件的全库备份 vim mysqlbak.sh #!/bin/bash #定义数据库目录,要能找到mysqldump ...