- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
DLL(动态链接库,Dynamic Link Library)是一种可执行文件,它包含可以在其他程序中调用的函数和数据。他是Windows操作系统中的一个重要概念,用于代码共享和模块化.
.lib
文件)不同,DLL不是在编译时链接到程序中的,而是在程序运行时链接。这意味着,如果更新了DLL,使用该DLL的程序可以在不重新编译的情况下直接使用新版本。新建项目-选择“win32控制台应用程序” 。
接着在弹出框中选择dll和空项目 完成后得到空项目的目录结构,创建DLL1.h和DLL1.cpp两个文件 。
DLL1.cpp
中实现两个数求和与求差的接口:int sum(int a, int b){
return a + b;
}
int sub(int a, int b){
return a - b;
}
DLL1.h
中声明函数:int sum(int a, int b);
int sub(int a, int b);
为了能在dll中使用,还需要给函数加上前缀:extern "C" __declspec(dllexport) 。
其中_declspec(dllexport)的意思是指定需要导出到dll的目标(用于生成dll) 。
extern "C"表示将C语言程序导出为DLL 。
extern "C" __declspec(dllexport) int sum(int a, int b);
extern "C" __declspec(dllexport) int sub(int a, int b);
也可以使用宏定义,使代码更具可读性 。
#define SumAndSub_API __declspec(dllexport)
extern "C" SumAndSub_API int sum(int a, int b);
extern "C" SumAndSub_API int sub(int a, int b);
在.h和.cpp中添加代码之后,右击项目选择“生成” 。
生成成功后,在项目Debug文件夹下即可找到生成的dll文件 。
.h所在目录也需要记录一下 。
到这DLL的封装算是完成了 。
首先需要重新创建一个空项目来调用测试:
创建完成之后,还需引入三个文件即前面生成的DLL1.dll和DLL1.lib以及项目DLL1.h文件 。
其中DLL1.dll需要放在当前项目的Debug目录下,其他两个在属性中配置路径即可(DLL1.lib还需添加依赖项) 。
右击项目-选择属性 。
选择VC++目录 。
其中“包含目录” 添加.h文件所在文件夹 “库目录”添加.lib所在目录 。
添加完成后如图:
然后在链接器-输入选项中添加依赖项 。
完成后应用属性保存,然后将DLL文件复制到当前项目的Debug目录下 。
下面新建一个test.cpp来测试下是否能够成功调用到DLL 。
#include "iostream"
#include "DLL1.h"
using namespace std;
int main(){
cout << sum(2, 5) << endl;
cout << sub(5, 2) << endl;
system("pause");
return 0;
}
成功调用到DLL 。
显式调用中又包含静态调用与动态调用.
.lib
文件包含了函数代码本身,在编译时直接将代码加入程序当中,称为静态链接库(static link library)。静态调用使用静态链接库,链接器从静态链接库LIB获取所有被引用函数,并将库同代码一起放到可执行文件中。先创建一个新的空项目,创建完成后添加一个.cpp源文件并写入简单的主函数 。
int main(){
}
右击项目选择-生成(生成Debug目录) 。
把DLL1.dll放到当前项目的Debug目录下 。
创建.cpp源文件通过以下代码进行静态调用 。
#include "iostream"
using namespace std;
#pragma comment(lib, "D:\\Code\\C++\\dll\\DLL1\\Debug\\DLL1.lib")
// dll中封装的函数
extern "C" __declspec(dllimport) int sum(int, int);
extern "C" __declspec(dllimport) int sub(int, int);
int main(){
cout << sum(2, 5) << endl;
cout << sub(5, 2) << endl;
system("pause");
return 0;
}
其中#pragma comment(lib, "D:\\Code\\C++\\dll\\DLL1\\Debug\\DLL1.lib") 表示链接DLL1.lib这个库,与在项目属性中的“VC++目录”中的“库目录”添加目录以及链接器-输入添加依赖性操作是等价的(一个显式一个隐式的区别).
.lib
文件包含了函数所在的DLL文件和文件中函数位置的信息(入口),代码由运行时加载在进程空间中的DLL提供,称为动态链接库(dynamic link library)。动态调用使用动态链接库,可执行模块(.dll文件或.exe文件)本身不包含它调用的DLL函数的代码,仅包含在运行时定位DLL函数的代码所需的信息,在程序运行时能够找到并链接到正确的DLL文件和函数。(这些信息通常包括函数名、参数类型等,足以让操作系统在运行时解析并调用正确的函数。)同样创建项目后先生成Debug目录 。
生成之后将DLL1.dll放入Debug目录中 。
通过如下方式进行动态调用 。
LoadLibrary()
函数来载入指定的dll文件,加载到程序的内存中(DLL没有自己的内存)GetProcAddress()
函数检索指定dll文件输出库函数地址,通过函数指针typedef int(*func)(int a, int b);
来装载函数并使用。FreeLibrary()
释放dll所占的空间。#include "iostream"
#include "windows.h"
using namespace std;
typedef int(*func)(int a, int b);
int main(){
// 动态加载dll
HMODULE hModule = LoadLibrary("DLL1.dll");
if (!hModule){
cout << "Error!" << endl;
}
// 装载函数
func sum = func(GetProcAddress(hModule, "sum"));
func sub = func(GetProcAddress(hModule, "sub"));
if (sum != NULL){
cout << sum(5, 2) << endl;
}
if (sub != NULL){
cout << sub(5, 2) << endl;
}
// 释放
FreeLibrary(hModule);
system("pause");
return 0;
}
注意:动态调用方式通常是只有.dll文件,而缺少.h和.lib文件时使用,当三个文件都齐全时,应采用更加简单方便的隐式调用.
最后此篇关于VS(visualstudio)C++封装dll,以及其隐式调用与显式调用(静态\动态)的文章就讲到这里了,如果你想了解更多关于VS(visualstudio)C++封装dll,以及其隐式调用与显式调用(静态\动态)的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我需要使用封装打印3个变量,并且无法修改主类。 主类声明变量[汽缸、制造商、所有者],并希望使用如下参数创建和打印一个对象: System.out.println (new Vehicle (cyli
我正在研究“Beginning Ruby”这本书,在我进行封装之前一切都进行得很顺利。我明白这段代码在做什么,我只是不知道为什么要用这些方法设置它。 对于那些感兴趣的人 this is the lin
所以我一直在研究面向对象的完整开发 JavaScript 实践,并对以下示例感到好奇。 据我了解,(这对我来说很有意义)以下“ secret ”字段是“私有(private)”的: var MyObj
在面向对象程式设计方法中,封装(英语:Encapsulation)是指,一种将抽象性函式接口的实作细节部份包装、隐藏起来的方法。 封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代
封装 被定义为 把一个或多个项目封闭在一个物理的或者逻辑的包中 。在面向对象程序设计方法论中,封装是为了防止对实现细节的访问。 抽象和封装是面向对象程序设计的相关特性。抽象允许相关信息可
今天我读了一本书,作者写道,在一个设计良好的类中,访问属性的唯一方法是通过其中一个类方法。这是一个被广泛接受的想法吗?为什么封装属性如此重要?不做会有什么后果?我早些时候在某处读到这可以提高安全性或类
今天我接受了软件工程职位的面试。我已经从 stackoverflow 中阅读了很多关于面试的内容。他们向我询问了与 OOP 相关的正常情况。但他们也问我这些: 没有继承就可以封装吗? 没有继承就可以抽
我正在制作一个简单的网站,并编写了gradle构建脚本,该脚本将执行诸如lint并最小化css / html / js之类的事情。 在这一阶段,我刚刚完成了正在运行的CSS,但是只是初始的非结构化格式
下面的幻灯片是指 C++ 语言,它说 "encapsulation is about ensuring the user uses our ADT in a safe way" 但是,如果他可以访问我
尝试设置一个 Person 类 我在尝试将信息封装在类中以使其不会被意外更改时遇到了问题。除了当我尝试使用 setter/getters 进行封装时,该类工作得非常好。我认为问题是这些方法最终会互相循
面向对象的概念:封装、数据抽象和数据隐藏是3个不同的概念,但彼此之间非常相关。所以我很难通过阅读互联网上的信息来完全理解这些概念。一个地方可用的信息与互联网上另一个地方的信息相矛盾。有人可以指导我阅读
我被封装困住了。在我看来,好像我已经按照规则做了一切,但仍然不起作用。虽然我知道我错过了一些东西。我正在使用 Eclipse。 我想要通过创建一副标准 52 张卡片来进行一些练习,并尝试我学到的新东西
在java中,要获取映射中的所有键,我们可以使用方法keySet。但我想知道为什么方法名称不只是 keys ?名称 Set 是否会泄露有关实现的详细信息? 据我了解,Java 是静态类型语言,名称中包
我正在尝试找出如何防止应用程序中的页面变量被全局定义。我想出了一些方法,但我想知道是否有人们使用的通用标准方法。 我使用这种方法得到了我的插件设计模式:http://www.virgentech.co
我有一个 tcp 连接,我想在服务器类的 HandleConnectionAsync 方法中保持打开状态。它将从客户端接收持续更新。 private async void HandleConnecti
这是我类(class)的一个小样本: #include #include using std::string; using std::vector; struct Book { string
我想要类似下面的代码: class Foo{ public: void update() { for( auto dataModifier : _dataModifierLis
这已经困扰我一段时间了,所以我问了一个同事他是否能理解它,现在我来了;) 为什么可以在依赖属性的 PropertyChangedCallback 中访问持有类的私有(private)成员? 让我通过这
我知道封装意味着一个对象不应该直接访问不同对象的成员……但我猜它与公共(public)领域有关?我假设公共(public)方法不会破坏封装..?我只是在这里不清楚,很高兴得到任何解释。 最佳答案
我就废话不多说了,大家还是直接看代码吧~ ? 1
我是一名优秀的程序员,十分优秀!