iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >怎么在Java中调用C/C++本地库
  • 771
分享到

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

2023-06-17 10:06:35 771人浏览 八月长安
摘要

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

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

--结束END--

本文标题: 怎么在Java中调用C/C++本地库

本文链接: https://www.lsjlt.com/news/288444.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

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

下载Word文档
猜你喜欢
  • 怎么在Java中调用C/C++本地库
    本篇内容介绍了“怎么在Java中调用C/C++本地库”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!编写Java类我们来编写一个Sample1...
    99+
    2023-06-17
  • C++中怎么调用C链接库
    本篇文章给大家分享的是有关C++中怎么调用C链接库,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。C++调用C链接库,其实相对C调用C++。因为C++本来就向下兼容C吧但由于编译...
    99+
    2023-06-17
  • 怎么在java中调用本地扬声器
    怎么在java中调用本地扬声器?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1.首先,我们需要一个dll作为辅助。这里解释一下dll的含义(DLL(Dynamic Link...
    99+
    2023-06-15
  • java怎么调用c++动态库
    要在Java中调用C++动态库,可以使用JNI(Java Native Interface)技术。以下是通过JNI调用C++动态库的...
    99+
    2023-10-20
    java c++
  • C#中怎么使用IronPython库调用Python脚本
    在C#中使用IronPython库调用Python脚本的步骤如下: 首先,需要将IronPython库添加到C#项目中。可以通过...
    99+
    2024-03-08
    python C#
  • 在java中怎么利用jna调用c#中dll
    这篇文章给大家介绍在java中怎么利用jna调用c#中dll,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。JNA(Java Native Access )提供一组Java工具类用于在运行期动态访问系统本地库(nativ...
    99+
    2023-05-31
    java jna
  • C++中怎么调用Python脚本
    C++中怎么调用Python脚本,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。#test function   def add...
    99+
    2023-06-17
  • 怎么在C++中调用Python
    小编给大家分享一下怎么在C++中调用Python,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!Python的安装为了使用Python.h这个扩展项,我们需要安装一...
    99+
    2023-06-15
  • rust怎么调用c++库
    在Rust中调用C++库,可以使用Rust的FFI(Foreign Function Interface)功能来实现。以下是一般的步...
    99+
    2023-10-26
    rust c++
  • c++ pthread库怎么调用
    要使用pthread库,需要引入头文件`#include `。 下面是一个简单的示例,展示了如何使用pthread库创建和运行一个线...
    99+
    2023-10-26
    c++ pthread
  • C#怎么连接本地数据库
    这篇文章主要讲解了“C#怎么连接本地数据库”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C#怎么连接本地数据库”吧!使用环境 C#VSCodeM11. 安装MySQL下载MySQL...
    99+
    2023-06-29
  • C#怎么调用js库
    这篇文章主要介绍“C#怎么调用js库”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“C#怎么调用js库”文章能帮助大家解决问题。安装ClearScriptClearScript是微软开源的js引擎,支...
    99+
    2023-07-05
  • golang怎么调用c++库
    要在Golang中调用C++库,你需要使用CGo,它是Golang与C/C++代码交互的一种方式。下面是一个简单的示例,展示了如何调...
    99+
    2023-10-20
    golang c++
  • C++中怎么调用python脚本函数
    本篇文章给大家分享的是有关C++中怎么调用python脚本函数,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。C++调用python脚本函数代码如下:Py_Initialize(...
    99+
    2023-06-17
  • C#使用IronPython库调用Python脚本
    IronPython是一种在 .NET及 Mono上的 Python实现,由微软的 Jim Hugunin所发起,是一个开源的项目,基于微软的 DLR引擎。 IronPython的主...
    99+
    2024-04-02
  • C++中怎么调用C接口
    本篇文章为大家展示了C++中怎么调用C接口,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。C++如何调用C接口首先提供一个C接口:#include"test.h" voi...
    99+
    2023-06-16
  • 怎么在C++中调用python代码
    这篇文章主要介绍了怎么在C++中调用python代码,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。一、环境设置windowsVS2015python的话用的是acaconda...
    99+
    2023-06-22
  • c#怎么调用java方法
    在 c# 中调用 java 方法可以通过以下两种机制:使用 java native interface (jni):提供了在不同编程语言之间调用本地方法的接口。需手动加载 jvm、查找类...
    99+
    2024-05-12
    access c#
  • unity怎么调用c++动态库
    要在Unity中调用C++动态库,可以按照以下步骤进行操作:1. 创建C++动态库:首先,使用C++编写你的库,并将其编译为动态库(...
    99+
    2023-09-20
    unity c++
  • C++/CLI怎么调用C#
    这篇文章主要讲解了“C++/CLI怎么调用C#”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++/CLI怎么调用C#”吧!跨越语言的障碍:C++/CLI 调用 C#当C#项目需要引用C++...
    99+
    2023-06-17
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作