最近一段时间,经常遇到这些问题,前一阵子研究了一下,没有记下来,没想到最近研究又有些不记得了,今天把它写下来以备忘。

一般我们提供给其他语言调用的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的更多相关文章

  1. delphi 基础之三 编写和调用dll文件

    delphi 编写和调用dll文件   Windows 的执行文件可以划分为两种形式程序和动态连接库 (DLLs).一般程序运行是用.EXE文件,但应用程序有时也可以调用存储在DLL的函数. 在如下几 ...

  2. VB.NET中的DLL编写和调用的最简单示例

    DLL(动态链接库)是一个很有用的东西,在开发大项目的时候显得非常重要,因为多人合作开发时,可以给每个人分配一个任务,用DLL完成,最后组合起来,就不会出现互相冲突的问题.这里给出最简单的DLL编写与 ...

  3. DLL DEF文件编写方法 VC++ 调用、调试DLL的方法 显式(静态)调用、隐式(动态)调用

    DLL 文件编写方法: 1.建立DLL工程 2.声明.定义要导出的函数 BOOL WINAPI InitDlg( HWND hTabctrl,TShareMem* pTshare,CRect* prc ...

  4. DLL编写与调用全解

    DLL编写与调用全解 DELPHI学习   2008-12-23 22:52   阅读8   评论0   字号: 大  中  小 第一章 为什么要使用动态链接库(DLL) top 提起DLL您一定不会 ...

  5. Node调用C++(dll)

    最近开始搞毕设了,打算用自己拿手的js来搞,但是仿佛入坑了,Node还不是很熟.总之,兵来将挡,水来土掩嘛,带着问题学习才是最高效的. 折腾1:Node 调用 C++ 刚开始,虽然我老师把dll文件给 ...

  6. golang调用c++的dll库文件

    最近使用golang调用c++的dll库文件,简单了解了一下,特作此笔记:一.DLL 的编制与具体的编程语言及编译器无关 dll分com的dll和动态dll,Com组件dll:不管是何种语言写的都可以 ...

  7. vs2010下C++调用lib或dll文件

    注: DLL:表示链接库,包含dll,lib文件: dll: 表示my.dll文件 lib: 表示my.lib文件 C++ 调用.lib的方法: 一: 隐式的加载时链接,有三种方法 1  设置工程的 ...

  8. 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 来 ...

  9. c++builder调用VC的dll以及VC调用c++builder的dll

    解析__cdecl,__fastcall, __stdcall 的不同:在函数调用过程中,会使用堆栈,这三个表示不同的堆栈调用方式和释放方式. 比如说__cdecl,它是标准的c方法的堆栈调用方式,就 ...

随机推荐

  1. 第三百三十二节,web爬虫讲解2—Scrapy框架爬虫—Scrapy使用

    第三百三十二节,web爬虫讲解2—Scrapy框架爬虫—Scrapy使用 xpath表达式 //x 表示向下查找n层指定标签,如://div 表示查找所有div标签 /x 表示向下查找一层指定的标签 ...

  2. html常用对照表

    常用对照表:http://tool.oschina.net/commons

  3. PHP中单引号与双引号的区别分析

    From: http://www.jb51.net/article/53973.htm 在PHP中,我们可以使用单引号或者双引号来表示字符串.不过我们作为开发者,应该了解其中的区别.单引号与双引号对于 ...

  4. php 正则获取字符串中的汉字preg_match_all

    preg_match_all('/[\x{4e00}-\x{9fff}]+/u', $list[$i]['iparr'], $matches); $list[$i]['iparr'] = join(' ...

  5. git忽略已添加版本控制的文件

    今天使用git做maven项目的版本控制,刚开始搭建项目后,把所有文件全部提交了. 已经提交的文件,gitignore中后配置也无效了. 所以使用以下命令来操作,操作后要提交哦. 1.执行 git r ...

  6. js sendBeacon

    页面性能日志: DNS解析耗时 TCP链接耗时 SSL安全链接耗时 网络请求耗时 DOM解析耗时 资源加载耗时 首包时间 白屏时间 首次可交换时间 Dom Ready时间 页面完全加载时间. 如某些统 ...

  7. lakala反欺诈建模实际应用代码GBDT监督学习

    /** * Created by lkl on 2018/1/16. */ import org.apache.spark.mllib.evaluation.BinaryClassificationM ...

  8. Spring AOP的日志记录

    现在的项目是Spring+MyBatis,前段时间项目经理让我干了一个活,就是给所有的controller里的所有方法加上日志记录的代码,其实没有多少,也就300来个方法,也没有抱怨什么,一边打着瞌睡 ...

  9. PowerDesigner使用技巧(转载)

    1.如何打开PowerDesigner 快捷工具栏 paletteTools(工具栏)--> customsize toolbars(自定义工具栏)-->勾选 palette(调色板) 2 ...

  10. Node.js之exports与module.exports

    每一个node.js执行文件,都自动创建一个module对象,同时,module对象会创建一个叫exports的属性,初始化的值是 {} module.exports = {}; Node.js为了方 ...