使用extern "C"改善显式调用dll

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 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 __cplusplus
extern "C"
{
#endif
	CREATEDLL_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 __cplusplus
extern "C" {
#endif

	extern  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



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值