【转】 编写C#调用的C++DLL

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

一般我们提供给其他语言调用的DLL,都是用C或者C++编写,然后封装。我这边也是采用的C++。

首先有几个注意点:

1、如果功能很简单,或者不使用第三方库(如MFC自带的库),建立一个win32的控制台程序就可以了,然后把项目生成改为DLL。值得一提的是,代码生成里面

          运行时库分四种:

                    (1)多线程MTD(静态库,编译之后,你的lib带有调试功能)——> debug时用

                    (2)多线程MT(静态库,没有调试功能)                           ——> release时用

                    (3)多线程DLL MTD(动态库,带有调试功能)                  ——> debug时用

                    (4)多线程DLL MT(动态库,没有有调试功能)。              ——> release时用s

          既然封装DLL,那调试的时候用(3),发布的时候用(4)。

2、设置为导出函数,并采用C风格。函数前加extern "C" __declspec(dllexport)。定义函数在退出前自己清空堆栈,在函数前加__stdcall。

      如extern "C" __declspec(dllexport) int __stdcall add(int x,int y);

      具备上述条件时,生成的DLL就含有导出函数的功能了,不过此时DLL中的函数名称不是规则的,使用编译器自定义的,可能是这样一个名字[email protected]20,具体的可以用VS的Depends工具查看一下。

3、把导出函数名称变为标准名称,需加模块定义文件,就是.def文件。

内容如下:(需要注释,前面加分号就可以了,注释需要单独行)

LIBRARY "TEST"

     EXPORTS

                ;add函数

                adds

LIBRARY 库名称

EXPORTS 需要导出的各个函数名称

     重新编译之后,再用Depends工具看一下,函数已经变成标准add,而不是[email protected]20。这个在动态加载时很有用,特别是在GetProcAddress函数寻找入库函数的时候。

4、C#调用C++ DLL,介绍两种方法

     (1)静态加载

             [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(10);

             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;         

     (2)动态加载

             [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)//0表示函数没找到
                 return null;

             //获取函数接口,相当于函数指针
             ADD add = (Delegate)Marshal.GetDelegateForFunctionPointer(apiFunction, typeof(ADD)) as ADD;          

             //调用函数

             add(1,2);

             //释放句柄

             FreeLibrary(hLib );

    最后,

            1)C++在返回字符串时,切记最后添加/0,不然在C#等中调用,会显示部分乱码。    

            2)C++动态申请的内存,需在出函数之前就必须释放,否则会报意想不到的错误。比如内存写入错误等等。
时间: 2024-10-06 22:34:08

【转】 编写C#调用的C++DLL的相关文章

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

DLL(动态链接库)是一个很有用的东西,在开发大项目的时候显得非常重要,因为多人合作开发时,可以给每个人分配一个任务,用DLL完成,最后组合起来,就不会出现互相冲突的问题.这里给出最简单的DLL编写与调用的示例,本人水平不高,各位看官莫笑. 首先,我们打开VB.NET,选择类库,名称改为test然后我们输入以下代码 Public Class test Public Function test(ByVal a As Long, ByVal b As Long) As Long Return a +

DLL编写与调用全解

DELPHI学习   2008-12-23 22:52   阅读8   评论0 字号: 大  中  小 第一章 为什么要使用动态链接库(DLL) top 提起DLL您一定不会陌生,在Windows中有着大量的以DLL为后缀的文件,它们是保证Windows正常运行和维护升级的重要保证.(举个例子,笔者的Win95 System目录下尽有500多个DLL文件.)其实,DLL是一种特殊的可执行文件.说它特殊主要是因为一般它都不能直接运行,需要宿主程序比如*.EXE程序或其他DLL的动态调用才能够使用.

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

delphi 编写和调用dll文件   Windows 的执行文件可以划分为两种形式程序和动态连接库 (DLLs).一般程序运行是用.EXE文件,但应用程序有时也可以调用存储在DLL的函数. 在如下几种情况下,调用DLL 是合理的: 1) 不同的程序使用相同的DLL ,这样只需要将DLL 在内存中装载一次,节省了内存的开销. 2) 当某些内容需要升级的时候,如果使用DLL 只需要改变DLL 就可以了,而不需要把整个程序都进行变动. 3) 由于DLL 是独立于语言的,所以,当不同语言习惯的人共同开

Atitit.java jna  调用c  c++ dll的原理与实践  总结  v2  q27

Atitit.java jna  调用c  c++ dll的原理与实践  总结  v2  q27 1. Jna简单介绍1 2. Jna范例halo owrld1 3. Jna概念2 3.1. (1)需要定义一个接口,继承自Library 或StdCallLibrary2 3.2. 2)接口内部定义2 4. 数据类型映射 NA官方给出的默认类型映射表如下:3 5.  JNA能完全替代JNI吗?3 6. 参考4 1. Jna简单介绍 原来使用JNI,你必须手工用C写一个动态链接库,在C语言中映射Ja

C#调用C/C++ DLL方式

1.编写一个简单的DLL 设置为导出函数,并采用C风格.函数前加extern "C" __declspec(dllexport).定义函数在退出前自己清空堆栈,在函数前加__stdcall. 新建一个头文件,在头文件中: /* 加入任意你想加入的函数定义*/ extern "C" _declspec(dllexport) int _stdcall add(int *x,int *y); // 声明为C编译.链接方式的外部函数extern "C"

Qt DLL总结【二】-创建及调用QT的 DLL(三篇)good

目录 Qt DLL总结[一]-链接库预备知识 Qt DLL总结[二]-创建及调用QT的 DLL Qt DLL总结[三]-VS2008+Qt 使用QPluginLoader访问DLL 开发环境:VS2008+Qt4.7.4 最近看了不少Qt的DLL例子,总结一下如何创建和调用QT 动态链接库. 先讲一下对QT动态链接库的调用方法,主要包括: 1.显式链接DLL,调用DLL的全局函数,采用Qt的QLibrary方法 2.显示链接DLL,调用DLL中类对象.成员函数.(通过对象即可实现类成员函数的调用

.Net 环境下C# 通过托管C++调用本地C++ Dll文件

 综述 : 本文章介绍.Net 环境下C# 通过托管C++调用本地C++ Dll文件, 示例环境为:VS2010, .Net4.0, Win7. 具体事例为测试C++, C#, 及C#调用本地C++Dll文件进行浮点运算效率的一部分. 如果需要查看三者的效率, 请继续阅读下面的文章. a 创建本地CPP类库 1. 创建本地CPP的Dll ---->EfficiencyNativeCPPDLL 2. 点击下一步 注意选择为DLL(D)项, 然后选择完成. 3.书写DLL文件 3.1 Efficie

Effective C++ 之 Item 5:了解C++默默编写并调用哪些函数

Effective C++ chapter 2. 构造 / 析构 / 赋值运算 (Constructors, Destructors, and Assignment Operators) Item 5. 了解 C++ 默默编写并调用哪些函数 (Know what functions C++ silently writes and calls)

Effective C++ Item 5 了解 C++ 默默编写并调用哪些函数

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 经验: 如果你自己没声明,编译器会自动声明copy constructor,copy assignment,destructor, 如果你没有声明任何构造函数,编译器会自动声明default constructor 示例: 如果你写下 class Empty{ }; 将会等价于 class Empty{ public: Empty() {...} //default构造函数 Empty(c