SWIG,我可以为从Java传递给C的char **赋值

时间:2013-10-25 14:11:57

标签: java c swig

我有一个看起来像这样的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对象。

2 个答案:

答案 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分配。