今天写一个数据结构,突然想到这种东西必然会经常复用,完全可以写个库来供以后调用。然后就研究了下code::blocks下怎么来写库,又怎么去调用。

  首先是静态库。这个最为简单,只要选择static library项目新建。写好的库ctrl+F9,就能生成一个.a文件。要调用的时候只要在所需的项目中添加一个链接库,链接到这个.a文件即可。然后在项目中添加相应的.h文件,就像是使用正常的函数一样了。

  其次是动态库。动态库略为复杂,不过也不难。首先写库的时候新建的时候选择dynamic link library,写好以后ctrl+f9会生成三个文件(10.05版本如此,好像之前的版本并非如此,还需更改编译选项,在项目属性的构建目标中选中选中红色选项框内的内容

)。生成的除了dll外,还有一个.a和一个.def文件。.def是给其它语言导入使用的,.a是一个导出库,类似于一个空壳实现。这时在新的项目中只要添加相应的头文件,并且在链接的时候链接到.a文件就行。

  当然,运行程序的时候,.dll应该在.exe的执行目录中。不要问执行目录和存放目录有什么区别……这个请参照win快捷方式的start in(或者称为启动位置?手头没有中文系统)属性。

  不过如果不是cb生成的dll呢?我们只有.dll文件和.h文件,那也没有关系。直接把.dll文件替换上述.a文件,cb会根据dll当做.h的实现的。

  如果更进一步,没有.h,只知道几个重要的函数怎么办?那也没关系,用windows.h提供的LoadLibrary函数就可以了。具体可以查看下说明。

  下边我提供代码作为一个示例:

  首先创建一个实验的动态链接库,比如我这里的LynxArrayList。 其中的main.c如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
/** @brief 简单的相加
*
* @param 第一个加数
* @param 第二个加数
* @return 返回相加的和
*
*/

int SampleAddInt(int i1, int i2)
{
    return i1 + i2;
}

version.h就不用看了,那个是自动更新版本号的。

然后更改为release,ctrl+F9,查看release目录下边生成了3个文件。然后删除除dll以外的文件(其实删不删都一样)。

新建一个普通的console application,在构造选项的链接器设置中添加刚才的.dll文件。

之后在代码中声明SampleAddInt函数就行:

LynxArrayList.h文件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#ifndef LYNXARRAYLIST_H_INCLUDED
#define LYNXARRAYLIST_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
int SampleAddInt(int i1, int i2);
#ifdef __cplusplus
}
#endif
#endif // LYNXARRAYLIST_H_INCLUDED

然后在main函数中include这个头文件,就可以使用SampleAddInt函数了。下边的主函数代码还示范了如何使用windows.h来动态加载dll,可以合理掌握dll的加载和释放时间,更加合理一些。

main.c文件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include "LynxArrayList.h"
/** @brief 主函数
*
* @return int
*
*/

int main()
{
    HINSTANCE hinstDLL;
    int (*myfunc)(int,int);
    hinstDLL = LoadLibrary("libLynxArrayList.dll");
    if(hinstDLL != 0){
        myfunc = (int (*)(int, int))GetProcAddress(hinstDLL, "SampleAddInt");
    }
    printf("%d\n",myfunc(1,2));
    FreeLibrary(hinstDLL);
    printf("%d\n",SampleAddInt(2,3));
    return 0;
}