一般大型的应用程序,都不会只由一个.exe文件构成,可能包含多个.exe文件、若干个.dll文件和若干.lib文件等。
在VS中,一个解决方案下,可以包含多个项目。每个项目可以是一个独立的.exe,也可以是一个供其他项目调用函数的静态库或者动态库。这些能够被调用的.exe、.lib、.dll文件(由各项目编译链接后生成的最终二进制文件),需要向外界提供一个被其他文件调用的函数接口(API)和接口使用文档说明。(在生成最终的可执行文件后,静态库.lib在编译时已经被包含进exe文件中了,而.dll是运行exe文件时,动态加载的)
Windows API :是一套用来控制windows各部件的预先定义的windows函数;windows API使用了很多windows自己定义的数据类型,要熟练使用windows API必须要熟悉windows数据类型,而这些数据类型是windows特有的,在SDK的相关头文件有定义。
Linux API:和Windows API功能上差不多。
接下来介绍怎样调用自己写的API,在VS2005的一个解决方案中各项目之间的API调用:
1、.exe文件调用.dll动态库文件api
大致流程:1、在.dll项目中写了一个供外界调用的函数接口
2、在.exe项目的文件中,需要先找到这个.dll文件
3、找到这个目标.dll文件后,再在该目标文件中找到目标函数接口
4、找到接口后,就可以在.exe项目文件中使用
具体操作:
①、在programdll.dll项目文件写的一个函数想被外界项目调用,那么这个函数需要在.dll项目文件中要做一个被外界引用的声明。比如int add(int x,int y)函数要被外界调用,那么声明就是:extern "C" int __declspec(dllexport)add(int x,int y); //declspec前面是两个下划线。
如果已经有了一个.dll文件,不是自己写的,那么和这个.dll文件配套的应该还有一个说明文档,用以说明这个.dll文件中的可被调用api,和调用规则。
②、在.exe项目中要想引用这个.dll文件中的api,就必须先找到这个.dll文件,先声明一个函数句柄(相当于一个要指向.dll文件的指针):HINSTANCE hDll; //函数句柄
而后就是通过调用Windows API,让该句柄指向该.dll文件:
hDll=LoadLibrary(__TEXT("D:\\study software\\programdll.dll"));
//LoadLibrary是windows api,使用前需要在文件中添加windows.h头文件;TEXT前面是双下划线;找路径时,使用的是.dll文件的绝对地址,所以这个.dll文件可以在任意位置,当然也可以用相对地址。
③、如果成功找到了该.dll文件,即if( hDLL!=NULL ),那么可以进一步从该.dll文件中找目标函数。
首先,需要定义一个指向目标函数的指针,用来保存目标函数地址:
typedef int(*lpAddFun)(int,int); //类型重命名,lpAddFun相当于一个函数类型,
lpAddFun addFun; //用lpAddFun类型定义了一个指向两实参类型为int,返回值类型为int的函数指针addFun,注意是用以指向函数的指针;
接下来就是从该.dll文件中找api的地址了:
addFun=(lpAddFun)GetProcAddress(hDll,"add"); //GetProcAddress是一个windows api,它有两个参数,一个是目标.dll地址,一个是在该目标.dll文件中要查找的目标函数名字。
if(addFun!=NULL),如果查找成功,现在addFun指向的就是目标api的地址,可以通过addFun来进行函数调用。
④、使用方式:int i=addFun(3,8); //addFun是指向目标函数的一个指针,函数名字本身就是一个地址存在,所以可以直接这样写
⑤、额外需要注意的地方:最后是通过窗口提示信息来判断程序是否正确执行,所以,在程序中还用到了MessageBox函数,这又是一个windows api。而MessageBox是由User32.lib提供,所以在使用前需要先添加这个User32.lib静态库:#pragma comment (lib,"User32.lib")。最后一点就是要释放这个句柄所指向的空间:FreeLibrary(hDll);
2、.exe文件调用.lib静态库文件api
大致流程,1、写一个静态库.lib项目
2、设置路径
3、在一个.exe项目中,包含这个静态链接库,并把其头文件添加到当前文件中
4、然后直接用
具体操作:
1、输出静态库的设置:在项目(项目,而不是解决方案)上右键--属性--常规--配置类型--静态库。
写静态库项目:在静态库test项目中,按照正常操作写test.c文件,同时添加一个test.h头文件,用以存放要被外界调用api的声明。
比如test.c文件中的int add(int x,int y);函数要被外界调用,在test.h文件中进行一次声明:int add(int x,int y);//不需要额外什么操作
2、复制:把上面那个静态库项目中的test.h(test项目文件夹下)和静态项目生成的test.lib(在解决方案的debug文件夹下,而不是test项目文件夹中)一起复制到.exe项目文件夹(项目文件夹,而不是解决方案文件夹)下。
其实如果不复制这个test.lib到.exe项目文件夹下,也可以使用绝对路径。这种情况#pragma comment(lib,"test.lib"),语句中的"test.lib"就必须是test.lib所在的绝对路径地址。
3、包含:在.exe项目中,包含这个静态链接库:#pragma comment(lib,"test.lib"),并把这个静态链接库中的头文件test.h,写到.exe项目文件中。
4、然后在.exe项目文件中就可以直接使用这个test.h头文件中包含的所有函数,真是简单的操作。
3、.exe文件调用.exe文件
大致流程:1、自己写一个.exe文件
2、调用windows API进行调用
具体操作:
1、按照正常操作写一个.exe项目,并最终编译成.exe文件
2、在另一个.exe项目中调用这个.exe文件,需要windows api:WinExec CreateProcess CreateProcessAsUser选一个。
比如:在.exe项目中调用QQ.exe:WinExec("D:\\interesting software\\QQ\\Bin\\QQ.exe",SW_SHOWNORMAL);//绝对路径
当然也可以使用相对路径,不过需要最后生成的1.exe和2.exe在同一目录下。
上面三种,均用到了Windwos API,参考了《Windows API开发详解 --函数、接口、编程实例》 范文庆 周彬彬 安靖 编著的书,同时听说《windows程序设计》 《windows系统编程》(人民邮电出版社) 的书对于Windows API的描述都非常棒。