【win32】day11-windows的库/静态库/动态库

Windows的库

  由于项目的复杂程度,或者为了提高代码的

  重用率等等,所以才引入了库程序。

  库包含两种:

    1 静态库:扩展名为LIB的文件,是不能被

        加载的程序,可以理解为目标程序的

        归档。

    2 动态库:扩展名是DLL的文件,是可以被

        应用程序加载的程序。

静态库

1 静态库的特点
1.1 目标程序的归档
1.2 静态库的代码会被嵌入到程序当中。
1.3 程序执行时不需要静态库存在


2 C语言静态库
2.1 创建静态库
创建Win32静态库项目,使用*.C文件建立项目。

int C_Add( int nAdd1, int nAdd2 )
{
	return ( nAdd1 + nAdd2 );
}

int C_Sub( int nSub1, int nSub2 )
{
	return ( nSub1 - nSub2 );
}
2.2 添加静态库函数
2.3 在程序中将静态库导入
   2.3.1 项目的Setting里设置, link选项
   2.3.2 使用关键字 pragma
#pragma comment(lib, "../lib/winclib.lib")
2.4 使用静态库提供的函数
   在C语言程序中,直接使用函数即可。

//导入静态库
#pragma comment(lib, "../lib/winclib.lib")

int main( )
{ 
	int nAdd = 0;
	int nSub = 0;
	//使用C静态库的函数
	nAdd = C_Add( 100, 100 );
	nSub = C_Sub( 100, 100 );

	printf( "ADD: %d\n", nAdd );
	printf( "SUB: %d\n", nSub );

	return 0;
}

3 C++语言的静态库

3.1 创建静态库

   创建Win32静态库项目,使用*.CPP文件建立项目。

int CPP_Add( int nAdd1, int nAdd2 )
{
	return ( nAdd1 + nAdd2 );
}

int CPP_Sub( int nSub1, int nSub2 )
{
	return ( nSub1 - nSub2 );
}

3.2 添加静态库的函数

3.3 导入静态库

   3.3.1 项目的Setting里设置

   3.3.2 使用关键字 pragma

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

3.4 定义库函数的原形

   int CPP_Add( int nAdd1, int nAdd2 );

3.5 使用库函数

3.6 注意:

   如果在CPP文件使用C语言静态库,定义的

   静态库函数原形,需要增加 extern "C".

   例如:

   extern "C" int C_Add( int nAdd1, int nAdd2 );

// usecpplib.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

//导入C++的静态库
#pragma comment( lib, "../lib/wincpplib.lib" )
#pragma comment( lib, "../lib/winclib.lib" )

//定义函数原形
int CPP_Add( int nAdd1, int nAdd2 );
int CPP_Sub( int nSub1, int nSub2 );

extern "C" {

int C_Add( int nAdd1, int nAdd2 );
int C_Sub( int nSub1, int nSub2 );

}

int main(int argc, char* argv[])
{	//使用C++库函数
	int nAdd = CPP_Add( 100, 100 );
	int nSub = CPP_Sub( 100, 100 );
	printf( "ADD: %d\n", nAdd );
	printf( "SUB: %d\n", nSub );
	//使用C库函数
	int nAdd2 = C_Add( 100, 100 );
	int nSub2 = C_Sub( 100, 100 );
	printf( "C_ADD: %d\n", nAdd );
	printf( "C_SUB: %d\n", nSub );

	return 0;
}

动态库

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的项目
  使用Win32 DLL项目,创建DLL,添加相应的文件。 
3.1.2 增加动态库函数
3.1.3 导出动态库函数
 3.1.3.1 使用__declspec(dllexport)方式
在函数前增加这个关键字,例如
__declspec(dllexport) int Dll_Add()
3.1.3.2 增加 extern "C" 方式,即
  extern "C" __declspec(dllexport)
  以C语言方式导出函数

#include "windows.h"
#include "stdio.h"

