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. 【vue】常用操作

    一.Vue中import from的来源:省略后缀与加载文件夹 https://blog.csdn.net/fyyyr/article/details/83657828 二.Vue安装依赖 #安装依赖 ...

  2. 如何使用eclipse创建简单的servlet

    Servlet是一种基于java开发的服务器程序,可以对外公布服务,如果是浏览器应用,可以通过浏览器打开网址的方式查看服务.创建servlet要继承httpservlet,并且在web.xml中配置拦 ...

  3. 004 JpaRepository,CrudRepository,PagingAndSortingRepository的区别

    很多程序都在使用,CrudRepository或者PagingAndSortingRepository,但是以前自己的程序使用的是JpaRepository,然后查了一下材料,记录一下. 1.类图 2 ...

  4. 原理分析dubbo分布式应用中使用zipkin做链路追踪(转)

    作者:@nele本文为作者原创,转载请注明出处:https://www.cnblogs.com/nele/p/10171794.html 目录 zipkin是什么为什么使用Zipkinzipkin架构 ...

  5. VMware虚拟机提示“锁定文件失败 打不开磁盘”解决方法

    VMware虚拟机提示“锁定文件失败 打不开磁盘”解决方法 摘自: http://www.xitongcheng.com/jiaocheng/xtazjc_article_40299.html 发布时 ...

  6. mysql存储过程中declare 和set 定义变量的区别

    declare为对变量进行声明,声明必须制定变量的数据类型,只能写在过程的前面set是对变量赋值,可以放在过程的任何地方对没有declare声明过的变量赋值,该变量必须以加上@号,否则会报错 DECL ...

  7. tp 执行sql 语句

    $User = D('User'); $User->query('select * from think_user where status=1'); $User->execute('up ...

  8. 删除pod后又重新创建pod发现还是访问原先的服务状态---解决

    因为做了数据持久化存储,需要删除数据目录下的数据才可以 参照: https://www.cnblogs.com/effortsing/p/10496391.html

  9. linux 大量time_wait的解决方法

    通过调整内核参数解决vi /etc/sysctl.conf 编辑文件,加入以下内容:net.ipv4.tcp_syncookies = 1net.ipv4.tcp_tw_reuse = 1net.ip ...

  10. Beta冲刺(4/4)

    队名:秃头小队 组长博客 作业博客 组长徐俊杰 过去两天完成的任务:学习了很多东西 Github签入记录 接下来的计划:继续学习 还剩下哪些任务:细节处理 燃尽图 遇到的困难:自己太菜了 收获和疑问: ...