C/C++ dll的隐式调用与显式调用

1.头文件、lib文件、dll文件

头文件:存放函数声明
dll文件:存放函数的定义,动态链接库文件Dynamic Link Library,运行时使用
lib文件:具体分静态编译与动态编译,编译时使用

静态编译

静态编译将导出声明和实现都放在lib中。编译后所有代码都嵌入到宿主程序

静态编译的优点是编写出来的程序不需要调用DLL和载入函数,直接可以当成程序的一部分来使用。

静态编译的缺点也是显而易见的,使用静态编译的程序体积会比动态编译大,原因是函数的实现被嵌入为程序代码的一部分。

动态编译

动态LIB文件相当于一个C语言中的h文件,是函数导出部分的声明,而不将实现过程嵌入到程序本身中,编译后只是将函数地址存在宿主程序中,运行到调用函数是调用DLL并载入函数来实现函数的具体操作。

2.代码示例

头文件:

extern "C" _declspec(dllexport)int Sum(int a, int b);
extern "C" _declspec(dllexport)int Min(int a, int b);
extern "C" _declspec(dllexport)int Max(int a, int b);

函数定义:

extern "C" _declspec(dllexport)int Sum(int a, int b)
{
	return a + b;
}
extern "C" _declspec(dllexport)int Min(int a, int b)
{
    if (a >= b)return b;
    else
	return a;
extern "C" _declspec(dllexport)int Max(int a, int b)
{
    if (a <= b)return b;
    else
	return a;

类的封装

创建DLL

添加facedll.h的头文件(里面定义dll的接口,调用时会用到)

#pragma once
#ifdef FaceLIBDLL
#define FACEAPI _declspec(dllexport)
#else
#define FACEAPI  _declspec(dllimport)
#endif
//可以include需要用到的头文件
#include <opencv2/opencv.hpp>
 
class FACEAPI  FaceRecognizer
{
public:
	FaceRecognizer();
	~FaceRecognizer();
 
/
//类的函数
 
};

之后在facedll.cpp中写函数实现,而且要定义为 FaceLIBDLL

#define FaceLIBDLL
 
#include "stdafx.h"
#include "facedll.h"
#include <opencv2/opencv.hpp>
 
//头文件中函数的实现
FaceRecognizer::FaceRecognizer() 
{ 	
 
} 
 
FaceRecognizer::~FaceRecognizer() 
{ 	
 
} 

生成(Build)工程,在debug文件夹中会生成相应的DLL及LIB文件:facedll.dll   facedll.lib

3.dll的调用

隐式链接:在程序执行的时候,就将DLL文件加载到应用程序中。实现方法:将导入函数关键字_declspec(dllimport) funct,然后在配置中设置lib和dll的路径。上面封装的dll的调用:

头文件:

//#pragma conment(lib, "funct.lib")  // 和属性里面配置一个效果
extern "C"_declspec(dllimport) int Sum(int a, int b);

 主函数:

#include "Testdll.h"//上述头文件
void mian()
{
    int a;
    a = Sum(5,5);
}

显式链接:应用程序在执行过程中随时可以添加DLL文件,也可以随时卸载DLL文件,这是隐式链接无法做到的,所以显示链接具有更好的灵活性,对于解释性言语更为合适。不过使用显示链接要麻烦一些。
在应用程序中用LoadLibrary或MFC提供的AfxLoadLibrary显示的将自己所做的动态链接库调用进来。在应用程序退出之前,应用FreeLibrary或MFC提供的AfxFreeLibrary释放的动态链接库。
 

#include <windows.h>  
#include <cstdio>  
void main(void)  
{  
typedef int(*pMax)(int a,int b);  
HINSTANCE hDLL;  
PMax Max  
HDLL=LoadLibrary("MyDll.dll");//加载动态链接库MyDll.dll文件;  
Max=(pMax)GetProcAddress(hDLL,"Max");  
A=Max(5,8);  
Printf("比较的结果为%d\n",a);  
FreeLibrary(hDLL);//卸载MyDll.dll文件;  
} 

4.extern "C"说明

#ifdef __cplusplus 
extern "C" { 
#endif 
 
//一段代码 
 
#ifdef __cplusplus 
} 
#endif 
 

__cplusplus是cpp中的自定义宏,上面的代码的含义是:如果这是一段cpp的代码,那么加入extern "C"{和}处理其中的代码。

C和C++对函数的处理方式是不同的。extern "C"是使C++能够调用C写作的库文件的一个手段,如果要对编译器提示使用C的方式来处理函数的话,那么就要使用extern "C"来说明。因为如果要变出dll的话,那么C和C++编译出来的dll中的导出函数名是不一样的,void function()  再C里面的导出函数名可能就是function而C++中导出函数名可能是@function@xxx之类乱七八糟的符号,为了调用方便,有些情况下用C风格的导出函数,也可以方便java或者其他的编程语言调用dll。

  • 5
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zyb-小波

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值