`

JNI Linux下在应用程序中加载动态库和静态库

    博客分类:
  • JNI
jni 
阅读更多
Linux 中的应用程序以以下两种方式之一链接到外部函数:要么在构建时与静态库( lib*.a ) 静态地链接,并且将库代码包含在该应用程序的可执行文件里;要么在运行时与共
享库( lib*.so ) 动态地链接。通过动态链接装入器,将动态库映射进应用程序的可执行内存中。在启动应用程序之前,动态链接装入器将所需的共享目标库映射到应用程序的
内存,或者使用系统共享的目标并为应用程序解析所需的外部引用。现在应用程序就可以运行了。

void *dlopen( const char *file, int mode );//将共享目标文件打开并且映射到内存中,并且返回句柄
void *dlsym( void *restrict handle, const char *restrict name );//回一个指向被请求入口点的指针
char *dlerror();//返回 NULL 或者一个指向描述最近错误的 ASCII 字符串的指针
char *dlclose( void *handle );//关闭句柄并且取消共享目标文件的映射
例子说明:在test.c中调用sayHi();
文件清单
Test.java
class Test {
public native void sayHi();
public static void main(String[] args) {
  Test test=new Test();
  test.sayHi();
}
static {
System.loadLibrary("test");
}
}
Test.h

#include <jni.h>
#ifndef _Included_Test
#define _Included_Test
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT void JNICALL Java_Test_sayHi
  (JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif

test.c (适用于第一种情况)
#include <stdio.h>
#include <dlfcn.h>
#include "Test.h"
void  *FunctionLib;         /*  Handle to shared lib file   */
int   (*Function)();        /*  Pointer to loaded routine   */
const char *dlError;        /*  Pointer to error string     */
JNIEXPORT void JNICALL Java_Test_sayHi(JNIEnv* env, jobject obj)
{
  int   rc;             /*  return codes            */
  char HelloMessage[] = "HeLlO WoRlD\n";

  FunctionLib = dlopen("/yijia/libtest2.so",RTLD_LAZY);
  dlError = dlerror();
  printf("1 \n", dlError);
  if( dlError ) exit(1);

  Function    = dlsym( FunctionLib, "sayHi");
  dlError = dlerror();
  printf("2\n", dlError);
  if( dlError ) exit(1);

  rc = (*Function)( HelloMessage );
  printf("3 \n", dlError);

  rc = dlclose(FunctionLib);
  dlError = dlerror();
  printf("4 \n",dlError);
  if( rc ) exit(1);
  rc = dlclose(FunctionLib);
  dlError = dlerror();
  printf("5 \n",dlError);
  if( rc ) exit(1);
 
}

test2.c
#include <stdio.h>
void sayHi(char str[])
{
printf("hi!.... %s \n",str);

}
----------------------------------------------------------

test.c (适用于第二种情况)
#include <stdio.h>
#include "Test.h"
JNIEXPORT void JNICALL Java_Test_sayHi(JNIEnv* env, jobject obj)
{
  //sayHi("hello!\n");
//jni函数实现调用sayHi(),继续学习jni的函数
}

第一种情况:加载动态库*.so
step1.新建java文件,编译,生成头文件
javac Test.java
javah Test
step2.新建test.c文件,生成动态库.so文件
生成libtest2.so
gcc  -c -fpic test2.c
gcc -shared -o libtest2.so test2.o
生成libtest.so
gcc  -c -fpic test.c
gcc -shared -lc -o libtest.so test.o -ldl
  -ldl选项,表示生成的对象模块需要使用共享库
step3.运行java文件

java -Djava.library.path=. Test
./Test
第二种情况:加载静态库*.a

step1.新建java文件,编译,生成头文件
javac Test.java
javah Test
step2.新建test2.c文件,生成静态库.a文件
生成libtest2.a
gcc -c test2.c -o test2.o //编译成目标文件
ar rs libtest2.a test2.o //打包成一个静态库
参数r表示将后面的文件列表添加到文件包,如果文件包不存在就创建它,如果文件包中已有同名文件就替换成新的。
参数s是专用于生成静态库的,表示为静态库创建索引,这个索引被链接器使用。

生成libtest.a
gcc -c test.c -o test.o //编译成目标文件
ar rs libtest.a test.o //打包成一个静态库
step3.运行java文件
java -Djava.library.path=. Test
./Test
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics