java - 将数据从 JNI 函数返回到 Android 应用程序代码

标签 java android c android-ndk

我正在开发一个 Android 应用程序,我正在为其使用一个原生 C 库。该库用于文件解压。

native方法的定义如下:

public static native Long decompress(ByteBuffer src, ByteBuffer dst);

我使用此功能的应用程序代码如下:

try {
            File inFile = new File(Environment.getExternalStorageDirectory().getPath() +"/1"); // source file

            ByteBuffer buf = ByteBuffer.allocateDirect((int)inFile.length());

            ByteBuffer buf_out = ByteBuffer.allocateDirect((int)inFile.length()*20);

            InputStream is = new FileInputStream(inFile);

            int b;

            while ((b=is.read())!=-1) {
                buf.put((byte)b);
            }
            Log.d("nims","source buffer zie"+buf.position());
            File file = new File(Environment.getExternalStorageDirectory().getPath() +"/2");

            // append or overwrite the file
            boolean append = false;

            FileChannel channel = new FileOutputStream(file, append).getChannel();

            Long t = decompress(buf,buf_out); // t is some XYZ number

            Log.d("nims","dest buffer zie"+buf_out.position()); // buf_out.position() returns 0
            buf_out.flip();

            // Writes a sequence of bytes to this channel from the given buffer.
            channel.write(buf_out);

            // close the channel
            channel.close();

        }
        catch (IOException e) {
            System.out.println("I/O Error: " + e.getMessage());
        }

JNI代码:

JNIEXPORT jlong JNICALL 

    Java_com_company_appName_MainActivity_decompress(JNIEnv* env, jclass cls, jobject src, jobject dst) {

        uint8_t* src_buffer = (*env)->GetDirectBufferAddress(env,src);
        const size_t src_size = (*env)->GetDirectBufferCapacity(env, src);

        uint8_t* dst_buffer = (*env)->GetDirectBufferAddress(env,dst);

        size_t dst_size = (*env)->GetDirectBufferCapacity(env, dst);
        jlong test = _decode_buffer(dst_buffer, dst_size, src_buffer, src_size, NULL);

        return test;
    }

目标缓冲区不包含任何数据。

我有以下问题:

  1. 如何将目标字节缓冲区从 JNI 代码读回应用程序代码?
  2. 如何将目标字节缓冲区数据写入文件?

如果您对此主题有任何建议和想法,我将不胜感激。

编辑 1:

size_t test = lzfse_decode_buffer(dst_buffer, dst_size, src_buffer, src_size, NULL);

    ALOG("Size of test %d.",test); // output is 319488
    ALOG("Size of test after casting  %ld.",(jlong)test); // output is -125648933


    //New code from stack overflow
    jclass cls2 = (*env)->GetObjectClass(env, dst);
    jmethodID limitId = (*env)->GetMethodID(env, cls2, "limit", "(I)Ljava/nio/Buffer;");
    (*env)->CallObjectMethod(env, dst, limitId,(jlong) test);
    jmethodID positionId = (*env)->GetMethodID(env, cls2, "position", "(I)Ljava/nio/Buffer;");
    (*env)->CallObjectMethod(env, dst, positionId, 0);

编辑 2:

size_t test = lzfse_decode_buffer(dst_buffer, dst_size, src_buffer, src_size, NULL);
     ALOG("Size of test %d.",test); // output is 319488
    ALOG("Size of test after casting  %d.",(jint)test); // output is 319488
    //New code from stack overflow
    jclass cls2 = (*env)->GetObjectClass(env, dst);
    jmethodID limitId = (*env)->GetMethodID(env, cls2, "limit", "(I)Ljava/nio/Buffer;");
    (*env)->CallObjectMethod(env, dst, limitId,(jint) test);
    jmethodID positionId = (*env)->GetMethodID(env, cls2, "position", "(I)Ljava/nio/Buffer;");
    (*env)->CallObjectMethod(env, dst, positionId, 0);

最佳答案

当您在 C 中写入 DirectByteBuffer 时,这不会更改大小 (limit) 和 position dst 缓冲区。你必须自己设置这些。您可以使用 native 代码执行此操作:

jclass cls = (*env)->GetObjectClass(env, dst);
jmethodID limitId = (*env)->GetMethodID(env, cls, "limit", "(I)Ljava/nio/Buffer;");
(*env)->CallObjectMethod(env, dst, limitId, actual_size);
jmethodID positionId = (*env)->GetMethodID(env, cls, "position", "(I)Ljava/nio/Buffer;");
(*env)->CallObjectMethod(env, dst, positionId, 0);

这假定您可以从 _decode_buffer() 函数检索写入 dst 缓冲区的实际字节数。

而且您不需要flip()

关于java - 将数据从 JNI 函数返回到 Android 应用程序代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48096494/

相关文章:

java - 方法完成后将进度条重置为零 java swing

java - 资源 ID 和设备

C潜在的内存泄漏malloc

c - 全局变量的乘法声明/定义

java - mongodb根据父文档的搜索结果选择子文档

java - 关于如何优化这段代码有什么想法吗?我似乎想不出任何有效的办法

java - 使用 <a href> 将值从 jsp 传递到 servlet

java - 如何根据整数值执行代码

Android避免缓存

c++ - 将某些字符和结构写入文件并读回时,fread 和 fwrite 出现问题