jni不支持类型为void *,unsigned int *,....该怎么办? [英] jni not support types as void*, unsigned int*, .... What to do?

查看:1239
本文介绍了jni不支持类型为void *,unsigned int *,....该怎么办?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有使用C ++编写的 .so (共享库),可以将其称为 functions.so ,其中我实现了不同的功能,这里列出了一些功能: / p>

I have .so (shared library) written in C++, lets call it functionality.so in which I implement different functions, here is list of some functions:

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 );

等等...

我想在我的java应用程序中使用这个库( functions.so )功能。为此,我在我的Android应用程序项目文件夹中创建jni文件夹,并放置文件:

I want to use this library's (functionality.so) functionality in my java application for android. For that I create jni folder in my android application project folder and place there files:


  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)


  • Test_library.c

    #include <string.h>
    #include <jni.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 );
    }
    


  • Test_library.h

    头文件,其中初始化未初始化 DeviceOpen DeviceClose 函数被声明。

    A header file where Initialize, Uninitialize, DeviceOpen, DeviceClose functions are declared.

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

    After this I run ndk-build and create a Test_library.so library and load it in my java application and use them like this:

    // Some code
    
    public native int Uninitialize( );
    
    public native int DeviceClose( int hDevice );
    
    static {
        System.loadLibrary("Test_library");
    }
    

    一切运行良好。之后我想添加其他两个功能

    Everything Runs fine. After I want to add other two functions

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

    `


    1. 如何在java中将这两个函数写成native?因为java中没有 void * unsigned long * 类型

    2. 如何在Test_library.c中编写相同的函数,如jni.h没有 void **或 unsigned long * 类型

    1. How I can write this two functions as native in java ? As there are no void* or unsigned long* types in java
    2. How I can write same functions in Test_library.c as in jni.h there are no void** or unsigned long* types



    Thanks for help.

    推荐答案

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

    You can use jlong to pass a pointer (or a pointer to pointer, or whatever) back to Java. Java code won't be able to use it for anything, other than passing it as an argument to one of your other methods; but often that's all you really want. If, on the other hand, you want Initialize() to be called with data set up in Java, then void * isn't appropriate; you'll need to use a Java class, and use reflection in JNI to get the information you need out of it.

    原来,您可以将 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中使用它们(无效!):

    and then use them (to no effect!) in Java:

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

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

    Now, if we wrapped some other functions that needed a block of memory as an argument, we could wrap them too, and let them accept a jlong argument, the same way free() does. The fact that the Java variable ptr represents a memory address is completely opaque in Java, but it's useful nonetheless.

    Java(i,e。,AWT,SWT)的窗口系统实现使用同样的事情将本机窗口句柄与Java组件相关联。

    Window system implementations for Java (i,e., AWT, SWT) use this same sort of thing to associate the native widget handle with the Java component.

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

    Now, if you want your Initialize() to be able to take useful arguments from Java, then a void * isn't going to cut it. You'd need to write your method to accept a Java object as an argument; that's the only way to allow you to manipulate the object in Java.

    我不想在此复制所有代码,但Sun的JNI教程是here 是关于调用Java对象的任意方法的部分( code>这个对象,或者作为参数传递给你的方法)和这个是访问对象的字段的类似部分。

    I don't want to duplicate all the code here, but Sun's JNI tutorial is here. This is the section on calling arbitrary methods of a Java object (either the this object, or one passed to your method as an argument) and this is an analogous section on accessing the fields of an object.

    这篇关于jni不支持类型为void *,unsigned int *,....该怎么办?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