演练:创建和使用动态链接库 (C++)
- 格式:pdf
- 大小:1.02 MB
- 文档页数:6
1.新建MFC DLL工程,取名为:DLL0410
动态链接库的创建和调用(类,函数的DLL导出和调用)
2.在工程中编辑好DLL0410.h,DLL0410.cpp,DLL0410.def三个文件后编译生成对应的dll和lib文件
2.1 DLL0410.h
2.2 DLL0410.cpp
2.3 DLL0410.def
2.4 编辑好上面的3个文件编译后,用dumpbin命令查看是否有函数导出。
(如图所示,sub全局函数和add类的成员函数已经导出)
3.新建一个工程DLL0410test将生成的DLL0410.dll,DLL0410.lib以及DLL0410.h文件拷贝到 DLL0410test工程目录下
4.静态调用:在工程的DLL0410test.cpp文件中导入头文件DLL0410.h,并编写对应的静态调用代码。
同时也要在工程属性链接中加入DLL0410.lib文件。
(如果编译出错有可能是,工程属性中的常规>>字符集>>修改为 使用多字节字符集)
运行成功
5.4.动态调用:只需将生成的DLL0410.dll文件拷贝到新建工程目录下,直接在工程的
DLL0410test.cpp中编写动态调用代码即可。
不用做其他任何连接和导入头文件的操作。
运行成功。
动态链接库*.so的编译与使用- -动态库*.so在linux下用c和c++编程时经常会碰到,最近在网站找了几篇文章介绍动态库的编译和链接,总算搞懂了这个之前一直不太了解得东东,这里做个笔记,也为其它正为动态库链接库而苦恼的兄弟们提供一点帮助。
1、动态库的编译下面通过一个例子来介绍如何生成一个动态库。
这里有一个头文件:so_test.h,三个.c文件:test_a.c、t est_b.c、test_c.c,我们将这几个文件编译成一个动态库:libtest.so。
so_test.h:#include <stdio.h>#include <stdlib.h>void test_a();void test_b();void test_c();test_a.c:#include "so_test.h"void test_a(){printf("this is in test_a...\n");}test_b.c:#include "so_test.h"void test_b(){printf("this is in test_b...\n");}test_c.c:#include "so_test.h"void test_c(){printf("this is in test_c...\n");}将这几个文件编译成一个动态库:libtest.so$ gcc test_a.c test_b.c test_c.c -fPIC -shared -o libtest.so2、动态库的链接在1、中,我们已经成功生成了一个自己的动态链接库libtest.so,下面我们通过一个程序来调用这个库里的函数。
程序的源文件为:test.c。
test.c:#include "so_test.h"int main(){test_a();test_b();test_c();return 0;}l 将test.c与动态库libtest.so链接生成执行文件test:$ gcc test.c -L. -ltest -o testl 测试是否动态连接,如果列出libtest.so,那么应该是连接正常了$ ldd test./test 执行test,可以看到它是如何调用动态库中的函数的。
[动态链接库英文为DLL,是Dynamic Link Library 的缩写形式,DLL是一个包含可由多个程序同时使用的代码和数据的库,DLL不是可执行文件。
动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。
函数的可执行代码位于一个 DLL 中,该 DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。
DLL 还有助于共享数据和资源。
多个应用程序可同时访问内存中单个DLL 副本的内容。
动态链接库(Dynamic Link Library或者Dynamic-link library,缩写为DLL),是微软公司在微软视窗操作系统(即Windows操作系统)中实现共享函数库概念的一种方式。
这些库函数的扩展名是.DLL、.OCX(包含ActiveX控制的库)或者.DRV(旧式的系统驱动程序)。
动态链接库缩写为DLL,在电脑中可以更为容易地将更新应用于各个模块,而不会影响该程序的其他部分。
例如,您有一个大型网络游戏,如果把整个数百MB 甚至数GB的游戏的代码都放在一个应用程序里,日后的修改工作将会十分费时,而如果把不同功能的代码分别放在数个动态链接库(DLL)中,您无需重新生成或安装整个程序就可以应用更新。
]1.使用VC6.0 生成DLL新建项目“Win32 Dynamic-Link Library”,输入项目名称,确定后选择“A simple DLL project”点击“完成”。
以下为cpp文件自动生成的代码:#include "stdafx.h"BOOL APIENTRY DllMain( HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved){return TRUE;}编辑cpp文件:在#include "stdafx.h"的下一行加入extern "C" __declspec(dllexport) int fun(int a, int b);/*这是C格式导出函数;这种写法一般用在C++写的DLL中,指按C的规则导出这个函数,否则导出的函数会很怪; 加上extern "C" 表示按标准C格式导出函数.如果去掉仅兼容C++;其中int fun(int a, int b) 这部分代码是我们想用dll 实现的函数原型声明如果还想加入其他的可以继续加入extern "C" __declspec(dllexport) int fun1(int a, int b);*/DllMain 是DLL 的默认入口函数,类似于C语言的main函数,该例子无需修改此处,在DllMain 的后面加入:int fun(int a,int b){return a+b;}这就是我们想用DLL 实现的函数的定义,build 之后就会在debug 目录下生成我们想要的dll 文件2.调用DLL新建一个Win32 Console Application 工程,把刚才生成的dll 文件拷贝到工程的根目录下在stdafx.h 文件中加入:#include <windows.h>编辑cpp文件:#include "stdafx.h"typedef int (*PFUN)(int,int);void main(){HMODULE hModule = ::LoadLibrary("dlltest.dll");PFUN newfun = (PFUN)::GetProcAddress(hModule,"fun");int i = newfun(1,2);printf("The result is %d\n",i);::FreeLibrary(hModule);}然后,运行就可以看到结果了转VC6.0下调用Dll文件提供的函数接口和全局变量函数接口:首先把生成的Dll文件(如RegularDll.dll和RegularDll.lib)拷贝到当前工程所在文件夹,调用有两种方法:1)动态方法:使用LoadLibrary和GetProcAddress等函数,例typedef void (*lpFun)(void);HINSTANCE hDll;hDll = LoadLibrary("RegularDll.dll");if (NULL==hDll) {MessageBox("Dll load failed!");}lpFun pShowDlg = (lpFun)GetProcAddress(hDll,"ShowDlg");if (NULL == pShowDlg) {MessageBox("Load function \"ShowDlg\" failed!");}pShowDlg();*/2)静态声明方法:创建Dll的工程中,函数声明和定义时用_stdcall 修饰,例void _stdcall ShowDlg(void){...}在调用dll的工程的文件中,在文件头部声明库和函数,如下例#pragma comment(lib,"RegularDll.lib")void _stdcall ShowDlg(void);调用时直接ShowDlg()就可以了。
Windows下C语⾔调⽤dll动态链接库dll是windows下的动态链接库⽂件,下⾯记录⼀下在windows下如何调⽤C语⾔开发的dll动态链接库。
1.dll动态链接库的源代码hello_dll.c#include "stdio.h"_declspec(dllexport) void test_print(char const *str){printf("%s\n", str);}_declspec(dllexport) int test_add(int a, int b){return a + b;}上⾯的代码定义了两个函数,第⼀个函数需要传⼊⼀个字符串,然后打印出这个字符串,第⼆个函数需要转⼊两个int型整数,然后返回这两个整数的和。
执⾏ cl -LD hello_dll.c 会⽣成hello_dll.dll⽂件2.main函数的源代码test_hello_dll.c#include <stdlib.h>#include <windows.h>int main(int argc, char const *argv[]){// define two functional pointervoid(*p_test_print)(char const *) = NULL;int(*p_test_add)(int, int) = NULL;int add_result;// load dll file, require window.h fileHMODULE module = LoadLibraryA("hello_dll.dll");if (module == NULL) {system("error load");}p_test_print = (void(*)(char const *))GetProcAddress(module, "test_print");p_test_add = (int(*)(int, int))GetProcAddress(module, "test_add");if (p_test_print != NULL) {p_test_print("Hello This is from dll");} else {system("function p_test_print can not excute");}if (p_test_add != NULL) {add_result = p_test_add(5, 5);printf("Add result is %d\n", add_result);} else {system("function p_test_print can not excute");}FreeLibrary(module);system("pause");return0;}执⾏ cl test_hello_dll.c 会⽣成test_hello_dll.exe的可执⾏⽂件。
Visual studio c++ 2017 动态链接库的创建和使用总结一动态链接库的创建两种方式:1、只有从文件->新建->项目->Windows桌面-> Windows桌面向导->选择“动态链接库(.dll)->生成解决方案,才会生成.dll和.lib文件。
(1)在头文件声明中(注意要在头文件变量和函数声明中,而不是在变量和函数的定义中声明),不加extern “C”修饰,编译成DLL后,用depends.exe查看导出函数名。
可以看出,导出的函数名都被编译器篡改了。
(2)在头文件声明中,变量和函数名前加extern “C”修饰后,编译成DLL后,再用depends.exe查看导出函数名。
可以看出,用extern “C”修饰的函数名,编译后函数名保持不变。
类及成员函数不能用extern “C”修饰,编译成DLL后,成员函数名发生了改变。
2、如果从文件->新建->项目->动态链接库(DLL)->生成解决方案,就只生成.dll,不生成.lib。
二动态链接库的调用两种方式:1、显式调用(1)使用显式调用的前提:创建的DLL,编译时不要篡改函数名称,定义函数名时,可用extern “C”修饰函数名,保证编译时,函数名不被篡改。
否则GetProcAddress( )不能正确地获取dll中的函数名。
但是导出的类不能使用extern “C”修饰。
(2)使用显式调用的优点:不用动态链接库的.h和.lib文件,只要有.dll文件就可调用库函数,使用LoadLibrary(),在需要调用.dll中的库函数时,才动态加载到内存中,使用完毕后,可以用FreeLibrary()释放内存中的dll;使用GetProcAddress( )获取dll中的函数名。
必须事先知道dll中的函数名和形式参数。
(3)使用显式调用缺点:调用每个函数时,都必须使用 GetProcAddress( )获取dll中的函数名,并转换成原来的函数,比较麻烦。
c语言dll写法
在C语言中,编写DLL(动态链接库)的基本步骤如下:
1. 定义导出函数或变量:使用__declspec(dllexport)关键字将需要导出的函数或变量声明为导出符号。
例如:
```c
__declspec(dllexport) void MyFunction()
{
// 函数实现
}
```
2. 编译源代码:使用C编译器将源代码编译为目标文件。
例如,使用GCC 编译器可以使用以下命令:
```shell
gcc -c -DBUILD_DLL
```
这将生成一个名为的目标文件。
3. 创建DLL项目:使用链接器将目标文件链接为DLL。
例如,使用GCC编译器可以使用以下命令:
```shell
gcc -shared -o
```
这将生成一个名为的DLL文件。
4. 使用DLL:在其他C语言程序中,使用__declspec(dllimport)关键字导
入DLL中的导出符号。
例如:
```c
__declspec(dllimport) void MyFunction();
```
然后在程序中使用该函数或变量即可。
注意,在使用DLL时需要确保DLL
文件与应用程序位于同一目录中,或者在系统路径中添加DLL文件的路径。
以上是编写C语言DLL的基本步骤。
需要注意的是,具体的实现方式可能
会因编译器和操作系统而有所不同。
c#(winform)环境下使⽤动态链接库dll的详解1,什么是dll⽂件?DLL(Dynamic Link Library)⽂件为动态链接库⽂件,⼜称“应⽤程序拓展”,是软件⽂件类型。
在Windows中,许多应⽤程序并不是⼀个完整的,它们被分割成⼀些相对独⽴的,即DLL⽂件,放置于系统中。
当我们执⾏某⼀个时,相应的DLL⽂件就会被调⽤。
⼀个应⽤程序可使⽤多个DLL⽂件,⼀个DLL⽂件也可能被不同的应⽤程序使⽤,这样的DLL⽂件被称为共享DLL⽂件。
2,托管dll和⾮托管dll区别是什么?托管DLL就是能够在公共语⾔运⾏库(Common Language Runtime,简称CLR)中能够直接引⽤的,并且扩展为“DLL”的⽂件。
具体所指就是封装各种命名空间所在的DLL⽂件,如System.dll等。
⾮托管DLL就是平常所的动态链接库等,其中就包括了封装所有Windows API函数的DLL⽂件。
各种⾮托管DLL中的函数在公共语⾔运⾏库中不能直接被调⽤,⽽需要经过.Net框架提供的“平台调⽤”服务后才可以。
(简⽽⾔之就是.net环境下⽣成的动态链接库为托管dll,相反则为⾮托管dll)3,托管dll和⾮托管dll如何使⽤?托管dll在VS环境下使⽤相对容易,可以在项⽬名上右击选择添加应⽤的⽅式导⼊dll,本⽂这⾥不作详解。
⾮托管dll的使⽤步骤及如下:1,需要检查使⽤的dll的⽬标平台(Any Cpu,x86,x64),在项⽬属性⽣成选项卡中选择与dll相对应的⽬标平台。
因为托管dll是在.net的环境下⽣成的,转换为机器语⾔后能够⾃动识别⽬标平台即有框架⽀持解释,⽽⾮托管不能够⾃⼰识别需要⼈为的设置。
2,使⽤DllImport导⼊⾮托管dll。
DllImport会按照以下3种顺序查找dll⽂件:1)、exe所在⽬录;2)、System32⽬录(系统⽬录);3)、环境变量⽬录。
(即需要将dll及依赖⽂件放到3个⽬录中的任何⼀个⽬录中)。
DLL的创建与调用1、DLL的概念DLL(Dynamic Linkable Library),动态链接库,可以向程序提供一些函数、变量或类。
这些可以直接拿来使用。
静态链接库与动态链接库的区别:(1)静态链接库与动态链接库都是共享代码的方式。
静态链接库把最后的指令都包含在最终生成的EXE 文件中了;动态链接库不必被包含在最终EXE文件中,EXE文件执行时可以“动态”地引用和卸载这个与EXE独立的DLL文件。
(2)静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接库。
动态链接库的分类:Visual C++支持三种DLL,它们分别是Non-MFC DLL(非MFC动态库)、MFC Regular DLL(MFC规则DLL)、MFC Extension DLL(MFC扩展DLL)。
非MFC动态库不采用MFC 类库结构,其导出函数为标准的C接口,能被非MFC或MFC编写的应用程序所调用;MFC规则DLL 包含一个继承自CWinApp的类,但其无消息循环;MFC扩展DLL采用MFC的动态链接版本创建,它只能被用MFC类库所编写的应用程序所调用。
2、创建一个DLL2.1 非MFC的DLL2.1.1声明导出函数:extern “C” __declspec(dllexport) int add(int a, int b);其中extern “C”为声明为C编译。
由于C++编译器在编译的时候会造成其函数名的该变,在其他应用程序中导致函数不可调用,而C编译器则不会在编译后改变其函数名。
这样如果用C编译的程序来调用该dll中的函数时,可能会造成找不到该函数。
__declspec(dllexport)表示该函数为DLL输出函数,即其他应用程序可以调用该函数从dll中声明输出函数有两种方式:(1)另外一种方式是采用模块定义(.def) 文件声明,.def文件为链接器提供了有关被链接程序的导出、属性及其他方面的信息。
Visual C++ 指导教程演练:创建和使用动态链接库(C++)Visual Studio 2010其他版本0(共1)对本文的评价是有帮助评价此主题我们将创建的第一种类型的库是动态链接库(DLL)。
使用DLL 是一种重用代码的绝佳方式。
您不必在自己创建的每个程序中重新实现同一例程,而只需对这些例程编写一次,然后从需要该功能的应用程序引用它们即可。
本演练涵盖以下内容:∙创建新的动态链接库(DLL) 项目。
∙向动态链接库添加类。
∙创建引用动态链接库的应用程序。
∙在控制台应用程序中使用类库的功能。
∙运行应用程序。
系统必备本主题假定您具备C++ 语言的基础知识。
如果您是刚开始学习C++,建议您参阅Herb Schildt 编写的“C++ Beginner's Guide”(《C++ 初学者指南》),该书可从/fwlink/?LinkId=115303在线获得。
创建新的动态链接库(DLL) 项目1.从“文件”菜单中,选择“新建”,然后选择“项目…”。
2.在“项目类型”窗格中,选择“Visual C++”下的“Win32”。
3.在“模板”窗格中,选择“Win32 控制台应用程序”。
4.为项目选择一个名称,如MathFuncsDll,并将其键入“名称”字段。
为解决方案选择一个名称,如DynamicLibrary,并将其键入“解决方案名称”字段。
5.单击“确定”启动Win32 应用程序向导。
在“Win32 应用程序向导”对话框的“概述”页中,单击“下一步”。
6.在“Win32 应用程序向导”中的“应用程序设置”页中,选择“应用程序类型”下的“DLL”(如果可用),或者选择“控制台应用程序”(如果“DLL”不可用)。
某些版本的Visual Studio 不支持通过使用向导创建DLL 项目。
您可以稍后对此进行更改,以将项目编译为DLL。
7.在“Win32 应用程序向导”的“应用程序设置”页中,选择“附加选项”下的“空项目”。
8.单击“完成”创建项目。
向动态链接库添加类1.若要为新类创建头文件,请从“项目”菜单中选择“添加新项…”。
将显示“添加新项”对话框。
在“类别”窗格中,选择“Visual C++”下的“代码”。
在“模板”窗格中选择“头文件(.h)”。
为头文件选择一个名称,如MathFuncsDll.h,并单击“添加”。
将显示一个空白文件。
2.添加一个名为“MyMathFuncs”的简单类,以执行常见的算术运算,如加、减、乘和除。
代码应与以下内容类似:复制// MathFuncsDll.hnamespace MathFuncs{class MyMathFuncs{public:// Returns a + bstatic __declspec(dllexport) double Add(double a, doubleb);// Returns a - bstatic __declspec(dllexport) double Subtract(double a, dou ble b);// Returns a * bstatic __declspec(dllexport) double Multiply(double a, dou ble b);// Returns a / b// Throws DivideByZeroException if b is 0static __declspec(dllexport) double Divide(double a, double b);};}3.请注意此代码方法声明中的__declspec(dllexport)修饰符。
这些修饰符使DLL 能够导出该方法以供其他应用程序使用。
有关更多信息,请参见dllexport, dllimport。
4.若要为新类创建源文件,请从“项目”菜单中选择“添加新项…”。
将显示“添加新项”对话框。
在“类别”窗格中,选择“Visual C++”下的“代码”。
在“模板”窗格中,选择“C++ 文件(.cpp)”。
为源文件选择一个名称,如MathFuncsDll.cpp,并单击“添加”。
将显示一个空白文件。
5.在源文件中实现“MyMathFuncs”的功能。
代码应与以下内容类似:复制// MathFuncsDll.cpp// compile with: /EHsc /LD#include "MathFuncsDll.h"#include <stdexcept>using namespace std;namespace MathFuncs{double MyMathFuncs::Add(double a, double b){return a + b;}double MyMathFuncs::Subtract(double a, double b){return a - b;}double MyMathFuncs::Multiply(double a, double b){return a * b;}double MyMathFuncs::Divide(double a, double b){if (b == 0){throw new invalid_argument("b cannot be zero!");}return a / b;}}6.若要将项目生成为DLL,请从“项目”菜单中选择MathFuncsDll“属性...”。
在左窗格中,选择“配置属性”下的“常规”。
在右窗格中,将“配置类型”更改为“动态库(.dll)”。
单击“确定”保存更改。
注意如果您从命令行生成项目,请使用/LD编译器选项指定输出文件应为DLL。
有关更多信息,请参见/MD、/MT、/LD(使用运行库)。
7.编译该动态链接库,方法是选择“生成”菜单中的“生成解决方案”。
这样就创建了一个可供其他程序使用的DLL。
有关DLL 的详细信息,请参见DLL。
创建引用动态链接库的应用程序1.若要创建将引用并使用刚创建的动态链接库的应用程序,请从“文件”菜单中选择“新建”,然后选择“项目...”。
2.在“项目类型”窗格中,选择“Visual C++”下的“Win32”。
3.在“模板”窗格中,选择“Win32 控制台应用程序”。
4.为项目选择一个名称(如MyExecRefsDll),并将其键入“名称”字段。
从“解决方案”旁边的下拉列表中选择“添入解决方案”。
这会将新项目添加到该动态链接库所属的同一个解决方案中。
5.单击“确定”启动“Win32 应用程序向导”。
在“Win32 应用程序向导”对话框的“概述”页中,单击“下一步”。
6.在“Win32 应用程序向导”的“应用程序设置”页中,选择“应用程序类型”下的“控制台应用程序”。
7.在“Win32 应用程序向导”的“应用程序设置”页中,清除“附加选项”下的“预编译头”复选框。
8.按“完成”创建项目。
在控制台应用程序中使用类库的功能1.创建新的控制台应用程序后,将为您创建一个空程序。
源文件的名称与您在前面为项目选择的名称相同。
在本示例中,名为“MyExecRefsDll.cpp”。
2.若要使用在动态链接库中创建的算术例程,则必须引用该库。
若要执行此操作,请在解决方案资源管理器中选择MyExecRefsDll 项目,然后从“项目”菜单中选择“引用...”。
在“属性页”对话框中,展开“通用属性”节点,选择“框架和引用”,然后选择“添加新引用...”按钮。
有关“引用...”对话框的更多信息,请参见“<Projectname> 属性页”对话框->“通用属性”->“框架和引用”。
3.显示“添加引用”对话框。
此对话框列出了所有可以引用的库。
“项目”选项卡列出了当前解决方案中的所有项目,以及它们包含的所有库。
在“项目”选项卡中,选择MathFuncsDll。
然后单击“确定”。
4.若要引用动态链接库的头文件,必须修改包含目录路径。
为此,请在“属性页”对话框中展开“配置属性”节点,然后展开“C/C++”节点,并选择“常规”。
在“附加包含目录”旁边,键入MathFuncsDll.h 头文件所在位置的路径。
5.可执行文件仅在运行时加载动态链接库。
必须告诉系统在哪里查找“MathFuncsDll.dll”。
您可以通过使用PATH环境变量做到这一点。
为此,请在“属性页”对话框中展开“配置属性”节点,并选择“调试”。
在“环境”旁边键入以下内容:PATH=<MathFuncsDll.dll文件的路径>,其中<MathFuncsDll.dll文件的路径> 应替换为MathFuncsDll.dll 的实际位置。
单击“确定”保存所有更改。
注意如果要从命令行而不是从Visual Studio 运行可执行文件,则必须在命令提示符处手动更新PATH 环境变量,如下所示:set PATH=%PATH%;<MathFuncsDll.dll文件的路径>,其中<MathFuncsDll.dll文件的路径> 应替换为MathFuncsDll.dll 的实际位置。
6.现在,可以在应用程序中使用“MyMathFuncs”类了。
使用以下代码替换“MyExecRefsDll.cpp”的内容:复制// MyExecRefsDll.cpp// compile with: /EHsc /link MathFuncsDll.lib#include <iostream>#include "MathFuncsDll.h"using namespace std;int main(){double a = 7.4;int b = 99;cout << "a + b = " <<MathFuncs::MyMathFuncs::Add(a, b) << endl;cout << "a - b = " <<MathFuncs::MyMathFuncs::Subtract(a, b) << endl;cout << "a * b = " <<MathFuncs::MyMathFuncs::Multiply(a, b) << endl;cout << "a / b = " <<MathFuncs::MyMathFuncs::Divide(a, b) << endl;return 0;}7.通过从“生成”菜单中选择“生成解决方案”,生成可执行文件。