【转】 编写C#调用的C++DLL
最近一段时间,经常遇到这些问题,前一阵子研究了一下,没有记下来,没想到最近研究又有些不记得了,今天把它写下来以备忘。
一般我们提供给其他语言调用的DLL,都是用C或者C++编写,然后封装。我这边也是采用的C++。
首先有几个注意点:
、如果功能很简单,或者不使用第三方库(如MFC自带的库),建立一个win32的控制台程序就可以了,然后把项目生成改为DLL。值得一提的是,代码生成里面
运行时库分四种:
()多线程MTD(静态库,编译之后,你的lib带有调试功能)——> debug时用
()多线程MT(静态库,没有调试功能) ——> release时用
()多线程DLL MTD(动态库,带有调试功能) ——> debug时用
()多线程DLL MT(动态库,没有有调试功能)。 ——> release时用s
既然封装DLL,那调试的时候用(),发布的时候用()。
、设置为导出函数,并采用C风格。函数前加extern "C" __declspec(dllexport)。定义函数在退出前自己清空堆栈,在函数前加__stdcall。
如extern "C" __declspec(dllexport) int __stdcall add(int x,int y);
具备上述条件时,生成的DLL就含有导出函数的功能了,不过此时DLL中的函数名称不是规则的,使用编译器自定义的,可能是这样一个名字_add@,具体的可以用VS的Depends工具查看一下。
、把导出函数名称变为标准名称,需加模块定义文件,就是.def文件。
内容如下:(需要注释,前面加分号就可以了,注释需要单独行)
LIBRARY "TEST"
EXPORTS
;add函数
adds
LIBRARY 库名称
EXPORTS 需要导出的各个函数名称
重新编译之后,再用Depends工具看一下,函数已经变成标准add,而不是_add@。这个在动态加载时很有用,特别是在GetProcAddress函数寻找入库函数的时候。
、C#调用C++ DLL,介绍两种方法
()静态加载
[DllImport("TEST.dll", EntryPoint = "add")]
public int add(int x,int y);//与dll中一致
注意如果需要返回字符串可以这样
C++中
int getString(const char* source,char* dest);
C#中
int getString(string source,StringBuilder sbr);
切记调用的时候给StringBuilder 分配空间,否则会报错。
如dest 长度为10,可以这样。
StringBuilder sbr=new StringBuilder();
getString("hello",sbr);
如果你希望C++的dll还能被VB等语言调用,建议将字串写成com的形式
如
C++中
int getString(BSTR source,BSTR dest);//BSTR就是一个com形式的字符数组,相当于字符串
C#中
int getString(string source,StringBuilder sbr);
VB中
Declare Function getString Lib "TEST.dll" (ByVal source As String, ByVal dest As String) As Integer;
()动态加载
[DllImport("kernel32.dll")]
private extern static IntPtr LoadLibrary(String path);//path 就是dll路径 返回结果为0表示失败。
[DllImport("kernel32.dll")]
private extern static IntPtr GetProcAddress(IntPtr lib, String funcName);//lib是LoadLibrary返回的句柄,funcName 是函数名称 返回结果为0标识失败。
[DllImport("kernel32.dll")]
private extern static bool FreeLibrary(IntPtr lib);
//声明委托
delegate int ADD(int x,int y);
//使用动态加载
IntPtr hLib = LoadLibrary(dllPath);//加载函数
IntPtr apiFunction = GetProcAddress(hLib, apiName);//获取函数地址
int i = Marshal.GetLastWin32Error();
if (apiFunction.ToInt32() == )//0表示函数没找到
return null;
//获取函数接口,相当于函数指针
ADD add = (Delegate)Marshal.GetDelegateForFunctionPointer(apiFunction, typeof(ADD)) as ADD;
//调用函数
add(,);
//释放句柄
FreeLibrary(hLib );
最后,
)C++在返回字符串时,切记最后添加/,不然在C#等中调用,会显示部分乱码。
)C++动态申请的内存,需在出函数之前就必须释放,否则会报意想不到的错误。比如内存写入错误等等。
【转】 编写C#调用的C++DLL的更多相关文章
- delphi 基础之三 编写和调用dll文件
delphi 编写和调用dll文件 Windows 的执行文件可以划分为两种形式程序和动态连接库 (DLLs).一般程序运行是用.EXE文件,但应用程序有时也可以调用存储在DLL的函数. 在如下几 ...
- VB.NET中的DLL编写和调用的最简单示例
DLL(动态链接库)是一个很有用的东西,在开发大项目的时候显得非常重要,因为多人合作开发时,可以给每个人分配一个任务,用DLL完成,最后组合起来,就不会出现互相冲突的问题.这里给出最简单的DLL编写与 ...
- DLL DEF文件编写方法 VC++ 调用、调试DLL的方法 显式(静态)调用、隐式(动态)调用
DLL 文件编写方法: 1.建立DLL工程 2.声明.定义要导出的函数 BOOL WINAPI InitDlg( HWND hTabctrl,TShareMem* pTshare,CRect* prc ...
- DLL编写与调用全解
DLL编写与调用全解 DELPHI学习 2008-12-23 22:52 阅读8 评论0 字号: 大 中 小 第一章 为什么要使用动态链接库(DLL) top 提起DLL您一定不会 ...
- Node调用C++(dll)
最近开始搞毕设了,打算用自己拿手的js来搞,但是仿佛入坑了,Node还不是很熟.总之,兵来将挡,水来土掩嘛,带着问题学习才是最高效的. 折腾1:Node 调用 C++ 刚开始,虽然我老师把dll文件给 ...
- golang调用c++的dll库文件
最近使用golang调用c++的dll库文件,简单了解了一下,特作此笔记:一.DLL 的编制与具体的编程语言及编译器无关 dll分com的dll和动态dll,Com组件dll:不管是何种语言写的都可以 ...
- vs2010下C++调用lib或dll文件
注: DLL:表示链接库,包含dll,lib文件: dll: 表示my.dll文件 lib: 表示my.lib文件 C++ 调用.lib的方法: 一: 隐式的加载时链接,有三种方法 1 设置工程的 ...
- paip.java c# .net php python调用c++ c dll so windows api 总结
paip.java c# .net php python调用c++ c dll so windows api 总结 作者Attilax 艾龙, EMAIL:1466519819@qq.com 来 ...
- c++builder调用VC的dll以及VC调用c++builder的dll
解析__cdecl,__fastcall, __stdcall 的不同:在函数调用过程中,会使用堆栈,这三个表示不同的堆栈调用方式和释放方式. 比如说__cdecl,它是标准的c方法的堆栈调用方式,就 ...
随机推荐
- mysql limit分页查询效率
对于有大数据量的mysql表来说,使用LIMIT分页存在很严重的性能问题. 查询从第1000000之后的30条记录: SQL代码1:平均用时6.6秒 SELECT * FROM `cdb_posts` ...
- char* 与 char[] 的区别
"Hello world"作为静态字符串实际上存储在数据区,但写程序的人不知道这个地址,而程序本身知道.当某一函数以{ char p[] = "Hello world&q ...
- gitlab的安装和基本维护
基本介绍 GitLab是一个自托管的Git项目仓库,可以自己搭建个人代码管理的仓库,功能与github类似. 安装 操作系统:CentOS6.5 gitlab官网下载安装地址:https://abou ...
- winform程序开机自动启动
app.manifest <requestedExecutionLevel level="requireAdministrator" uiAccess="false ...
- asp.net 截屏
public class HomeController : Controller { // // GET: /Home/ static System.Windows.Forms.WebBrowser ...
- UITableView:可展开的 UITableView
针对 TableView,有些时候需要在点击 cell 时,展开这行 cell,显现出更多的选项或者全部内容等. 比较容易想到的处理方案就是利用 section,在未选择之前,每一行都是一个 sect ...
- exportfs命令 NFS客户端问题 FTP介绍 使用vsftpd搭建ftp
exportfs命令 • 常用选项 • -a 全部挂载或者全部卸载 • -r 重新挂载 • -u 卸载某一个目录 • -v 显示共享目录 • 以下操作在服务端上 • vim /etc/exports ...
- VS2010 正则批量替换头文件路径
最近在项目实践中,需要统一对工程头文件进行重构,具体要求是,将之前 #include "../../abc/def.h" 类似的头文件引用路径 替换为#include &q ...
- [转]Phantomjs实现获取网页快照并生成缩略图
Shell脚本实现获取网页快照并生成缩略图 这篇文章主要介绍了Shell脚本实现获取网页快照并生成缩略图,本文获取网页快照使用phantomjs.生成缩略图使用ImageMagick,需要的朋友可以参 ...
- iOS多版本多设备适配的问题
好吧,能找到这文章的,一般是接到了如下需求: 我是从raywenderlich抽了点内容出来做日记,另外,本文说的不是布局的适配,而是因为ios的升级带来的各版本代码上的不兼容. Deploymen ...