javaapi:api

“接口”,生活中一个很普通的概念。电梯开门关门的按钮;摩托车响喇叭的按钮;打开电视的遥控;等等;这些
都是接口。为什么要有接口,是因为有接口会更好,并非没有接口就不行。想像一下,如果没有接口,那么看到的可
能是一团凌乱的电路线,在使用功能时要按说明把“外界”接到其中的某条线路上,这样也ok,但显然有一些问题:
第一不好看,第二不好用,第三因为可以接触到线路而可能引发别的问题。现在,把电路线绑一下,加一个铁壳罩起
来,再开一口引个按钮出来。这时外界看到的是一个黑盒子,要使用功能就直接点按钮。显然接口避免了许多问题。
而且接口的形式是可以保持一百年不变的,即使黑盒子内部发生了翻天覆地的变化,而按钮还是老样子,使用的人
很容易接受。

API就是方便使用的接口。可以做自己的接口。
以下是用vc6.0安装目录\Program Files\Microsoft Visual Studio\VC98\Bin中的cl.exe作一个dll接口的过程,最
终要给接口使用者提供lib文件和dll文件(至少要有这两个)。直接使用cl.exe是为了去掉ide向导的混淆。
cl.exe用于编译链接,它也是一个接口,需要指定参数。这些参数中经常可能代表着一个文件(比如
Kernel32.lib;比如windows.h等),为了避免写漫长的全路径,一般可以先设置路径变量(环境变量),设置
的方法有几种,最简单的是,运行\Program Files\Microsoft Visual Studio\VC98\Bin下面的VCVARS32.BAT文件,
这个文件有set INCLUDE之类的动作。具体过程如下:运行cmd,把VCVARS32.BAT拉到cmd界面运行,继续使用这个
cmd。
假设要编译的源文件为a.cpp,假设不需要写它的全路径(完全可以做到),则把a.cpp编译成一个exe的命令如下:
cl.exe a.cpp
这将成生a.exe,如果想要重命名,则写成:
cl.exe a.cpp /FeOther.exe
如此则生成Other.exe。/Fe这个是重命名的选项,选项是区分大小写的!/Fe与新名字之间是没有空格的!

如果a.cpp里面用到了别人提供的接口,如MessageBox(在user32.dll中实现),则要加上链接选项,这样写:
cl.exe a.cpp /FeOther.exe /link user32.lib

如果想生成dll,这个是现在最终要的东西,则加上/LD表示生成dll的选项,这样写:
cl.exe /LD a.cpp /FeOther.dll /link user32.lib
这样就生成Other.dll。如果a.cpp中真的提供了导出接口(即可给外界使用的接口),则还会生成lib文件。
如果没有导出接口则不会生成lib,由此并结合链接过程可以推断,lib肯定是记录了导出接口的信息(比如它
的函数名),另外,lib肯定也记录了对应的dll文件的名字,只有这样exe运行时系统才会加载正确的dll。

这是提供接口的源文件:
#include <windows.h>

// _declspec(dllexport)说明这是个导出函数
// extern "C" 说明要兼容c代码的编译
extern "C" _declspec(dllexport)
void Api1()  // 导出函数,像系统的MessageBox实现时也应该是这样写的
{
 // 这里使用了系统的接口,使用这个接口之前要说明它是导入函数,这在windows.h里面作了说明。
 MessageBox(NULL, TEXT("calling api1"), TEXT("提示"), MB_OK);
}

int Sum(int a, int b)  // 这不是导出接口,因为它没有加extern "C" _declspec(dllexport)
{
 return a + b;
}

int  main()  // 入口点像一般程序那样照写,但不会被执行,因为它不是导出函数,也未尝被内部调用。
{
 return 0;
}
以上编译后生成lib和dll。

这是使用Api1接口的源文件(使用接口则要加入对应的lib和dll,比如放到工程目录下):
// 告诉编译器链接时使用a.lib,它应该在工程目录下,因为它没有写全路径
#pragma comment (lib, "a.lib") 

// 说明这个是导入的函数(在别的模块中实现了),查一下MessageBox的声明
// 可以看到它也是这样声明的,尽管它写在一个单独的文件中而且加了重重的宏定义,
// 但它本来的面目就是这样的。
extern "C" _declspec(dllimport) 
void Api1();

int main()
{
 Api1();  // 接口使用

 return 0;
}

如果提供的接口有多个,可以写成这样:
extern "C"
{
 _declspec(dllexport) void Api1();
 _declspec(dllexport) void Api2();
 ... 
}
同样,使用接口时,也可以把导入接口的说明放到一个文件中,再引入这个文件。
技巧太多,容易隐藏真相。

windows系统到处都是接口,也就是到处都在用lib和dll,像user32.lib/dll,gdi32.lib/dll,kernel32.lib/dll等。
同样,我们也可以这样做,如果我们喜欢的话。

Tags:  api函数 jqueryapi windowsapi javaapi

延伸阅读

最新评论

发表评论