教育考试类网站建设,官方网站建设维护合作协议,酒店网站建设设计,大润发超市网上商城extern C的简单解析 我们前面介绍了显式调用dll的方法#xff0c;例如 #xfeff;#xfeff;http://www.cnblogs.com/laogao/archive/2012/12/07/2806528.html #xff0c;其中在GetProcAddress第二个参数的填写煞费苦心#xff0c;我们需要比较麻烦…extern C的简单解析 我们前面介绍了显式调用dll的方法例如 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 stylecolor:#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 __cplusplus
extern C
{
#endifCREATEDLL_API void printMax(int, int);
#ifdef __cplusplus
}
#endif // __cplusplus
/span// CreateDLL.cpp : 定义 DLL 应用程序的导出函数。
//#include stdafx.h
#include CreateDLL.h
#include iostreamCREATEDLL_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 iostreamtypedef 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 dlldllName 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 __cplusplus
extern 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.htypedef 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;coutresult 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语言编译创建dllC程序可以正确调用DLL而当用户使用C调用DLL时extern C {}就起作用了。
附录
1.例1
2.例2