我有一个看起来像这样的C API:
int my_function(char** assign_me_a_string);
我基本上需要本机代码来告诉我一个值。如果我这样做:
char* my_function();
工作正常。我得到一个String,作为回报我可以在Java中使用。但是我更喜欢使用第一种方法,因为我的所有函数默认返回一个int(状态值)。
我试过使用various.i和这个typemap:
%apply char **STRING_ARRAY { char **assign_me_a_string }
这样做我得到了为Java API生成的String []。然后我尝试使用它:
String[] myStringToAssign = new String[1];
my_function(myStringToAssign);
但这似乎只是崩溃。
那么,是否有一种从C代码内部为Java String赋值的正确方法?我不是试图使用数组,我只需要能够取消引用char **并在本机代码中为其分配一个字符串,然后可以在Java中用作String对象。
答案 0 :(得分: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"!
}
(有关详情,请参阅示例Passing a String by Reference in Java?)。不用说,你也不能使用JNI。
请参阅SWIG 2.0文档的第24.10.5节:它显示了如何通过类型映射为char **执行此操作。但是,必须修改类型映射以在退出时检查char *数组(可能是freearg typemap)以替换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 *复制到返回的String:
// From Java you can then do:
int status;
String result = my_function(status);
System.out.println(result);
答案 1 :(得分:1)
不,Java字符串是不可变的,甚至不能通过JNI分配。