JAVA调用C语言写的SO文件

简介:
 因为 工作需要写一份SO文件,作为 手机硬件IC读卡和APK交互的桥梁,也就是中间件,看了网上有说到JNI接口技术实现,这里转载了一个实例
1 // 用JNI实现
2 // 实例:
3
4 // 创建HelloWorld.java
5 class HelloWorld
6 {
7     private native void print();
8     public static void main(String[] args)
9     {
10         new HelloWorld().print();
11     }
12
13     static
14     {
15         System.loadLibrary("HelloWorld");
16     }
17 }
18 // 注意print方法的声明,关键字native表明该方法是一个原生代码实现的。另外注意static代码段的System.loadLibrary调用,这段代码表示在程序加载的时候,自动加载libHelloWorld.so库。
19 // 编译HelloWorld.java
20 // 在命令行中运行如下命令:
21 javac HelloWorld.java
22 // 在当前文件夹编译生成HelloWorld.class。
23 // 生成HelloWorld.h
24 // 在命令行中运行如下命令:
25 javah -jni HelloWorld
26 // 在当前文件夹中会生成HelloWorld.h。打开HelloWorld.h将会发现如下代码:
27 /* DO NOT EDIT THIS FILE - it is machine generated */
28 #include <jni.h>
29 /* Header for class HelloWorld */
30
31 #ifndef _Included_HelloWorld
32 #define _Included_HelloWorld
33 #ifdef __cplusplus
34 extern "C" {
35 #endif
36 /*
37  * Class:     HelloWorld
38  * Method:    print
39  * Signature: ()V
40  */
41 JNIEXPORT void JNICALL Java_HelloWorld_print
42 (JNIEnv *, jobject);
43
44 #ifdef __cplusplus
45 }
46 #endif
47 #endif
48 // 该文件中包含了一个函数Java_HelloWorld_print的声明。这里面包含两个参数,非常重要,后面讲实现的时候会讲到。
49 // 实现HelloWorld.c
50 // 创建HelloWorld.c文件输入如下的代码:
51 #include <jni.h>
52 #include <stdio.h>
53 #include "HelloWorld.h"
54
55 JNIEXPORT void JNICALL
56 Java_HelloWorld_print(JNIEnv *env, jobject obj)
57 {
58     printf("Hello World!\n");
59 }
60 // 注意必须要包含jni.h头文件,该文件中定义了JNI用到的各种类型,宏定义等。
61 // 另外需要注意Java_HelloWorld_print的两个参数,本例比较简单,不需要用到这两个参数。但是这两个参数在JNI中非常重要。
62 // env代表 java虚拟机环境,Java传过来的参数和c有很大的不同,需要调用JVM提供的接口来转换成C类型的,就是通过调用env方法来完成转换的。
63 // obj代表调用的对象,相当于c++的this。当c函数需要改变调用对象成员变量时,可以通过操作这个对象来完成。
64 // 编译生成libHelloWorld.so
65 // 在 Linux下执行如下命令来完成编译工作:
66 cc -I/usr/lib/jvm/java-6-sun/include/linux/
67 -I/usr/lib/jvm/java-6-sun/include/
68 -fPIC -shared -o libHelloWorld.so HelloWorld.c
69 // 在当前目录生成libHelloWorld.so。注意一定需要包含Java的include目录(请根据自己系统环境设定),因为Helloworld.c中包含了jni.h。
70 // 另外一个值得注意的是在HelloWorld.java中我们LoadLibrary方法加载的是“HelloWorld”,可我们生成的Library却是libHelloWorld。这是Linux的链接规定的,一个库的必须要是:lib+库名+.so。链接的时候只需要提供库名就可以了。
71 // 运行Java程序HelloWorld
72 // 大功告成最后一步,验证前面的成果的时刻到了:
73 java HelloWorld
74 // 如果你这步发生问题,如果这步你收到java.lang.UnsatisfiedLinkError异常,可以通过如下方式指明共享库的路径:
75 java -Djava.library.path='.' HelloWorld
76 // 当然还有其他的方式可以指明路径请参考《在Linux平台下使用JNI》。
77 // 我们可以看到久违的“Hello world!”输出了。
 试着去完成,自己生成了一份com_test_GetMsg.h头文件,并完成test.c,生成libtest.so文件,JAVA调用SO文件时,屡次报:
  failed: Cannot load library: load_library(linker.cpp:761): not a valid ELF executable: /data/app-lib/com.example.iccommtest-libtest.so
  也就是提供的SO无法load,是valid的。
  注意,刚才引用的实例是JAVA调用SO,而我需要的是android调用SO,不然会频繁上面错误。
   原因有两点:
  1、JAVA和android的虚拟环境不一样
  2、Linux和android的系统库文件不一样
  这样导致了在Linux下通过JNI标准命名方式编译的SO文件,在android是调用失败的,原因是Linux和android的系统库不一样,而生产的SO跟生产环境库文件有依赖关系,然后搭建了NDK和Cywin环境,然后生产的SO可以被android调用,
  那么SO文件就必须完全遵循JNI命名规则,方法名是这样:
