【问题标题】:How to return data in a Java String from a call to a C function via JNI in Android NDK如何在Android NDK中通过JNI调用C函数返回Java字符串中的数据
【发布时间】:2014-07-24 14:22:35
【问题描述】:

我需要使用 Android NDK 调用 C 函数,并且必须通过作为 char* 参数传递给 C 函数的 Java 字符串返回更改后的值。问题是 Java 字符串是按值传递的,因此我的 C 函数对字符串所做的更改不会到达调用 Java 函数。

我的 Java 源代码如下,我从 arg1_j 和 result_j 中的值得到合理的输出,但如上所述,我的 C 函数没有更新 arg3_j:

import Cptr.Cptr;
...
String arg1_j = new String(new byte[65]);
long arg2_j = 1000;
String arg3_j = new String(new byte[65]);

arg1_j = "1234567890123456789012345678901234567890123456789012345678901234";

Integer result_j = Cptr.test_cptr(arg1_j, arg2_j, arg3_j);

final EditText eText = (EditText) findViewById(R.id.editText1);

eText.setText(arg1_j);
//eText.setText(result_j.toString());
//eText.setText(arg3_j);
...

我的C头文件,cptr.h如下:

#ifndef CPTR_H_
#define CPTR_H_

#include <stdint.h>
#include <stdbool.h>

int32_t test_cptr(char *, uint32_t, char *);

#endif // ndef CPTR_H_

我的C源文件cptr.c如下:

#include "cptr.h"

// The function sets arg3 data and returns arg2 - 1
int32_t test_cptr(char* arg1, uint32_t arg2, char* arg3)
{
    arg3[0] = 'h';
    arg3[1] = 'e';
    arg3[1] = 'l';
    arg3[3] = 'l';
    arg3[4] = 'o';
    arg3[5] = '\0';

    return arg2 - 1;
}

我的 Cptr.i 文件是:

/* File : Cptr.i */
%module Cptr
%{
/* Includes the header in the wrapper code */
#include "cptr.h"
%}

%include "stdint.i"

// Enable the JNI class to load the required native library.
%pragma(java) jniclasscode=%{
static {
try {
java.lang.System.loadLibrary("Cptr"); 
} catch (UnsatisfiedLinkError e) {
java.lang.System.err.println("native code library failed to load.\n" + e);
java.lang.System.exit(1); 
} 
}
%}
/* Parse the header file to generate wrappers */
%include "cptr.h"

我尝试在 SWIG 示例代码 (...Examples/Java/typemap/example.i) 中使用 typemap 示例,如下所示,但没有成功。同一来源中的以下示例对我也不起作用,在这两种情况下 arg3 都是作为字符串传递的,并且没有由我的 C 函数更新:

/* default behaviour is that of input arg, Java cannot return a value in a 
  * string argument, so any changes made by f1(char*) will not be seen in the Java
  * string passed to the f1 function. 
 */
void f1(char *s);

%include various.i

/* use the BYTE argout typemap to get around this. Changes in the string by 
 * f2 can be seen in Java. */
 void f2(char *BYTE);

我也从这个论坛上的各种帖子中尝试过 carrays.i,但我是 Java 新手,Android 没有任何工作。你的回复越明确,我的 POV 就越好。

非常感谢,

【问题讨论】:

  • 这在几个层面上是错误的。请参阅 ndk 发行版中的 hello-jni 示例,该示例演示了从 C 向 Java 返回字符串。

标签: java c android-ndk java-native-interface swig


【解决方案1】:

也许你可以让 c 方法返回修改后的参数,然后在 Java 中以这种形式调用它:

value = function(value);

【讨论】:

    【解决方案2】:

    好吧,我错了!非常抱歉,SWIG 附带的 ..Examples/Java/typemap/example.i 中的第一个方法确实对我有用。我不知道我之前做错了什么,但是与上面相同的 cptr.c 和 cptr.h 文件现在可以通过以下更改正常工作:

    Java 源代码:

    import Cptr.Cptr;
    ...
    byte[] arg1_j = "1234567890123456789012345678901234567890123456789012345678901234\0".getBytes();
    
    int arg2_j = 1000;
    
    byte[] arg3_j = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\0".getBytes();
    
    Integer result = Cptr.test_cptr(arg1_j, arg2_j, arg3_j);
    
    // convert byte array to hex string using no external libraries
    StringBuffer sb = new StringBuffer();
    for (byte b : arg3_j) { sb.append(Integer.toHexString( (int) (b & 0xff) )); }
    
    final EditText eText = (EditText) findViewById(R.id.editText1);
    
    eText.setText(sb.toString());
    

    我的新 Cptr.i 文件是:

    /* File : Cptr.i */
    %module Cptr
    %{
    /* Includes the header in the wrapper code */
    #include "cptr.h"
    %}
    
    %include "stdint.i"
    %include various.i
    
    // Enable the JNI class to load the required native library.
    %pragma(java) jniclasscode=%{
    static {
    try {
    java.lang.System.loadLibrary("Cptr");
    } catch (UnsatisfiedLinkError e) {
    java.lang.System.err.println("native code library failed to load.\n" + e);
    java.lang.System.exit(1);
    }
    }
    %}
    int32_t test_cptr(char* BYTE, uint32_t, char *BYTE);
    

    希望这对其他人有所帮助

    感谢您的关注,

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-28
      • 2013-05-13
      • 1970-01-01
      • 1970-01-01
      • 2023-03-14
      • 1970-01-01
      相关资源
      最近更新 更多