BOOL WINAPI DllMain( HINSTANCE hinstDLL,
	DWORD fdwReason, LPVOID lpvReserved )
{
	printf( "DLL=%p, Reason=", hinstDLL );
	switch( fdwReason )
	{
	case DLL_PROCESS_ATTACH:
		printf( "DLL_PROCESS_ATTACH\n" );
		break;
	case DLL_THREAD_ATTACH:
		printf( "DLL_THREAD_ATTACH\n" );
		break;
	case DLL_THREAD_DETACH:
		printf( "DLL_THREAD_DETACH\n" );
		break;
	case DLL_PROCESS_DETACH:
		printf( "DLL_PROCESS_DETACH\n" );
		break;
	}
	return TRUE;
}

//C++导出方式
__declspec(dllexport) int Dll_Add( int nAdd1, int nAdd2 )
{
	return ( nAdd1 + nAdd2 );
}
//C的导出方式
extern "C" __declspec(dllexport) int Dll_Sub( int nSub1, int nSub2 )
{
	return ( nSub1 - nSub2 );
}
//DEF的导出方式
int Dll_Mul( int nMul1, int nMul2 )
{
	return ( nMul1 * nMul2 );
}

3.1.3.3 使用DEF文件导出

 增加扩展名为DEF的文件到项目中.

 DEF文件中添加导出定义.

  LIBRARY dllfunc.dll //导出库

EXPORTS             //导出表

  Dll_Mul @1      //导出函数

  Dll_Div @2

LIBRARY dllfunc.dll
EXPORTS 
	Dll_Mul	@1

3.2 使用

  3.2.1 隐式链接

3.2.1.1 导入LIB

  项目的Setting或者使用#pragma导入,例如:

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

3.2.1.2 定义函数原形

  声明一个和导出函数一致的函数定义.

  如果DLL采用extern "C"导出函数,

  需要定义extern "C"方式函数原形

3.2.1.3 使用函数

  直接函数即可

3.2.1.4 应用程序查找DLL的路径

  1) 查找当前应用程序的目录.

  2) 当前的工作目录

  3) 查找Windows System32的目录

  4) 查找Windows System的目录

  5) 查找Windows目录

  6) 查找环境变量PATH指定路径

// CallDllFunc.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

//导入DLL的Lib文件
#pragma comment( lib, "../lib/dllfunc.lib")

//定义函数原形
int Dll_Add( int nAdd1, int nAdd2 );
extern "C" int Dll_Sub( int nSub1, int nSub2 );
int Dll_Mul( int nMul1, int nMul2 );

int main(int argc, char* argv[])
{	// 使用函数
	int nAdd = Dll_Add( 100, 100 );
	int nSub = Dll_Sub( 100, 100 );
	int nMul = Dll_Mul( 100, 100 );
	printf("Dll_Add: %d\n", nAdd );
	printf("Dll_Sub: %d\n", nSub );
	printf("Dll_Mul: %d\n", nMul );
	return 0;
}

3.2.2 显示链接    

3.2.2.1 加载动态库

  HINSTANCE LoadLibrary(

LPCTSTR lpLibFileName );//DLL的路径

  返回加载好DLL的句柄

3.2.2.2 定义函数原形对应的函数指针

3.2.2.3 获取函数地址

   FARPROC GetProcAddress(

  HMODULE hModule,//DLL的句柄

  LPCSTR lpProcName );//函数的名称

返回对应函数地址

注意:

1 对于__declspec(dllexport)导出的函数,

  由于函数名称发生变化,所以无法使用

  函数名称获取对应的函数地址,所以

  尽量采用隐式链接的方式.

2 extern "C"DEF方式导出的函数,

  可以正常的使用函数名称获取函数地址.

3.2.2.4 使用函数

3.2.2.5 释放动态库

   FreeLibrary

// InvokeDllFunc.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "windows.h"

typedef int ( * DLL_ADD )( int nAdd1, int nAdd2 );
typedef int ( * DLL_SUB )( int nSub1, int nSub2 );
typedef int ( * DLL_MUL )( int nMul1, int nMul2 );