/*
* Class:     com_samples_jni_test
* Method:    GetMsg
* Signature: ()V
*/
JNIEXPORT jstring JNICALL Java_com_samples_jni_test_GetMsg
(JNIEnv *, jobject);
  通过NDK和Cywin生产libtest.so,android调用成功!

最新内容请见作者的GitHub页:http://qaseven.github.io/
相关文章
|
8月前
|
Java Unix Go
【Java】(8)Stream流、文件File相关操作,IO的含义与运用
Java 为 I/O 提供了强大的而灵活的支持,使其更广泛地应用到文件传输和网络编程中。!但本节讲述最基本的和流与 I/O 相关的功能。我们将通过一个个例子来学习这些功能。
315 1
|
11月前
|
存储 Java 编译器
深入理解Java虚拟机--类文件结构
本内容介绍了Java虚拟机与Class文件的关系及其内部结构。Class文件是一种与语言无关的二进制格式,包含JVM指令集、符号表等信息。无论使用何种语言,只要能生成符合规范的Class文件,即可在JVM上运行。文章详细解析了Class文件的组成,包括魔数、版本号、常量池、访问标志、类索引、字段表、方法表和属性表等,并说明其在Java编译与运行过程中的作用。
317 0
|
11月前
|
存储 人工智能 Java
java之通过Http下载文件
本文介绍了使用Java实现通过文件链接下载文件到本地的方法,主要涉及URL、HttpURLConnection及输入输出流的操作。
755 0
|
11月前
|
监控 Java API
Java语言按文件创建日期排序及获取最新文件的技术
这段代码实现了文件创建时间的读取、文件列表的获取与排序以及获取最新文件的需求。它具备良好的效率和可读性,对于绝大多数处理文件属性相关的需求来说足够健壮。在实际应用中,根据具体情况,可能还需要进一步处理如访问权限不足、文件系统不支持某些属性等边界情况。
470 14
|
存储 Java 数据安全/隐私保护
Java技术栈揭秘:Base64加密和解密文件的实战案例
以上就是我们今天关于Java实现Base64编码和解码的实战案例介绍。希望能对你有所帮助。还有更多知识等待你去探索和学习,让我们一同努力,继续前行!
691 5
|
网络协议 安全 Java
实现Java语言的文件断点续传功能的技术方案。
像这样,我们就完成了一项看似高科技、实则亲民的小工程。这样的技术实现不仅具备实用性,也能在面对网络不稳定的挑战时,稳稳地、不失乐趣地完成工作。
599 0
|
存储 编译器 程序员
c语言的文件操作与文件缓冲区
如果没有文件,我们写的程序的数据是存储在电脑的内存中,如果程序退出,内存回收,数据就丢失了,等再次运行程序,是看不到上次程序的数据的,如果要将数据进行持久化的保存,我们可以使用文件。磁盘(硬盘)上的文件是文件。但是在程序设计中,我们⼀般谈的⽂件有两种:程序文件、数据文件(从文件功能的角度来分类 的)。就比如说我们电脑中以.txt为后缀的就是文件的一种,他就是数据文件。.exe为后缀的就为程序文件。函数名功能适用范围fgetc字符输入函数所有输入流fputc字符输出函数所有输出流fgets。
509 0
|
前端开发 Cloud Native Java
Java||Springboot读取本地目录的文件和文件结构,读取服务器文档目录数据供前端渲染的API实现
博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
Java||Springboot读取本地目录的文件和文件结构,读取服务器文档目录数据供前端渲染的API实现
|
Java API 数据处理
深潜数据海洋:Java文件读写全面解析与实战指南
通过本文的详细解析与实战示例,您可以系统地掌握Java中各种文件读写操作,从基本的读写到高效的NIO操作,再到文件复制、移动和删除。希望这些内容能够帮助您在实际项目中处理文件数据,提高开发效率和代码质量。
883 4
|
人工智能 C语言