用c语言制作动画相关的函数,C/C++ (函数、变量和类)动态库的创建、导出和使用...

一Windows库

1引入库的原因:

a.项目的复杂程度大

b.提高代码的利益利用率

2库的分类

2.1静态库: *.lib,不能被加载的程序,可以理解为目标程序的归档。

2.2动态库:*.dll,可以被应用程序加载的程序。

二 动态库

1动态库优点

1.1可以提供模块化的方式,方便协调开发(对于大项目,每个人写的东西编译为动态库,直接链接即可)

1.2对源代码保护

1.3减小可执行文件大小

1.4提高代码重用率

2动态库的基本使用方法

2.1动态库的创建

2.2加载动态库

2.3获取并使用库函数、变量或类

2.4释放动态库

3动态库的函数

3.1动态库的创建

3.1.1创建DLL项目

创建Win32Dll项目,创建DLL项目,添加*.cpp文件。

111901408_1_20170926052441818

3.1.2增加动态库函数

3.1.3导出动态库函数(告诉使用者动态库中可提供的函数,代码示例如上)

(1)使用__declspec(dllexport)方式,在函数前增加关键字。举例如下:

__declspec(dllexport) intDll_Add(intnLeft,intnRight){

return(nLeft + nRight);

}//C++方式导出

(2)增加extern

“C”方式,举例如下

extern"C" __declspec(dllexport)//  以C语言方式导出函数

(3)使用def方式导出(在项目中添加*.def文件)

//*.def文件中信息

LIBRARY dllfunc.dll //导出库

EXPORTS        //导出表

Dll_Mul @1   //导出函数

Dll_Div @2

(VC6中def导出方式与 extern “C”导出方式导出.lib文件内容基本相同,可用于显式链接)

动态库导出函数代码示例如下:

#include

#include 

using namespace std;

BOOL WINAPI DllMain(//返回值代表是否记载成功

HINSTANCE hinstDll,//DLL句柄

DWORD   fdwReason,//DLL被调用的原因

LPVOID  lpvReserved)//保留值

{

cout <

cout <

return TRUE;

}

//C++导出方式

extern "C" __declspec (dllexport)  int Dll_Add(int nLeft, int nRight)

{

return (nLeft + nRight);

}

//C的导出方式

extern "C"__declspec (dllexport)  int Dll_Sub(int nLeft, int nRight)

{

return (nLeft - nRight);

}

//DEF导出方式

int Dll_Mul(int nLeft, int nRight)

{

return (nLeft * nRight);

}

111901408_2_2017092605244237.png

3.2 使用

3.2.1隐式链接

(1)导入lib

a.在项目属性->链接器->输入->附加依赖项中设置即可。

b.使用#pragma导入,举例如下:

#pragma comment (lib,"../lib/Dll_Func.lib")

(2) 定义函数原型

声明一个和导出函数一致的函数原型,如下所示:

#pragma comment (lib,"../lib/Dll_Func.lib")

extern "C" int  Dll_Add(int nLeft, int nRight);

extern "C" int  Dll_Sub(int nLeft, int nRight);

(3) 使用函数(注意:生成.dll文件最好与调用其的.exe文件在同一个目录)

直接使用函数即可,示例代码如下:

#include 

#pragma comment (lib,"../lib/Dll_Func.lib")

extern "C" int  Dll_Add(int nLeft, int nRight);

extern "C" int  Dll_Sub(int nLeft, int nRight);

int Dll_Mul(int nLeft, int nRight);

int main()

{

int nAdd = Dll_Add(100, 100);

int nSub = Dll_Sub(100, 100);

int nMul = 0;//Dll_Mul(100, 100);

printf("nAdd = %d\n", nAdd);

printf("nSub = %d \n", nSub);

printf("nMul = %d \n", nMul);

return 0;

}

(4) 应用程序查找Dll路径(最好将要调用的动态库与调用动态库的.exe文件放在同一目录下)

A查找当前应用程序的目录

B当前工作目录

C查找Windows System32目录

D查找Windows System的目录

E查找Windows目录

F查找环境变量Path指定的目录

3.2.2显式链接

(1)加载动态库

LoadLibraryW(

LPCSTR lpLibFileName  //DLL文件路径

);

(2) 定义函数原型对应的函数指针

(3)获取函数地址

FARPROC  GetProcAddress(//返回对应函数地址

HMODULE hModule, // DLL句柄

LPCSTR lpProcName);//函数名称

注意:a.__declspec(dllexport)导出的函数由于函数名称发生变化,所以无法使用函数名称获取对应函

数地址,所以尽量采用隐式链接的方式。

b. extern “C”__declspec(dllexport)方式导出的函数可以正常使用函数名称获取函数地址。

c.使用def导出方式在VC6.0下可使用显示链接(本人在VS2013中对def导出方式导出动态库未成功使

用,希望哪位大神可以指点迷津)

(4)使用函数

