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
分享到:
相关推荐
在这个"JNI源码和动态库实验参考"的压缩包中,我们很可能会发现一系列关于JNI编程的实例和相关动态库文件。 JNI源码通常包含两部分:Java源代码和C/C++源代码。Java源代码会声明native方法,这些方法的实现是在C/...
通过JNI,Java可以调用外部的动态链接库或静态库中的函数,并能够访问这些库中的数据类型和结构。 #### 三、加载动态链接库的过程 1. **声明Native方法**:在Java代码中声明native方法,这些方法只定义了方法签名...
通过JNI调用第三方动态库在Android开发中是常见操作,涉及到的知识点包括Java本地方法声明、JNI接口定义、Makefile编写以及NDK编译。在实际操作过程中,务必注意代码的正确性,因为一个小错误都可能导致编译失败或...
1. **创建Java类**:首先创建一个名为`HelloWorld`的Java类,声明两个native方法`setMsg`和`getMsg`,并在静态块中加载动态库。 ```java public class HelloWorld { static { System.loadLibrary("HelloWorld"); ...
如果希望减少应用程序的体积,或者多个应用共享同一库,可以选择动态库;如果想要确保库的独立性,避免版本冲突,或者在没有网络更新库的情况下也能正常运行,静态库是更好的选择。 FFmpeg编译时可能需要配置以下...
4. **静态库和动态库**:静态库(如`libfaac.a`)在编译时会被链接到目标程序中,而动态库(如`libfaac.so`)则在运行时加载。在Android和Linux环境下,选择使用哪种库取决于项目需求,如是否需要减小程序体积、跨...
4. **编译本地库**:将实现的C/C++代码编译为动态链接库或静态库,依赖于目标平台。 5. **加载本地库**:在Java代码中使用`System.loadLibrary`加载本地库,使Java虚拟机能够找到并调用本地方法。 值得注意的是,...
在Java程序中,静态代码块`System.loadLibrary("hello")`确保在运行时加载了动态库。这样,Java就可以调用C++代码实现的功能,实现了Java和本地代码的无缝交互。 通过这个简单的例子,我们可以看到JNI的使用并不...
- 动态注册是在C/C++代码中完成的,使用`JNI_OnLoad`函数,当JNI库被加载时,Java虚拟机(JVM)会调用这个函数。 - 示例: ```c++ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { JNIEnv *...
在您提供的压缩包中包含的全平台静态库意味着您将能够为 Android、iOS、Windows、Mac 和 Linux 平台的项目集成 `curl` 功能。 1. **curl 的主要功能**: - 支持多种网络协议:HTTP、HTTPS、FTP、FTPS、TFTP、SMTP...
同样使用ndk-build,但需要注意的是,Android的动态库不支持软链接,这意味着你需要为每个支持的CPU架构(armeabi, armeabi-v7a, arm64-v8a, x86, x86_64等)编译不同的.so文件,并在应用的jniLibs目录下放置对应...
动态库与静态库(.lib)不同,静态库在编译时会被直接合并到目标程序中,而动态库则是在程序运行时动态加载的。DLL可以减少程序的大小,因为多个程序可以共享同一份库的代码。C++从DLL导出类涉及到两个主要步骤:...
JNI使得开发者可以在Java程序中嵌入C/C++代码,以利用这些语言的高效性能和丰富库,比如调用操作系统级别的功能,如打开系统默认的浏览器。 以下是一个简化的步骤来实现这个功能: 1. **创建JNI接口**:首先,在...
总结,JNI基础知识涵盖了Java与C/C++的数据类型映射、交叉编译、动态库与静态库的概念以及它们在Android开发中的应用,以及JNI方法的静态注册。理解这些概念对于进行Java与C/C++的混合编程,特别是在Android平台上的...
动态链接允许在运行时加载本地库,而静态链接则是在编译时将本地代码嵌入到Java应用程序中。此外,JNI在不同操作系统中的具体实现可能会有所不同,因此手册也会介绍如何在Windows、Linux、Mac OS等平台上实现JNI代码...
本文的主要目标是通过JNI技术来实现在Java应用程序中调用已有的C++视频镜头提取程序。这一技术的应用场景非常广泛,例如在多媒体处理领域中,常常需要处理大量的视频数据,并从中提取有用的特征信息。由于C++在性能...
5. **加载和调用**:在Java代码中使用`System.loadLibrary("serial_port")`加载静态库,然后就可以调用定义好的JNI接口进行串口操作。 在HardwareControlerDemo这个项目中,很可能已经封装好了这些步骤,开发者只...
JNI,全称Java Native Interface,是Java平台标准的一部分,它为Java程序员提供了一种方法,可以在Java应用程序中调用本地(非Java)代码,同时也允许本地代码调用Java对象。JNI在很多场景下非常有用,比如优化性能...
同时,由于它是静态库,可以直接链接到你的Android应用中,无需关心动态库的加载问题。 接下来,我们谈谈如何通过Java JNI调用libcurl.a。JNI(Java Native Interface)是Java平台的一部分,允许Java代码和其他语言...