我的编程空间,编程开发者的网络收藏夹
学习永远不晚

怎么在Java中调用C/C++本地库

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

怎么在Java中调用C/C++本地库

本篇内容介绍了“怎么在Java中调用C/C++本地库”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

编写Java类

我们来编写一个Sample1的java类

public class Sample1 {      public native int intMethod(int n);      public native boolean booleanMethod(boolean bool);      public native String stringMethod(String text);      public native int intArrayMethod(int[] intArray);             public static void main(String[] args) {          System.loadLibrary("Sample1");          Sample1 sample = new Sample1();          int square = sample.intMethod(5);          boolean bool = sample.booleanMethod(true);          String text = sample.stringMethod("Java");          int sum = sample.intArrayMethod(new int[]{1,2,3,4,5,8,13});                     System.out.println("intMethod: " + square);          System.out.println("booleanMethod: " + bool);          System.out.println("stringMethod: " + text);          System.out.println("intArrayMethod: " + sum);      }  }

上面有4个native方法, 分别是4种类型的参数, int, boolean, String, int[].

其中有一句比较重要, 这句话加载了动态类库

System.loadLibrary("Sample1");

在windows下加载的就是Sample1.dll, 在linux下加载的就是Sample1.so。

本文使用的windowws, 所以后面使用Sample1.dll来表示Sample1动态链接库。

注意:不可以在代码中写上后缀dll或so. 还要保证Sample1.dll在path路径中. 这个Sample1.dll是我们后面需要编译出来的东西。

4个native方法就是我们需要用C来实现的方法。

编译Sample1.java, 使用命令行(windows是cmd, linux下一般是bash)

>javac Sample1.java

可以看到Sample1.class文件

使用javah生成头文件

在命令行中运行

>javah Sample1

可以在目录下看到一个新文件Sample1.h

 #include <jni.h>      #ifndef _Included_Sample1  #define _Included_Sample1  #ifdef __cplusplus  extern "C" {  #endif   JNIEXPORT jint JNICALL Java_Sample1_intMethod    (JNIEnv *, jobject, jint);      JNIEXPORT jboolean JNICALL Java_Sample1_booleanMethod    (JNIEnv *, jobject, jboolean);      JNIEXPORT jstring JNICALL Java_Sample1_stringMethod    (JNIEnv *, jobject, jstring);      JNIEXPORT jint JNICALL Java_Sample1_intArrayMethod    (JNIEnv *, jobject, jintArray);     #ifdef __cplusplus  }  #endif  #endif

我们可以看到其中有四个函数声明, Java_完整类名_方法名, 完整类名包括了包名, 例如demo.Sample1是完整类名, 对应的这里就是demo_Sample1.

在注释中我们可以看到这样一个东西 Signature, 这个是方法的签名. 关于Signature, 下面通过一个表格来说明。

