Java调用本地代码(一)—— 创建动态链接库

近期项目需要使用Java调用本地一个很老的C写的库,就顺便研究了下Java调用本地代码的一些方法。整理一下出一个小系列。主要就是介绍两种不同的方法:JNIJNA。作为第一篇,我们先动手用C写个简单的动态链接库,为后面的文章做准备。

什么是动态链接库

先做个基础的普及。C/C++编译出来的库有两种:静态链接库和动态链接库。

静态库后缀名在Windows上是.lib,Unix/Linux上是.a。当你的程序在编译时引用静态库,编译器会将整个静态库都包含在你编译后的可执行文件中,所以可执行文件会很大,但是程序执行时就不再需要静态库了。

动态库后缀名在Windows上是.dll,一般存放在”C:\Windows\System32″下;Unix/Linux上是.so,一般存放在”/lib”或”/usr/lib”下。程序编译时,编译器不会将动态库包含在生成的可执行文件中,所以引用动态库的可执行文件较小,程序会在运行过程中动态加载所需要的库。对于Java程序员就可以将它简单的想象成.jar文件。在Unix/Linux上,动态链接库一般都命名为libxxx.so,其中xxx是库名。

创建动态链接库

这里我们使用Linux环境,用C语言创建一个动态链接库”libhello.so”,库里面就提供一个hello()函数。根据输入的字符串,在屏幕上打印相应的欢迎信息。

  1. 编写头文件”hello.h”,声明hello()函数
  1. 编写程序文件”hello.c”,根据输入参数打印Hello信息
  1. 编译生成动态链接库
  2. $ gcc hello.c -fPIC -shared -o libhello.so

现在你就可以在当前目录下找到”libhello.so”文件。这样,动态链接库就创建好了。我们先写个C程序测试下。

测试动态链接库

我们写个C程序来调用刚才创建的动态链接库。

  1. 编写测试程序”test.c”
  1. 编译并生成可执行文件
  2. $ gcc test.c -L . -lhello -o test

    参数”-L .”表明除了系统指定的目录外,还会从当前目录里搜索需要引用的库。参数”-lhello”指明需要链接名为hello的库,也就是文件名为”libhello.so”的库。编译后,会在本地生成名为”test”的可执行文件。

  1. 查看可执行文件的依赖库
  2. Linux提供”ldd”命令来查看可执行文件运行时需依赖的动态链接库。我们查看下刚才生成的”test”文件:

    $ ldd ./test

    命令执行后,你会看到类似于下面的这段信息

    从第二行中你可以看到,该程序依赖于库”libhello.so”,而且该库文件存在于当前目录下”./libhello.so”。如果你将该文件移走,这里就会显示”not found”,程序自然也无法执行。

  1. 运行可执行文件
  2. 在运行前,你先要将当前目录加到环境变量LD_LIBRARY_PATH中。程序执行时,会在其中搜索需加载的库。

    $ export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH

    运行测试程序

    $ ./test Billy

    你可以看到屏幕上打印出了

    恭喜你,测试通过!

用C++也一样,这里就不再做描述了。下一篇,我们将介绍如何使用JNI的方法从Java语言调用刚才创建的动态链接库。

本例代码可以从这里下载

发表评论

电子邮件地址不会被公开。 必填项已用*标注