C/C++ dll的隐式调用与显式调用_c++ 显式和隐式调用dll的区别-程序员宅基地

技术标签: 计算机视觉  开发工具  c/c++  opencv  

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。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_37708614/article/details/121474325

智能推荐

SpringBoot集成ElasticSearch客户端Transport_springboot集成es transport方式-程序员宅基地

文章浏览阅读807次。使用Rransport操作es导包使用transport客户端时,不能引入springboot中的es依赖<dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>transport</artifactId> <ver..._springboot集成es transport方式

发顶会论文,怎么就那么难?-程序员宅基地

文章浏览阅读1k次。随着 AI 领域越来越火热,各大顶会的论文发布似乎也越来越难:AAAI 2020 放榜,8800 篇提交论文创历史记录;CVPR 2020 被称为十年来最难投中的一届;IJCAI 202..._ai顶会难吗

C++: static_c++ static仅文件内有效-程序员宅基地

文章浏览阅读112次。文章目录局部变量全局变量函数面向对象静态数据成员静态成员函数总结局部变量编译器一般不对普通局部变量进行初始化,也就是说它的值在初始时是不确定的,除非对其显式赋值。普通局部变量存储于进程栈空间,使用完毕会立即释放。静态局部变量使用static修饰符定义,即使在声明时未赋初值,编译器也会把它初始化为0。且静态局部变量存储于进程的全局数据区,即使函数返回,它的值也会保持不变。变量在全局数据区分配内存空间编译器自动对其初始化其作用域为局部作用域,当定义它的函数结束时,其作用域随之结束stat_c++ static仅文件内有效

mybatis连接数据库进行查询,返回对象为null_mybatis 结果返回 null id_log 映射-程序员宅基地

文章浏览阅读1.6k次。*Mapper.xml中代码&amp;lt;select id=&quot;query&quot; parameterType=&quot;int&quot; resultType=&quot;User&quot;&amp;gt; select username , password from user where id=#{id}&amp;lt;/select&amp;gt;主要测试代码User us_mybatis 结果返回 null id_log 映射

并行FP-Growth算法分析_flink fp-growth-程序员宅基地

文章浏览阅读228次。首先是单机情况下的算法其次参考论文《PFP: Parallel FP-Growth for Query Recommendation》_flink fp-growth

Android声音大小控制——AudioManager使用_android 提示音太小 audiomanager-程序员宅基地

文章浏览阅读1.2w次,点赞2次,收藏7次。控制系统的音量大小,方法很简单,如果是手机,嘿嘿,请按音量加减键,如果想通过什么上下滑动屏幕来控制的话,那就得看看android是怎么控制音量的了。AudioManager类,我们定义的控制系统声音的管理者,位于android.Media 包中,该类提供访问控制音量和钤声模式的操作。咱们可以通过以下方式来获取到他:AudioManager audiomanage = (AudioMan_android 提示音太小 audiomanager

随便推点

Bootstrap selectpicker无法显示问题_bootstrap selectpicker 不出现选项值-程序员宅基地

文章浏览阅读1.7k次。问题描述今天第一次使用selectpicker,遇到一个坑Chrome在有的情况下会自动初始化selectpicker(暂时没有搞清缘由),所以在别的机器上运行时会无法显示。这是初始化后的结果,bootstrap会自动为selectpicker套上一个如图所示的div。解决方法在js中初始化selectpicker即可:$(function () { $('.selectpicker').selectpicker();});..._bootstrap selectpicker 不出现选项值

windows 升级docker 4.9.1后,提示 Docker Desktop stopped,然后自动退出了-程序员宅基地

文章浏览阅读1.2k次。以管理员身份重新运行_docker desktop stopped

springboot—+Vue之模板前后端分离实现跨域问题-程序员宅基地

文章浏览阅读294次。Springboot+Vue前后端分离实现跨域问题在IDEA后端新建一个config-》CrosConfig直接复制粘贴一下的代码:@Configurationpublic class CrosConfig implements WebMvcConfigurer { //解决跨域问题 @Override public void addCorsMappings(CorsRegistry registry) { registry.addMappin...

微信跳一跳全自动软件JumpDevil >>> 使用说明-程序员宅基地

文章浏览阅读3.2k次。一、前言接着上一篇《Python + OpenCV >>> 写一个微信跳一跳全自动脚本》我后续将该脚本封装成了一个可执行exe文件 —“JumpDevil”,只需电脑安装有“傲软投屏”软件即可运行,无需任何其他环境配置。本博文是针对微信跳一跳全自动软件 —“JumpDevil” 的使用指南。二、使用指南1. 准备工作在启动JumpDevil 之前,我们需要先在电脑和手..._jumpdevil

实现一个Android输入法-程序员宅基地

文章浏览阅读882次。原文来自Android Developer Guide,本文为原文翻译,如有错误,欢迎指出。输入法(IME:Input method editor)是一个能够让用户输入文本的工具。Android提供了一个可扩展的输入法框架,允许应用为用户提供不同的输入法,比如触屏键盘甚至语音输入。只要安装,用户就可以从系统设置中选择自己喜欢使用的输入法,并且在整个系统环境中使用;在同一时刻,只有一种..._android 输入法

linux 重启网络服务后路由表丢失问题的解决方案-程序员宅基地

文章浏览阅读9.7k次,点赞6次,收藏19次。服务器多块网卡,需要访问多个网段,因此需要手动添加路由信息到路由表。 -----------------------------操作-----------------------------------------一:使用 route 命令添加使用route 命令添加的路由,机器重启或者网卡重启后路由就失效了,方法://添加到主机的路由(针对单个主机添加)# route add –ho..._centos7.9开机后路由表失效

推荐文章

热门文章

相关标签