void UseDll( )
{	//加载动态库
	HMODULE hDll = (HMODULE)
		LoadLibrary( "dllfunc.dll" );
	if( hDll == NULL )
	{
		printf( "Load Failed\n");
		return;
	}
	printf( "DLL Handle: %p\n", hDll );

	//定义函数指针
	DLL_ADD Dll_Add = NULL;
	DLL_SUB Dll_Sub = NULL;
	DLL_MUL Dll_Mul = NULL;
	//获取函数地址
	Dll_Add = ( DLL_ADD )
		GetProcAddress( hDll, "Dll_Add" );
	if( NULL == Dll_Add )
	{
		printf( "Get Dll_Add Failed\n");
	}
	printf( "Dll_Add: %p\n", Dll_Add );

	Dll_Sub = ( DLL_SUB )
		GetProcAddress( hDll, "Dll_Sub" );
	if( NULL == Dll_Sub )
	{
		printf( "Get Dll_Sub Failed\n");
	}
	printf( "Dll_Sub: %p\n", Dll_Sub );

	Dll_Mul = ( DLL_MUL )
		GetProcAddress( hDll, "Dll_Mul" );
	if( NULL == Dll_Mul )
	{
		printf( "Get Dll_Mul Failed\n");
	}
	printf( "Dll_Mul: %p\n", Dll_Mul );
	//使用函数
	int nSub = Dll_Sub( 100, 100 );
	int nMul = Dll_Mul( 100, 100 );
	printf( "Dll_Sub: %d\n", nSub );
	printf( "Dll_Mul: %d\n", nMul );
	//释放动态库
	FreeLibrary( hDll );
}

int main(int argc, char* argv[])
{
	UseDll( );
	return 0;
}

4 动态库的变量

 

  4.1 定义全局变量

  4.2 导出全局变量

 4.2.1 __declspec(dllexport)导出

__declspec(dllexport) int g_nValue1 = 100;

 4.2.2 DEF文件导出

int g_nValue1 = 100;

DEF文件的导出列表中增加

  g_nValue1 @1 DATA

4.3 导入LIB文件

  4.4 定义导入变量

 需要使用__declspec(dllimport)定义变量.

 extern __declspec(dllimport) int g_nValue1;

  4.5 使用变量

// usevalue.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

//导入LIB
#pragma comment( lib, "../lib/dllvalue.lib")
//定义DLL导入变量
extern __declspec(dllimport) int g_nValue1;
extern __declspec(dllimport) int g_nValue2;

int main(int argc, char* argv[])
{
	printf("g_nValue1 = %d\n", g_nValue1 );
	printf("g_nValue2 = %d\n", g_nValue2 );
	return 0;
}

5 动态库的类

 

  5.1 创建动态库并定义类

  5.2 DLL中导出类

 在类名称前增加__declspec(dllexport)定义.

 class __declspec(dllexport) CMath

 { ... };

  5.3 使用时导入LIB文件

  5.4 导入类

 在类名称前增加__declspec(dllimport)定义.

 class __declspec(dllimport) CMath

 { ... };

  5.5 使用类

  5.6 关于类的导入和导出

1) 定义一个宏,例如:

  #ifdef _DLLCLASS_DLL_

#define DLLCLASS_EXT __declspec(dllexport)

#else

#define DLLCLASS_EXT __declspec(dllimport)

#endif //_DLLCLASS_DLL_

  2) 根据编译项目,修改_DLLCLASS_DLL_宏声明

对于导出类,需要定义_DLLCLASS_DLL_,

否则不需要定义 _DLLCLASS_DLL_

  3) 类的定义为

class DLLCLASS_EXT CMath

{ ... };

#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 CMath 
{
public:
	int Add( int nAdd1, int nAdd2 );
	int Sub( int nSub1, int nSub2 );
};
#endif //_MATH_H_

#include "math.h"