java类型Signature备注
booleanZ 
byteB 
charC 
shortS 
intI 
longL 
floatF 
doubleD 
voidV 
objectL用/分割的完整类名例如: Ljava/lang/String表示String类型
Array[签名例如: [I表示int数组, [Ljava/lang/String表示String数组
Method(参数签名)返回类型签名例如: ([I)I表示参数类型为int数组, 返回int类型的方法

上面头文件的***个函数声明

JNIEXPORT jint JNICALL Java_Sample1_intMethod (JNIEnv *, jobject, jint);

注释中的签名是 Signature: (I)I

在每个函数的参数列表中都有JNIEnv *和 jobject两个参数, 这两个参数稍候说明。

实现头文件中的函数

可以使用C语言来实现, 也可以使用C++来实现, 下面先说说C语言的实现。

#include "Sample1.h" #include <string.h>     JNIEXPORT jint JNICALL Java_Sample1_intMethod    (JNIEnv *env, jobject obj, jint num)  {      return num * num;  }     JNIEXPORT jboolean JNICALL Java_Sample1_booleanMethod    (JNIEnv *env, jobject obj, jboolean boolean)  {      return !boolean;  }     JNIEXPORT jstring JNICALL Java_Sample1_stringMethod    (JNIEnv *env, jobject obj, jstring string)  {      const char* str = (*env)->GetStringUTFChars(env, string, 0);      char cap[128];      strcpy(cap, str);      (*env)->ReleaseStringUTFChars(env, string, 0);      return (*env)->NewStringUTF(env, strupr(cap));  }     JNIEXPORT jint JNICALL Java_Sample1_intArrayMethod    (JNIEnv *env, jobject obj, jintArray array)  {      int i, sum = 0;      jsize len = (*env)->GetArrayLength(env, array);      jint *body = (*env)->GetIntArrayElements(env, array, 0);             for (i = 0; i < len; ++i)      {          sum += body[i];      }      (*env)->ReleaseIntArrayElements(env, array, body, 0);      return sum;  }

(*env)->GetStringUTFChars()这个方法, 是用来在Java和C之间转换字符串的, 因为Java本身都使用了双字节的字符, 而C语言本身都是单字节的字符, 所以需要进行转换.

JNIEnv *是每个函数都有的参数, 它包含了很多有用的方法, 使用起来类似Java的反射, 也提供了这样一个编码转换的函数.

GetStringUTFChars()和NewStringUTF(), ***个是从UTF8转换为C的编码格式, 第二个是根据C的字符串返回一个UTF8字符串.

ReleaseStringUTFChars()是用来释放对象的, 在Java中有虚拟机进行垃圾回收, 但是在C语言中, 这些对象必须手动回收. 否则可能造成内存泄漏.

函数的名字一眼看到就可以猜出功能, jni.h中的大部分函数名都是这样.

如果是C++的话, 这段代码该怎么写?

下面是C++的代码

#include "Sample1.h"  #include <string.h>     JNIEXPORT jint JNICALL Java_Sample1_intMethod    (JNIEnv *env, jobject obj, jint num)  {      return num * num;  }     JNIEXPORT jboolean JNICALL Java_Sample1_booleanMethod    (JNIEnv *env, jobject obj, jboolean boolean)  {      return !boolean;  }     JNIEXPORT jstring JNICALL Java_Sample1_stringMethod    (JNIEnv *env, jobject obj, jstring string)  {      const char* str = env->GetStringUTFChars(string, 0);      char cap[128];      strcpy(cap, str);      env->ReleaseStringUTFChars(string, 0);      return env->NewStringUTF(strupr(cap));  }     JNIEXPORT jint JNICALL Java_Sample1_intArrayMethod    (JNIEnv *env, jobject obj, jintArray array)  {      int i, sum = 0;      jsize len = env->GetArrayLength(array);      jint *body = env->GetIntArrayElements(array, 0);             for (i = 0; i < len; ++i)      {          sum += body[i];      }      env->ReleaseIntArrayElements(array, body, 0);      return sum;  }

上述两端代码非常相似, 只有一个不同点

C代码: (*env)->GetStringUTFChars(env, string, 0);

C++代码: env->GetStringUTFChars(string, 0);

C语言中使用的是结构体的函数指针, 而在C++中使用的还是struct, 我们知道struct在C++中和class的功能是几乎一样的, struct也可以用来定义类, 所以env在C++中是个类对象的指针.

编译和运行

这里使用的是微软编译器, 编译C语言版的dll

>cl -I%JAVA_HOME%\include -I%JAVA_HOME%\include\win32 -LD Sample1.c -FeSample1.dll

编译C++版本的dll

>cl -I%JAVA_HOME%\include -I%JAVA_HOME%\include\win32 -LD Sample1.cpp -FeSample1.dll

运行

>java Sample1

注意: 64位版本的JDK可能会在运行时报错:

java.lang.UnsatisfiedLinkError: ...Sample1.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform

如果您有这样的错误, 请使用32位的JDK来重新运行.

运行结果如下:

intMethod: 25 booleanMethod: false stringMethod: JAVA intArrayMethod: 36

“怎么在Java中调用C/C++本地库”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

怎么在Java中调用C/C++本地库

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

怎么在Java中调用C/C++本地库

本篇内容介绍了“怎么在Java中调用C/C++本地库”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!编写Java类我们来编写一个Sample1
2023-06-17

C++中怎么调用C链接库

本篇文章给大家分享的是有关C++中怎么调用C链接库,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。C++调用C链接库,其实相对C调用C++。因为C++本来就向下兼容C吧但由于编译
2023-06-17

java怎么调用c++动态库

要在Java中调用C++动态库,可以使用JNI(Java Native Interface)技术。以下是通过JNI调用C++动态库的一般步骤:1. 编写C++动态库:- 创建C++源代码文件,实现所需的功能。- 使用C++编译器将源代码编译
2023-10-20

怎么在java中调用本地扬声器

怎么在java中调用本地扬声器?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1.首先,我们需要一个dll作为辅助。这里解释一下dll的含义(DLL(Dynamic Link
2023-06-15

C#中怎么使用IronPython库调用Python脚本

在C#中使用IronPython库调用Python脚本的步骤如下:首先,需要将IronPython库添加到C#项目中。可以通过NuGet包管理器搜索IronPython,并将其添加到项目中。创建一个Python脚本文件,编写需要调用的Pyt
C#中怎么使用IronPython库调用Python脚本
2024-03-08

在java中怎么利用jna调用c#中dll

这篇文章给大家介绍在java中怎么利用jna调用c#中dll,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。JNA(Java Native Access )提供一组Java工具类用于在运行期动态访问系统本地库(nativ
2023-05-31

C++中怎么调用Python脚本

C++中怎么调用Python脚本,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。#test function def add(a,b): print "in py
2023-06-17

怎么在C++中调用Python

小编给大家分享一下怎么在C++中调用Python,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!Python的安装为了使用Python.h这个扩展项,我们需要安装一
2023-06-15

c++ pthread库怎么调用

要使用pthread库,需要引入头文件`#include `。下面是一个简单的示例,展示了如何使用pthread库创建和运行一个线程。#include #include // 线程函数,用于并行执行的任务void* threadFu
2023-10-26

rust怎么调用c++库

在Rust中调用C++库,可以使用Rust的FFI(Foreign Function Interface)功能来实现。以下是一般的步骤:创建一个Rust项目,可以使用`cargo new`命令来创建一个新的项目。在项目目录下创建一个C++库
2023-10-26

golang怎么调用c++库

要在Golang中调用C++库,你需要使用CGo,它是Golang与C/C++代码交互的一种方式。下面是一个简单的示例,展示了如何调用一个C++库:首先,创建一个名为example.cpp的C++源文件,其中包含需要调用的函数:cpp#in
2023-10-20

C#怎么调用js库

这篇文章主要介绍“C#怎么调用js库”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“C#怎么调用js库”文章能帮助大家解决问题。安装ClearScriptClearScript是微软开源的js引擎,支
2023-07-05

C#怎么连接本地数据库

这篇文章主要讲解了“C#怎么连接本地数据库”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C#怎么连接本地数据库”吧!使用环境 C#VSCodeM11. 安装MySQL下载MySQL软件,傻瓜
2023-06-29

C++中怎么调用python脚本函数

本篇文章给大家分享的是有关C++中怎么调用python脚本函数,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。C++调用python脚本函数代码如下:Py_Initialize(
2023-06-17

C++中怎么调用C接口

本篇文章为大家展示了C++中怎么调用C接口,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。C++如何调用C接口首先提供一个C接口:#include"test.h" void testCfun() {
2023-06-16

怎么在C++中调用python代码

这篇文章主要介绍了怎么在C++中调用python代码,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。一、环境设置windowsVS2015python的话用的是acaconda
2023-06-22

c#怎么调用java方法

在 c# 中调用 java 方法可以通过以下两种机制:使用 java native interface (jni):提供了在不同编程语言之间调用本地方法的接口。需手动加载 jvm、查找类和方法 id,并使用 jnienv 对象调用 java
c#怎么调用java方法
2024-05-12

unity怎么调用c++动态库

要在Unity中调用C++动态库,可以按照以下步骤进行操作:1. 创建C++动态库:首先,使用C++编写你的库,并将其编译为动态库(.dll文件)或共享库(.so文件)。2. 创建Unity项目:在Unity中创建一个新的项目或打开现有项目
2023-09-20

C#中怎么调用iisapp.vbs

C#中怎么调用iisapp.vbs,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。C#调用iisapp.vbs代码:usingSystem; usingSystem.Tex
2023-06-17

C#中怎么调用CreateObject

这篇文章给大家介绍C#中怎么调用CreateObject,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。如在VB中的源代码如下:PublicSubTestLateBind() DimoAsObject=CreateOb
2023-06-18

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录