当前位置: 首页 > 面试题库 >

jni不支持void *,unsigned int *等类型,该怎么办?

夏经武
2023-03-14
问题内容

我有一个用C ++编写的 .so (共享库),我们称它为 function.so ,其中我实现了不同的功能,这是一些功能的列表:

1. unsigned long Initialize(void* userData);
2. unsigned long Uninitialize(void);
3. unsigned long DeviceOpen( unsigned long id, unsigned long* device);
4. unsigned long DeviceClose( unsigned long device );

等等 …

我想在我的Android Java应用程序中使用该库的( functional.so
)功能。为此,我在我的android应用程序项目文件夹中创建jni文件夹,并将文件放置在其中:

  1. Android.mk

    LOCAL_PATH := $(call my-dir)
    

    include $(CLEAR_VARS)
    LOCAL_MODULE := Test_library
    LOCAL_SRC_FILES := Test_library.c

    Linking functionality library

    LOCAL_LDLIBS := -lfunctionality
    include $(BUILD_SHARED_LIBRARY)

  2. Test_library.c

    #include <string.h>
    

    include “Test_library.h”

    jint Java_com_Dsm_Test_DsmLibraryTest_vtUninitialize(JNIEnv* env, jobject thiz) {
    return Uninitialize( );
    }

    jint Java_com_Dsm_Test_DsmLibraryTest_vtDeviceClose(JNIEnv* env, jobject thiz, jint hDevice) {
    return DeviceClose( hDevice );
    }

  3. Test_library.h

其中A头文件 初始化未初始化DeviceOpenDeviceClose 函数声明。

之后,我运行 ndk-build 并创建一个Test_library.so库,并将其加载到我的Java应用程序中,并像这样使用它们:

// Some code

public native int Uninitialize( );

public native int DeviceClose( int hDevice );

static {
    System.loadLibrary("Test_library");
}

一切运行正常。我要添加其他两个功能之后

1. unsigned long Initialize(void* userData);
2. unsigned long DeviceOpen( unsigned long id, unsigned long* device);

`

现在的问题:

  1. 我如何才能将这两个函数编写为Java本机?由于Java 中没有 void ** 或 **无符号long 类型
  2. 我如何在Test_library.c中编写与jni.h中相同的函数,没有 void 或 *unsigned long 类型

感谢帮助。


问题答案:

您可以jlong用来将指针(或指向该指针的指针,或其他)传递回Java。Java代码除了将它作为参数传递给其他方法之一之外,将不能用于任何其他用途。但是通常这就是您真正想要的。另一方面,如果要Initialize()使用Java设置的数据来调用它,则void *不合适;您将需要使用Java类,并在JNI中使用反射来从中获取所需的信息。

好听的,你可以包装malloc()free()

jlong Java_c_utils_malloc(JNIEnv* env, jclass clazz, jint size) {
    return (jlong) malloc(size);
}

void Java_c_utils_free(JNIEnv* env, jclass clazz, jlong ptr) {
   free((void *) ptr);
}

然后在Java中使用它们(无效!):

long ptr = utils.malloc(100);
// Store ptr for a while
utils.free(ptr);

现在,如果我们包装一些需要一块内存作为参数的其他函数,我们也可以包装它们,并让它们接受jlong参数,方法free()与之相同。Java变量ptr代表一个内存地址这一事实在Java中是完全不透明的,但是仍然很有用。

Java的窗口系统实现(即AWT,SWT)使用相同的方式将本机窗口小部件句柄与Java组件相关联。

现在,如果您希望Initialize()能够从Java中获取有用的参数,那么a void *并不会减少它。您需要编写方法以接受Java对象作为参数。这是允许您使用Java操作对象的唯一方法。

我不想在这里重复所有代码,但是Sun的JNI教程在这里。这是关于调用Java对象(this对象或作为参数传递给您的方法的任意方法)的部分,这与访问对象的字段类似。



 类似资料:
  • 问题内容: 为什么Java中的泛型只能用于类,而不能用于原始类型? 例如,这可以正常工作: 但这是不允许的: 问题答案: ava中的泛型是一个完全编译时的结构-编译器将所有泛型使用转换为正确的类型。这是为了保持与以前的JVM运行时的向后兼容性。 这个: 变成(大致): 因此,任何用作泛型的东西都必须可转换为Object(在此示例中返回),而原始类型则不是。因此它们不能用于泛型。

  • 为什么Java中的泛型可以处理类而不能处理基元类型? 例如,这个操作很好: 但这是不允许的:

  • 问题内容: 我正在为apache HttpClient包实现一个,如下所示: 但我希望函数不返回任何值,即。这可能吗?由于不是有效的Java类型,因此以下内容无法编译: 我想可以替换为以返回对象,但这并不是我真正想要的。 问 :是否有可能安排在这样一种方式,我可以返回此回调局面从? 问题答案: 泛型仅处理对象类。泛型不支持void和基本类型,您不能将它们用作参数化类型。您必须改用Void。 你能说

  • 我需要在JAX-WS中通过客户端连接到外部服务器。客户端在Wildfly 8上运行。使用Java8连接是正常的。但我在Java7中连接到服务器时遇到了问题(我尝试了u45、67、79)。服务器端安全性的属性为https://www.ssllabs.com/ssltest/analyze.html?d=app.bundesnetzagentur.de 在部分“密码套件”中有四个密码。源代码不应支持J

  • 下面是错误指定的错误示例。我应该如何修复它,为什么我得到一个错误?

  • 我正在使用一种称为点(x:双精度,y:双精度)的数据类型。我正在尝试使用_c1列和_c2作为Point()的输入,然后创建一个新的Point值列,如下所示 然后我调用函数: 但是,当我声明udf时,我得到了以下错误: 我已经正确导入了此数据类型,并且之前多次使用它。现在我尝试将其包含在我的udf的架构中,它无法识别它。包含标准Int,字符串,数组等以外的类型的方法是什么? 我在亚马逊EMR上使用火