0

我有一个如下所示的 C API:

int my_function(char** assign_me_a_string);

我基本上需要本机代码来告诉我一个值。如果我做:

char* my_function();

它工作正常。我得到一个可以在 Java 中使用的字符串作为回报。但是我更喜欢使用第一种方法,因为我的所有函数默认返回一个 int (状态值)。

我曾尝试使用各种.i 和这个类型图:

%apply char **STRING_ARRAY { char **assign_me_a_string }

这样做我得到一个为 Java API 生成的 String[]。然后我尝试通过以下方式使用它:

String[] myStringToAssign = new String[1];
my_function(myStringToAssign);

但这似乎只是崩溃。

那么,有没有一种正确的方法可以从 C 代码内部为 Java 字符串赋值?我不想使用数组,我只需要能够取消引用 char** 并在本机代码中为其分配一个字符串,然后可以将其用作 Java 中的 String 对象。

4

2 回答 2

3

Java String 是不可变的,并且引用是按值传递的,因此以下内容不会按照您的想法进行(纯 Java):

// java: 
void someFunction(String yourString) {yourString = "bye";}
void test() {
    String test = "hi";
    someFunction(test);
    System.out.println(test); // prints "hi", not "bye"!
}

(有关这方面的更多信息,请参见在 Java 中通过引用传递字符串?)。不用说你也不能使用 JNI 来做到这一点。

查看 SWIG 2.0 文档的第 24.10.5 节:它展示了如何通过类型映射为 char** 执行此操作。但是,必须修改那里的类型映射以在退出时检查 char* 数组(可能是 freearg 类型映射)以替换 String[] 的内容。您的功能只能假设一项。

或者,您可以将 Java String 包装在一个类中,该类将通过引用传递;但是,您必须再次使用类型映射来复制对数据成员所做的任何更改。

可能最简单的方法是提供一个交换状态码和字符串的辅助函数:

// C/C++ lib: the function you'd like to export but can't:
int my_function(char*& ) { 
    val = new char[20];
    ...put stuff in val, don't forget the terminating \0 char...
    return status;
}

创建包装器:

// SWIG .i file: an "adapter" function, Java gives you no choice: 
%inline %{
char* my_function(int& err) {
    char * val;
    err = my_function(val);
    return val;
%}

SWIG 将负责将 char* 复制到返回的字符串:

// From Java you can then do: 
int status;
String result = my_function(status);
System.out.println(result);
于 2013-10-25T22:20:51.087 回答
1

不,Java 字符串是不可变的,即使通过 JNI 也无法分配。

于 2013-10-25T14:13:58.430 回答