【问题标题】:SWIG, can I assign a value to a char** passed from Java to CSWIG,我可以为从 Java 传递到 C 的 char** 赋值吗
【发布时间】:2013-11-04 17:01:05
【问题描述】:

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

int my_function(char** assign_me_a_string);

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

char* my_function();

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

我尝试过使用各种.i 和这个 typemap:

%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 对象。

【问题讨论】:

    标签: java c swig


    【解决方案1】:

    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 类型映射)以替换 String[] 的内容。您的功能只能假设一项。

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

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

    // 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);
    

    【讨论】:

    • 感谢您抽出宝贵时间提出替代解决方案。
    • 第一个例子不正确。 yourString = "bye" 可以正常工作,因为它不会改变字符串 - 它会将 yourString 引用更改为指向不同的字符串(在本例中为 "bye")。
    • @pburka 我可能不清楚,但你解释的正是问题所在:调用会成功,但结果不会是 user1816142 所期望的(在调用 yourFunction(yourString) 之后,yourString 不会是“再见”,而不是打电话之前的任何事情)。
    • @Schollii 我很抱歉。我将“不起作用”误解为它会崩溃或无法编译。仔细阅读后,我明白你的意思了。
    • @pburka 没问题,我不清楚,我编辑了帖子的那一部分以(希望)澄清
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2020-01-31
      • 2013-04-25
      • 2020-12-31
      • 2021-03-09
      • 1970-01-01
      • 2011-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多