使用extern "C"改善显式调用dll
来源:互联网 发布:安卓手机淘宝网 编辑:程序博客网 时间:2024/06/03 18:00
http://www.cnblogs.com/laogao/archive/2012/12/07/2806528.html ,其中在GetProcAddress第二个参数的填写煞费苦心,我们需要比较麻烦地使用vs自带的dumpbin查看dll的具体函数,即使后来可以使用MAKEINTRESOURCE直接填写函数序号来不直接填写函数名,依然你需要在dumpbin中查找函数的序号,比较费力。
其实我们有更好的方法来解决这个问题,其中一个比较好的一个方法是改用extern "C"来修饰函数,使之按照c的风格来编译函数。我们知道c不支持函数重载,因此我们定义的时候用的什么名字,在显式调用dll的时候也是用的这个名字,完全不用改变,很简单。
在进行下面的介绍之前,先可以阅读这个文章《extern "C"的简单解析》
下面我们介绍两个例子。
例1. 在纯C++环境下使用c语言方式编译dll,然后调用
CreateDLL.h
<span style="color:#000000;">// 下列 ifdef 块是创建使从 DLL 导出更简单的// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 CREATEDLL_EXPORTS// 符号编译的。在使用此 DLL 的// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将// CREATEDLL_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的// 符号视为是被导出的。#ifdef CREATEDLL_EXPORTS#define CREATEDLL_API __declspec(dllexport)#else#define CREATEDLL_API __declspec(dllimport)#endif#ifdef __cplusplusextern "C"{#endifCREATEDLL_API void printMax(int&, int&);#ifdef __cplusplus}#endif // __cplusplus</span>
// CreateDLL.cpp : 定义 DLL 应用程序的导出函数。//#include "stdafx.h"#include "CreateDLL.h"#include <iostream>CREATEDLL_API void printMax(int& a, int& b){std::cout << "Among (" << a << "," << b << "), the Max Number is " << (a > b ? a : b) << "\n";}
然后点击“生成”,即可生成dll和lib。接下来我们就可以直接使用了。注意:生成dll的时候,需要先设置dll的项目为启动项。当使用dll的时候,需设置使用dll的项目为启动项。
先看显式调用:
#include <Windows.h>#include <iostream>typedef void(*FUNA)(int&, int&);int main(){ const char* dllName = "CreateDLL.dll";int x(100), y(100);HMODULE hDLL = LoadLibrary(dllName);if (hDLL!=NULL){FUNA fp1 = FUNA(GetProcAddress(hDLL, "printMax"));if (fp1!=NULL){std::cout << "Input 2 Numbers:";std::cin >> x >> y;fp1(x, y);}else{std::cout << "connot find the function "<<"printMax" << std::endl;}FreeLibrary(hDLL);}else{std::cout << "cannot load dll"<<dllName << std::endl;}system("pause");return 0;}
注意观察,我们的GetProcAddress的第二个参数直接使用原来的函数名。另外需要注意的是在使用dll的项目中,我们没有包含dll的头文件,但是仍然可以使用。但是有时候也过不去,此时你需要包含dll的.h的路径。
再看隐式调用:
#include "CreateDLL.h"#include <iostream>using namespace std;#pragma comment(lib,"CreateDLL.lib")int main(){int a,b;cout << "input 2 num:";cin >> a >> b;printMax(a,b);system("pause");return 0;}
将.h,.lib,.dll一块儿放在项目目录下,然后在程序中使用#pragma comment(lib,"CreateDLL.lib"),即可成功链接dll。与显式调用,隐式调用比较简单。
另外在上一篇《c++显式加载dll并使用DLL的类》,我们也使用了extern "C"的风格
extern "C" INTERFACE_API Interface* Export(void);
例2. 在纯C环境下使用c语言方式编译dll,然后在C++中调用
CreateDLL.h
//c.h#ifndef _C_H_#define _C_H_ //防止被重复包含#ifdef CREATEDLL_EXPORTS#define CREATEDLL_API __declspec(dllexport)#else#define CREATEDLL_API __declspec(dllimport)#endif#ifdef __cplusplusextern "C" {#endifextern CREATEDLL_API int add(int x, int y);#ifdef __cplusplus}#endif#endif
CreateDLL.c
#include "CreateDLL.h"int add(int x, int y){return x + y;}
然后我们就可以生成dll了。注意我们这里都是c语言。
然后我们在c++中调用dll。
显式调用:
#include <Windows.h>#include <iostream>#include "CreateDLL.h"typedef int(*Func)(int, int);#pragma comment(lib,"CreateDLL.lib")int main(){HMODULE Hdll = LoadLibrary("CreateDLL.dll");if (Hdll!=nullptr){Func f = Func(GetProcAddress(Hdll, "add"));if (f!=nullptr){std::cout << "input 2 num:";int a, b;std::cin >> a >> b;std::cout << "result is " << add(a, b);}else{std::cout << "connot find the function " << "add" << std::endl;}FreeLibrary(Hdll);}else{std::cout << "cannot load dll" << "CreateDLL.dll" << std::endl;}system("pause");return 0;}
注意要将CreateDLL.h和CreateDLL.lib放在项目目录下。
隐式调用:
#include "CreateDLL.h"#include <iostream>using namespace std;#pragma comment(lib,"CreateDLL.lib")int main(){int a,b;cout << "input 2 num:";cin >> a >> b;cout<<"result is "<<add(a,b);system("pause");return 0;}
解读:
文件为*.c,__cplusplus没有被定义,extern "C" {}这时没有生效,对于C语言只是extern int add(int, int);而编译c++源文件,__cplusplus被定义,对于C++他看到的是extern "C" {extern int add(int, int);},编译器就会知道add(1, 0)调用的是C连接。
很多DLL的生成文件(XXX.c)中常出现extern "C" ,windows采用C语言编译创建dll,C程序可以正确调用DLL,而当用户使用C++调用DLL时,extern "C" {}就起作用了。
附录:
1.例1
2.例2
- 使用extern "C"改善显式调用dll
- c调用c++编的dll,c++调用c编写的dll,extern “C”的用法
- extern c , c++ 调用c
- extern "C" C 调用c++
- c调用c++、c++调用c 时所使用的extern "c" 的区别
- C#中使用DllImport调用C++dll
- 使用 JNI 调用 c 的 DLL
- 使用JNI调用dll(C++)
- c调用c++和c++调用c时所使用的extern "c"的区别
- extern "C"使用
- “extern c”的使用
- extern “C”的使用
- extern "C"的使用
- extern "C"的使用
- extern "C"的使用
- 何时使用 extern "C"
- extern "c"使用
- extern "C"的使用
- LeetCode 185. Department Top Three Salaries
- android studio 导入一个开源库文件汇总
- Execute & ExecuteGlobal
- R3多线程
- 观察者模式(这个用的太多了)
- 使用extern "C"改善显式调用dll
- 最长回文子串(动态规划和递归)
- R0多线程
- const 相关
- Android EventBus的基本使用
- c++ 版的蛇形矩阵,正方形的,从数字1开始逐渐增大,呈回字形
- 策略模式使用场景
- 算法:最长回文子串长度
- 共同学习Java源码--常用数据类型--String(七)