本篇介绍的是静态库函数。
静态库扩展名一般是.lib(windows上)或.a(linux上),他和动态库(dll)是有区别的。调用静态库编译后会写入执行程序中。然后就可以独立运行了。动态库旨在动态调用,调用的时候需要加载dll才能正常工作(所以动态库往往可以提供补丁,或功能升级的时候使用,但是运行的速度有待商协)。另外,两个库的编译器也不一样,例如mingw用g++生成动态库*.dll, 用ar生成静态库*.a;而VC则一律用link.exe生成生成动态和静态库,用options来区别生成哪种。
下面把若干的C++和C文件在MinGW上编译成一个静态库函数文件,然后在Windows上调用这个库函数。假设我们有两个库函数文件myf1.cpp和myf2.c
/*
myf1.cpp
*/
#include <stdio.h>
void f1_Fonction1(int a, double b, char *c)
{
printf("调用文件myf1.cpp的f1_Fonction1成功\n");
}
int f1_Fonction2(int c)
{
printf("调用文件myf1.cpp的f1_Fonction2成功\n");
return c+1;
}
/*
* myf2.c
*/
#include <stdio.h>
void f2_Fonction1(void)
{
printf("调用文件myf2.c的f2_Fonction1成功\n");
}
int f2_Fonction2(int c)
{
printf("调用文件myf2.c的f2_Fonction2成功\n");
return c+2;
}
上面两个文件一个是C++的,另一个是C的。两个文件各提供了两个函数。 首先我们用gcc命令将他们编译成目标文件myf1.o和myf2.o
gcc -c myf1.cpp myf2.c
接着使用ar命令生成静态库
ar r mylib.lib myf1.o myf2.o
这样就生成了一个静态库mylib.lib
现在,我们尝试在windows上调用这个库中的一个函数试试看
写一个简单的调用的C++程序main.cpp
/*
main.cpp
*/
#include <iostream>
using namespace std;
void f1_Fonction1(int a, double b, char *c);
int main()
{
char c;
f1_Fonction1(1,2.0,&c); //调用了myf1里面的函数f1_Fonction
cout << "Hello world!" << endl;
return 0;
}
然后用MinGW编译,先生成main.o文件
gcc -c main.cpp
接着把main.o和函数库mylib.lib连接起来生成main.exe文件
g++ -o main.exe main.o mylib.lib
注意链接的顺序,函数库必须在主函数后面。另外,因为main.cpp是C++格式,所以link的时候要用g++编译器,否则gcc编译器会出现没有定义std::cout 这类的错误信息。
另外一个值得注意的是,虽然VC的.lib和Linux的.a格式是相同,即都是一种归档文件格式,但是由于在VC编译的程序中函数列表需要符号索引 (如果你用 reimp -s mylib.lib 察看VC的lib文件就会发现,函数名都被加了冗长的前后缀),所以vc的lib似乎无法直接在gcc上连接通过,同样的gcc的.a似乎也无法在vc上使用。虽然也有些文章讨论过lib和a的转换问题,配合使用reimp和dlltool命令转换。但是我的测试中发现转换后的库文件还是无法调用。如果有人成功的实现vc和gcc的静态库互换,请务必留言告诉我具体方法。