Java通过JNI调用C/C++动态链接库之参数传递及结果返回

接上一篇关于JNI的基本入门Java通过JNI调用C/C++动态链接库之HelloWorld,简述给JNI函数传递参数,以及通过JNI函数返回值的方式。

JNI类型映射
首先来回顾一下上一篇基础文章中通过javah生成的头文件的以下内容:

/*
 * Class:     hello
 * Method:    helloWorld
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_hello_helloWorld
  (JNIEnv *, jobject);

发现注释中给出了类名hello,是我们JAVA程序的类名,后面跟着方法名以及方法的签名,注意方法的签名类型为()V,表示该方法不接收任何参数,且返回类型为void,即没有返回值。
JNI定义了一些基本类型用于在java与native代码之间的映射,这些基本类型都是j开头,后面跟java中的实际类型,具体的基本类型及方法签名类型如下表所示:
在这里插入图片描述
方法签名的形式即为(参数签名)返回值类型签名。例如一个形如double func(int a, int b)的方法签名为(II)D
另外还有几个比较特殊的签名,如object签名为L{用/分割的完整类名}如Ljava/lang/String表示一个String对象。Array的签名为[{相应类型的签名},如[D,表示类型为D的数组,[Ljava/lang/String表示String对象的数组。
当然JNI也定义了很多引用类型的映射,其中jobject对应于java.lang.Object,以及其之类型:

jclass—java.lang.Class
jstring—java.lang.String
jthrowable—java.lang.Throwable

jarray与java中的Array对应,由于Array在java中支持8种基本数据类型,所以相应的有8种Array,分别为jintArray、jbyteArray、jshortArray、jlongArray、jfloatArray、jdoubleArray、jcharArray和jbooleanArray。以及一个对象类型的Array:jobjectArray。
查看jni.h头文件会发现里面都是使用typedef进行的定义:

// 头文件"jni.h"中的声明
typedef unsigned char   jboolean;
typedef unsigned short  jchar;
typedef short           jshort;
typedef float           jfloat;
typedef double          jdouble;
typedef jint            jsize;

struct _jobject;

typedef struct _jobject *jobject;
typedef jobject jclass;
typedef jobject jthrowable;
typedef jobject jstring;
typedef jobject jarray;
typedef jarray jbooleanArray;
typedef jarray jbyteArray;
typedef jarray jcharArray;
typedef jarray jshortArray;
typedef jarray jintArray;
typedef jarray jlongArray;
typedef jarray jfloatArray;
typedef jarray jdoubleArray;
typedef jarray jobjectArray;

//"linux/jni_mh.h"中的声明
typedef int jint;
#ifdef _LP64 /* 64-bit Solaris */
typedef long jlong;
#else
typedef long long jlong;
#endif

typedef signed char jbyte;

现在可以清楚的知道JNI在java代码和native代码之间做了类型转换,以使两种语言之间的数据类型可以互通。

基本类型参数传递
举一个例子说明,程序的功能为给java程序传递两个int做为参数,将该参数传递给native函数,native函数累加两个参数之间的数字,然后取平均后将结果返回给java程序并输出。
java代码

//TestJint.java
public class TestJint
{
   
    static {
   
        System.loadLibrary("myjint");  //载入本地的动态链接库
    }
    private native double avg(int a, int b);    //声明一个本地方法,接受2个int变量做为参数,返回其double类型的累加和的平均值
    public static void main(String args[]) {
   
        if 
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当通过JNI调用C++的DLL动态库时,可以使用出参的方式返回结果。下面是详细的步骤和代码示例: 1. C++代码: ```cpp // MyLibrary.h #ifdef MYLIBRARY_EXPORTS #define MYLIBRARY_API __declspec(dllexport) #else #define MYLIBRARY_API __declspec(dllimport) #endif extern "C" { MYLIBRARY_API void add(int a, int b, int* result); } ``` ```cpp // MyLibrary.cpp #include "MyLibrary.h" MYLIBRARY_API void add(int a, int b, int* result) { *result = a + b; } ``` 2. 使用C++编译器将上述代码编译成动态链接库(DLL)文件,例如命名为MyLibrary.dll。 3. Java代码: ```java // MyLibrary.java public class MyLibrary { static { System.loadLibrary("MyLibrary"); // 加载动态链接库 } // 声明native方法 public static native void add(int a, int b, int[] result); } ``` 4. 使用命令`javac MyLibrary.java`编译Java代码生成.class文件。 5. 将生成的.class文件与MyLibrary.dll放在同一个目录下。 6. 在Java代码调用C++的DLL动态库的接口函数,并通过出参方式返回结果: ```java public class Main { public static void main(String[] args) { int[] result = new int[1]; // 定义一个长度为1的数组用于接收结果 MyLibrary.add(3, 4, result); System.out.println("add result: " + result[0]); } } ``` 在Java代码,声明native方法时,将结果参数定义为一个数组。在调用C++的接口函数时,将结果参数传递C++函数,并在C++函数修改结果值。在Java代码,通过访问数组的方式获取返回的结果。 以上就是通过JNI调用C++的DLL动态库,并通过出参方式返回结果的详细实现步骤和代码。确保动态链接库文件与Java代码在同一个目录下,并设置好运行环境。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值