int CMath::Add( int nAdd1, int nAdd2 )
{
	return ( nAdd1 + nAdd2 );
}

int CMath::Sub( int nSub1, int nSub2 )
{
	return ( nSub1 - nSub2 );
}

// useclass.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
//导入DLL的LIB文件
#pragma comment( lib, "../lib/dllclass.lib")
//需要类的导入方式的声明
#include "../DllClass/math.h"

int main(int argc, char* argv[])
{	//使用DLL中的类
	CMath math;
	int nAdd = math.Add( 100, 100 );
	int nSub = math.Sub( 100, 100 );
	printf("math.Add = %d\n", nAdd );
	printf("math.Sub = %d\n", nSub );
	return 0;
}

6 DllMain 函数

DLL文件入口函数.当程序加载或者释放

动态库的时候,会自动调用这个函数.

 BOOL WINAPI DllMain(

   HINSTANCE hinstDLL,//DLL的句柄

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

   LPVOID lpvReserved ); //保留值

 fdwReason -

   DLL_PROCESS_ATTACH 进程加载

   DLL_THREAD_ATTACH  线程加载

   DLL_THREAD_DETACH  线程卸载

   DLL_THREAD_DETACH  进程卸载

 返回值表示是否加载成功.











  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
cd C:\Program Files\FlightGear fgfs --fg-root=C:\Program Files\FlightGear\data --aircraft=ufo --in-air --fdm=null --telnet=5501 --telnet=5502 --telnet=5503 --disable-ai-traffic --disable-real-weather-fetch --disable-random-objects --disable-terrasync --disable-clouds --disable-sound --disable-panel --disable-hud --disable-specular-highlight --timeofday=noon --prop:/sim/rendering/multi-sample-buffers=1 --prop:/sim/rendering/multi-samples=2 --prop:/sim/rendering/draw-mask-clouds=false --prop:/sim/rendering/draw-mask-terrain=true --prop:/sim/rendering/draw-mask-objects=true --prop:/sim/rendering/draw-mask-lights=true --prop:/sim/rendering/draw-mask-internal=true --prop:/sim/rendering/draw-mask-cockpit=true --prop:/sim/rendering/draw-mask-effects=true --prop:/sim/rendering/draw-mask-overlay=true --prop:/sim/rendering/draw-mask-world=true --prop:/sim/rendering/draw-mask-panel=true --prop:/sim/rendering/draw-mask-vr=true --prop:/sim/rendering/draw-mask-2d=true --prop:/sim/rendering/draw-mask-3d=true --prop:/sim/rendering/draw-mask-sky=true --prop:/sim/rendering/draw-mask-shadows=true --prop:/sim/rendering/draw-mask-cabin=true --prop:/sim/rendering/draw-mask-weather=true --prop:/sim/rendering/draw-mask-stereo=true --prop:/sim/rendering/draw-mask-internal-cockpit=true --prop:/sim/rendering/draw-mask-internal-windows=true --prop:/sim/rendering/draw-mask-internal-instruments=true --prop:/sim/rendering/draw-mask-internal-overlay=true --prop:/sim/rendering/draw-mask-internal-effects=true --prop:/sim/rendering/draw-mask-internal-lights=true --prop:/sim/rendering/draw-mask-internal-world=true --prop:/sim/rendering/draw-mask-internal-panel=true --prop:/sim/rendering/draw-mask-internal-3d=true --prop:/sim/rendering/draw-mask-internal-sky=true --prop:/sim/rendering/draw-mask-internal-cabin=true --prop:/sim/rendering/draw-mask-internal-weather=true --prop:/sim/rendering/draw-mask-internal-stereo=true --prop:/sim/rendering/draw-mask-internal-shadow=true --prop:/sim/rendering/draw-mask-internal-stall=true --prop:/sim/rendering/draw-mask-internal-aoa=true --prop:/sim/rendering/draw-mask-internal-thermal=false --prop:/sim/rendering/draw-mask-internal-ice=false --prop:/sim/rendering/draw-mask-internal-glass=true --prop:/sim/rendering/draw-mask-internal-dead=true --prop:/sim/rendering/draw-mask-internal-reflection=true --telnet=127.0.0.1:5501 --disable-panel --disable-hud --disable-specular-highlight --disable-clouds --disable-sound --timeofday=noon --enable-hud-3d=no --enable-hud-2d=yes --enable-panel=no --enable-sound=no程序显示错误
05-10
这个命令有些问题。你需要在命令行中输入这个命令,并且将其中的双引号去掉。此外,你需要确保FlightGear已经安装在C:\Program Files\FlightGear目录下,并且你已经选择了一个可用的飞行器(例如: ufo)。最后,如果你需要使用telnet,你需要指定不同的端口。以下是更正后的命令: ``` cd C:\Program Files\FlightGear fgfs --fg-root=C:\Program Files\FlightGear\data --aircraft=ufo --in-air --fdm=null --telnet=5501 --telnet=5502 --telnet=5503 --disable-ai-traffic --disable-real-weather-fetch --disable-random-objects --disable-terrasync --disable-clouds --disable-sound --disable-panel --disable-hud --disable-specular-highlight --timeofday=noon --prop:/sim/rendering/multi-sample-buffers=1 --prop:/sim/rendering/multi-samples=2 --prop:/sim/rendering/draw-mask-clouds=false --prop:/sim/rendering/draw-mask-terrain=true --prop:/sim/rendering/draw-mask-objects=true --prop:/sim/rendering/draw-mask-lights=true --prop:/sim/rendering/draw-mask-internal=true --prop:/sim/rendering/draw-mask-cockpit=true --prop:/sim/rendering/draw-mask-effects=true --prop:/sim/rendering/draw-mask-overlay=true --prop:/sim/rendering/draw-mask-world=true --prop:/sim/rendering/draw-mask-panel=true --prop:/sim/rendering/draw-mask-vr=true --prop:/sim/rendering/draw-mask-2d=true --prop:/sim/rendering/draw-mask-3d=true --prop:/sim/rendering/draw-mask-sky=true --prop:/sim/rendering/draw-mask-shadows=true --prop:/sim/rendering/draw-mask-cabin=true --prop:/sim/rendering/draw-mask-weather=true --prop:/sim/rendering/draw-mask-stereo=true --prop:/sim/rendering/draw-mask-internal-cockpit=true --prop:/sim/rendering/draw-mask-internal-windows=true --prop:/sim/rendering/draw-mask-internal-instruments=true --prop:/sim/rendering/draw-mask-internal-overlay=true --prop:/sim/rendering/draw-mask-internal-effects=true --prop:/sim/rendering/draw-mask-internal-lights=true --prop:/sim/rendering/draw-mask-internal-world=true --prop:/sim/rendering/draw-mask-internal-panel=true --prop:/sim/rendering/draw-mask-internal-3d=true --prop:/sim/rendering/draw-mask-internal-sky=true --prop:/sim/rendering/draw-mask-internal-cabin=true --prop:/sim/rendering/draw-mask-internal-weather=true --prop:/sim/rendering/draw-mask-internal-stereo=true --prop:/sim/rendering/draw-mask-internal-shadow=true --prop:/sim/rendering/draw-mask-internal-stall=true --prop:/sim/rendering/draw-mask-internal-aoa=true --prop:/sim/rendering/draw-mask-internal-thermal=false --prop:/sim/rendering/draw-mask-internal-ice=false --prop:/sim/rendering/draw-mask-internal-glass=true --prop:/sim/rendering/draw-mask-internal-dead=true --prop:/sim/rendering/draw-mask-internal-reflection=true ``` 请注意,如果你需要使用telnet连接到FlightGear,你需要在另一个命令行窗口中输入telnet命令,例如: ``` telnet localhost 5501 ``` 这将连接到FlightGear的第一个telnet端口。如果你想连接到其他端口,你需要相应地更改端口号。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值