Windows操作系统中,库分为动态链接库(dll)和静态链接库(lib)

动态库是Windows中实现代码共享的一种方式。它是一个二进制式文件,不可单独运行,需要调用方调用才能运行。在Windows中,动态库可以被多种编程语言所支持。

静态链接库不同于动态链接库(dll),在静态库情况下,函数和数据被编译进一个二进制 文件(通常扩展名为*.lib),Visual C++的编译器在链接过程中将从静态库中恢复这些函数和数据并把他们和应用程序中的其他模块组合在一起生成可执行文件。这个过程称为"静态链接",此时因为应用程序所需的全部内容都是从库中复制了出来,所以静态库本身并不需要与可执行文件一起发行。

使用动态库有以下好处:

1、有利于代码和数据的共享

2、有利于模块化开发

3、有利于软件升级

4、代码保护

动态链接库又分为Win32动态链接库和MFC动态链接库。区别就是是否使用了MFC类

Win32 DLL编程

如何导出Win32 DLL

1、通过关键字_declspec(dllexport导出)

新建一个C++ dll工程 DllExportTest

新建一个DllExportTest..h文件

输入

 #pragma once

 __declspec(dllexport) void PrintHelloWorld();

在DllExportTest.cpp中输入

 #include "stdafx.h"
#include"DllExportTest.h"
#include<iostream> using namespace std; void PrintHelloWorld()
{
cout << "HelloWorld" << endl;
}

2、通过模块定义文件导出

新建一个C++ dll工程 DllExportWithDEFTest

新建一个DllExportWithDEFTest.h,输入

 #pragma once

 void PrintHelloWorld();

在DllExportWithDEFTest.cpp中输入

 #include "stdafx.h"
#include"DllExportWithDEFTest.h"
#include<iostream> using namespace std; void PrintHelloWorld()
{
cout << "HelloWorld" << endl;
}

然后在“源文件”上右键选择“添加新项”,选择“代码”->”模块定义文件(.def)“

.def常用格式如下

LIBRARY   DllName                  //dll名字, DllName可以为空
DESCRIPTION DllDescription //dll 描述 这一行可以省略
EXPORTS FuncOrVariables //要导出的函数名或变量的名字

我在前面的代码中定义了PrintHelloWorld函数,要将它导出,可以这样定义.def文件

LIBRARY
EXPORTS
PrintHelloWorld

如果要将PrintHelloWorld函数导出为其它的名字,如MyFuncName,可以这样定义.def文件

LIBRARY
EXPORTS
MyFuncName = PrintHelloWorld

如何使用导出的函数

C#调用可以参考以下链接

https://www.cnblogs.com/zhaotianff/p/8991847.html

C++调用

分为隐式链接和显式链接两种方式

隐式链接

步骤如下

1、引入lib文件

2、引入头文件

3、调用dll中的数据

新建一个C++ 控制台程序 InvokeDll

打开项目的目录,建立lib和include文件夹(这个操作不是必须的,.h和.lib可以通过路径引用,不一定非要建立这样的文件夹,但这样操作会更好管理)

把前面生成的DllExportTest.lib拷到lib文件夹下,把DllExportTest.h拷到include文件夹下

然后在项目上单击右键,选择属性,依次选择配置属性-》链接器-》常规-》附加库目录。新建一个路径,选择刚才建立 的lib文件夹,单击确定

再选择输入-》附加依赖项,增加DllExportTest.lib

在InvokeDll.cpp中输入以下代码

 #include "stdafx.h"
#include "include\DllExportTest.h" int main()
{
PrintHelloWorld();
return ;
}

运行之后可以看到屏幕输出HelloWorld

隐式链接还有一种方式,使用指令#pragma comment来引用lib文件

新建一个C++控制台程序 InvokeDll_2

复制InvokeDll项目路径下的include和lib文件夹到InvokeDll_2的项目路径下,在InvokeDll_2.cpp中输入以下代码

 #include "stdafx.h"
#include "./include/DllExportTest.h" #pragma comment(lib,"./lib/DllExportTest.lib") int main()
{
PrintHelloWorld();
return ;
}

运行之后也可以看到屏幕输出HelloWorld

 显式链接

显示链接主要是通过调用LoadLibrary、GetProcAddress、FreeLibrary这三个API函数来实现

LoadLibrary()

声明如下

HMODULE WINAPI LoadLibrary( _In_ LPCTSTR lpFileName);

用于载入指定的动态链接库

GetProcAddress()

声明如下

FARPROC GetProcAddress( HMODULE hModule, LPCSTR lpProcName );

用于检索指定的动态链接库中函数地址

FreeLibrary()

声明如下

BOOL FreeLibrary( HMODULE hLibModule );

用于释放指定的动态链接库

新建一个C++控制台程序 InvokeDllExplicitly,在InvokeDllExplicitly.cpp中输入以下代码

 #include "stdafx.h"
#include <Windows.h> typedef void(*MyFunc)(); //后面是函数签名部分,需要跟导出函数中的保持一致。这个函数没有参数,所以后面部分为空 int main()
{
HMODULE hDll = NULL;
MyFunc myFunc = NULL; //加载库
hDll= LoadLibrary("./DllExportTest.dll"); if (hDll)
{
//获取函数或变量的地址
myFunc =(MyFunc)GetProcAddress(hDll, "PrintHelloWorld"); if (myFunc)
{
//调用函数
myFunc();
}
} //释放动态链接库
FreeLibrary(hDll); return ;
}