(5)释放动态库

FreeLibrary(HMOUDLE)

显式链接示例代码如下:

#include 

#include  /

#include 

using namespace std;

typedef int(*DLL_ADD)(int nLeft, int nRight);

typedef int(*DLL_SUB)(int nLeft, int nRight);

typedef int(*DLL_MUL)(int nLeft, int nRight);

void useDll()

{

HMODULE  hDll = LoadLibrary(_T("Dll_Func.dll"));

if (nullptr == hDll)

{

cout <

return;

}

//定义函数指针

DLL_ADD Dll_Add = nullptr;

DLL_SUB Dll_Sub = nullptr;

DLL_MUL Dll_Mul = nullptr;

//获取函数地址

Dll_Add = (DLL_ADD)GetProcAddress(hDll, "Dll_Add");

if (nullptr == Dll_Add)

{

cout <

}

cout <

Dll_Sub = (DLL_SUB)GetProcAddress(hDll, "Dll_Sub");

if (nullptr == Dll_Sub)

{

cout <

}

cout <

Dll_Mul = (DLL_MUL)GetProcAddress(hDll, "Dll_Mul");

if (nullptr == Dll_Mul)

{

cout <

}

cout <

//使用函数

int nSub = Dll_Sub(100, 100);

int nAdd = Dll_Add(100, 100);

cout <

cout <

//释放动态库

FreeLibrary(hDll);

}

int main()

{

useDll();

return 0;

}

4.动态库中的变量

4.1定义全局变量

4.2导出全局变量

4.2.1  __declspec(dllexport)导出

4.2.2 DEF导出

Int g_nValue1 = 100;

在DEF文件中到处列表增加g_nValue1 @1 DATA

4.3导入LIB文件

4.4声明导入变量

需要使用__declspec(dllimport)声明变量,举例如下:

extern__declspec(dllimport)intg_nValuel;

4.5使用变量

动态库变量使用代码示例如下:

#include 

using namespace std;

#pragma comment(lib,"../lib/DllValue.lib")

//声明DLL导入变量

extern __declspec(dllimport) int g_nValue1;//动态库导出文件中有此全局变量,在此再次声明此变量原型

int main()

{

cout <

return 0;

}

5动态库的类导出

5.1创建静态库并定义类

5.2导出类

在类名称前__declspec(dllexport)定义:

class__declspec(dllexport)Math

{……}

导出类示例代码如下:

//**.h文件

#ifndef _MATH_H_

#define _MATH_H_

//定义类导入导出宏,

#ifdef _DLLCLASS_DLL__

#define DLLCLASS_EXT  __declspec(dllexport)

#else

#define DLLCLASS_EXT  __declspec(dllimport)

#endif //_DLLCLASS_DLL_

//增加类的导入 导出符号

class DLLCLASS_EXT Math

{

public:

Math()

{

}

virtual ~Math()

{

}

int Add(int nLeft, int nRight);

int Sub(int nLeft, int nRight);

};

#endif

//**.cpp文件

#include "Math.h"

int Math::Add(int nLeft, int nRight)

{

return (nLeft + nRight);

}

int Math::Sub(int nLeft, int nRight)

{

return (nLeft - nRight);

}

5.3使用时导入LIB文件

5.4导入类

5.5使用类

5.6关于类的导入和导出

5.6.1定义一个宏,举例如下(避免多次编写类头文件,使之可在导出、导入时使用同一个头文件):

#ifdef_DLLCLASS_DLL__

#defineDLLCLASS_EXT __declspec(dllexport)

#else

#define DLLCLASS_EXT  __declspec(dllimport)

#endif//_DLLCLASS_DLL_

5.6.2根据编译项目修改_DLLCLASS_DLL__宏声明,对于导出类,需定义_DLLCLASS_DLL__,否则,不需要定义_DLLCLASS_DLL__。

在导出类时,项目设置如下(即定义_DLLCLASS_DLL__宏):

111901408_3_20170926052442193

6 DllMain函数(用于变量初始化等操作。使用可参照3.1.3 (3)中示例代码)

Dll文件的入口函数,当程序加载或者释放动态库的时候,会自动调用此函数

BOOL WINAPIDllMain(//返回值代表是否加载成功

HINSTANCEhinstDll;//DLL句柄

DWORD  fdwReason;//DLL被调用的原因

LPVOID lpvReserved;)//保留值

FdwReason –

DLL_PROCESS_ATTACH进程加载

DLL_THREAD_ATTACH线程加载

DLL_PROCESS_DETACH进程卸载

DLL_THREAD_DETACH线程卸载

使用导出类代码示例如下:

#include 

#include "..\DllClass\Math.h"

using namespace std;

#pragma comment(lib,"../lib/DllClass.lib")

int main(int argc, char *argv[])

{

Math math;

int add = math.Add(100,100);

int sub = math.Sub(100,100);

cout <

cout <

return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值