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. JMS与消息队列

    JMS,Java Message Service,即Java消息服务. MOM,Message Oriented Miiddleware的英文缩写,指的是利用高效可靠的消息传递机制进行平台无关的数据交 ...

  2. 商城怎么使用ajax?

    1.前端: Ajax.call('order.php?act=export', params, function (data) { document.getElementById("expo ...

  3. 000 centos7下安装elasticsearch7的单节点安装

    在这里,直接使用最新的包进行学习.这里的安装也以前的版本不同,不过因为学习,这部分安装的区别不具体研究了. 这里也是摸索型的记录,所以会出现报错情况,然后针对这种方式进行解决,最后达到安装完成的效果. ...

  4. NonSerialized 属性忽略序列化报错'NonSerialized' is not valid on this declaration type

    [XmlIgnore] [NonSerialized] public List<string> paramFiles { get; set; } //I get the following ...

  5. Leetcode: Campus Bikes II

    On a campus represented as a 2D grid, there are N workers and M bikes, with N <= M. Each worker a ...

  6. 算法习题---5.3字典(Uva10815)

    一:题目 给出一段英文,里面包含一些单词,空格和标点,单词不区分大小写,默认都为小写.按照字典序输出这些单词(这些单词不能有重复,字母全部变成小写) (一)样例输入 Adventures in Dis ...

  7. 判断本网段有多少可用的ip地址

    为了提高效率,使用多线程方式同时ping. 但是如果开启255个线程,又会因为网络端口太拥挤,会被判定为无法ping通.所以本例使用java自带线程池,线程池的连接数还不能太大,启动了15个线程. 等 ...

  8. Python - Django - ORM Django 终端打印 SQL 语句

    在 settings.py 中添加以下内容: LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'c ...

  9. go micro 微服务框架温习

    go mod edit -require="github.com/chromedp/chromedp@v0.1.0" @后面加上你需要的版本号.就可以 已经修改go.mod 里的依 ...

  10. WEUI switch 如何取值?

    let id = $(this).attr("id"); let name = $(this).attr("data-name"); HTML: <div ...