运行可以看到屏幕输出 HelloWorld

Windows中的库编程的更多相关文章

  1. windows中静态库lib和动态dll的区别及使用方法

    1. 静态库lib和动态dll的区别 1.1 项目类型 VS在建Win32项目时,有以下选项: windows应用程序控制台应用程序DLL静态库最后两个类型:DLL和静态库,这两种项目类型是不可以单独 ...

  2. 在windows下的QT编程中的_TCHAR与QString之间的转换

    由于在windows下的QT编程中,如果涉及到使用微软的API,那么不可避免使用_TCHAR这些类型,因此在网上查了一下,其中一个老外的论坛有人给出了这个转换,因此在这里做一下笔记 : )#ifdef ...

  3. Python中使用模块和库编程

    """ python中使用模块和库编程 导入模块 import modulename [as alias] from modulename import fun1,fun ...

  4. winsock教程- windows下的socket编程(c语言实现)

    winsock教程- windows下的socket编程(c语言实现) 使用winsock进行socket 编程     这是一个学习windows下socket编程(c语言)的快速指南.这是因为一下 ...

  5. Linux与Windows中动态链接库的分析与对比

    摘要:动态链接库技术实现和设计程序常用的技术,在Windows和Linux系统中都有动态库的概念,采用动态库可以有效的减少程序大小,节省空间,提高效率,增加程序的可扩展性,便于模块化管理.但不同操作系 ...

  6. PHP中GD库是做什么用的? PHP GD库介绍11111111

    什么是gd库?    gd库是php处理图形的扩展库,gd库提供了一系列用来处理图片的API,使用GD库可以处理图片,或者生成图片. 在网站上GD库通常用来生成缩略图或者用来对图片加水印或者对网站数据 ...

  7. STM32 HAL固件库编程的文件构架

    对于我这种以前只接触过51和AVR单片机编程的小菜来说,现在开始学习STM32的编程,对于函数的功能以及C语言的语法都还好理解,难的是它提供的那一套硬件抽象层(HAL)驱动是怎么和其他的东东搭配在一起 ...

  8. Linux下TCP网络编程与基于Windows下C#socket编程间通信

    一.linux下TCP网络编程基础,需要了解相关函数 Socket():用于套接字初始化. Bind():将 socket 与本机上的一个端口绑定,就可以在该端口监听服务请求. Listen():使s ...

  9. .Net中的并行编程-6.常用优化策略

                本文是.Net中的并行编程第六篇,今天就介绍一些我在实际项目中的一些常用优化策略.      一.避免线程之间共享数据 避免线程之间共享数据主要是因为锁的问题,无论什么粒度的锁 ...

随机推荐

  1. Faster async functions and promises

    https://v8.dev/blog/fast-async async function computeAnswer() { return 42;}undefinedconst p = comput ...

  2. (信贷风控八)行为评分卡模型(B卡)的介绍

    python信用评分卡建模(附代码,博主录制) https://study.163.com/course/introduction.htm?courseId=1005214003&utm_ca ...

  3. Linux openkvm disk expansion

    How to Increase the size of a Linux LVM by expanding the virtual machine disk https://www.rootusers. ...

  4. HDCMS多图字段的使用?

    下面是HDCMS多图字段的简单使用: HDCMS在后台添加的多图,存到数据的时候是经过序列化过的,所以在使用的时候需要进行反序列化操作: $moreImg = M('keshi')->where ...

  5. Spring cloud微服务安全实战-5-11实现基于token的SSO(1)

    基于服务器session的SSO的方案,用户的登陆状态都是存在服务器端的 基于浏览器cookie的token实现一个sso,在原来的基础上做进一步的改造.让他不依赖session.而是完全由cooki ...

  6. (?:pattern) 与 (?=pattern)的区别

    共同点 (?:pattern) 与 (?=pattern)都匹配pattern,但不会把pattern结果放到Matches的集合中. 区别 (?:pattern) 匹配得到的结果包含pattern. ...

  7. C++数据存储方式

    1.栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清楚的变量的存储区,里面的变量通常是局部变量.函数参数等. 2.堆,就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去 ...

  8. hadoop记录-MapReduce之如何处理失败的task(转载)

    1.1作业某个任务阻塞了,长时间占用资源不释放 1.2在MapTask任务运行完毕,ReduceTask运行过程中,某个MapTask节点挂了,或者某个MapTask结果存放的那磁盘坏掉了 在Task ...

  9. SQL Server 2014 清除用户名和密码

    网上找来找去都是SQL Server 2008版本或者以前版本的... 后来:http://stackoverflow.com/questions/349668/removing-the-rememb ...

  10. LabWindows/CVI入门之第四章:库文件(转)

    按语: 在参考CVI参考书使用CVI生成动态库后,在另一工程中调用DLL ,编译通不过,后参考此文,豁然开朗. http://blog.sina.com.cn/s/blog_6373e9e60101b ...