使用SWIG处理C函数返回Java中结构数组的指针 [英] Use SWIG to Handle C Function Returning A Pointer to Array of Structure in Java

查看:219
本文介绍了使用SWIG处理C函数返回Java中结构数组的指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在试图找出需要哪些SWIG接口文件更改才能处理getFoo返回一个指向自定义结构数组的指针(sender_id_t)。没有任何特殊的SWIG接口代码,我只得到Java端的指针。如何将该指针转换为可循环或迭代的东西(在Java中),以便我可以获取每个sender_id_t id值?感谢任何建议。

I'm trying to figure out what SWIG Interface file change is needed in order to handle the getFoo returns a pointer that points to an array of a custom structure (sender_id_t). Without any special SWIG Interface code, I get just the pointer on the Java side. How can I turn that pointer into something I can loop or iterate over (in Java) so that I can get each sender_id_t id value? Appreciate any suggestions.

C结构:

typedef unsigned char id_v1_t[32];
typedef id_v1_t id_t;
%rename (Sample) sender_id_t_;
struct sender_id_t_ {
    id_t       id;
    uint32_t   phy_idx;
};

C功能:

//This will return a pointer to an array of sender_id_t data.  The number of elements is retrieved from a separate call. 
sender_id_t* getFoo(resultset_t* resultset);

例外:

 [exec] test_wrap.c: In function `new_foo_array':
 [exec] test_wrap.c:785: error: invalid application of `sizeof' to incomplete type `sender_id_t_' 
 [exec] test_wrap.c: At top level:
 [exec] test_wrap.c:792: error: return type is an incomplete type
 [exec] test_wrap.c: In function `foo_array_getitem':
 [exec] test_wrap.c:793: error: invalid use of undefined type `struct sender_id_t_'
 [exec] test_wrap.c:793: error: dereferencing pointer to incomplete type
 [exec] test_wrap.c:793: warning: `return' with a value, in function returning void
 [exec] test_wrap.c: At top level:
 [exec] test_wrap.c:795: error: parameter `value' has incomplete type
 [exec] test_wrap.c: In function `foo_array_setitem':


推荐答案

对此最简单的解决方案根本不涉及编写任何JNI - 实际上它是方法2 。所以我所做的就是使用carrays.i 公开一个非常基本的界面然后编写一小部分Java来使 public 视图更加可用/直观。关键是你需要提供一种方法,将数组的知识集中在一起。我把一个最小的完整示例放在一起来说明,它返回一个Java数组,但它同样适用于 ArrayList 或任何你喜欢的集合。

The simplest solution to this doesn't involve writing any JNI at all - in effect it's method 2. So what I did was use carrays.i to expose a very basic interface and then written a small bit of Java to make the public view of it more usable/intuitive. The key thing is you need to supply a way of bringing together the knowledge of the array and the length of it. I've put together a minimal complete example to illustrate, it returns a Java array, but it could equally work for an ArrayList or any collection you like.

首先是一个头文件,带有紧凑的内联实现:

Firstly a header file, with an inline implementation for compactness:

#ifndef TEST_H
#define TEST_H

struct Foo {
   int v;
};

inline static struct Foo *getFoo() {
  static struct Foo r[] = {{0},{1},{2}};
  return r;
}

inline static unsigned short numFoo() {
  return 3;
}

#endif

然后将其包装为:

%module test

%{
#include "test.h"
%}

%include <carrays.i>
%array_functions(struct Foo, foo_array);

%rename(getFooImpl) getFoo;
%javamethodmodifiers getFoo() "private";
%javamethodmodifiers numFoo() "private";
%include "test.h"

%pragma(java) modulecode=%{
  public static Foo[] getFoo() {
    final int num = numFoo();
    Foo ret[] = new Foo[num];
    Foo result = getFooImpl();
    for (int i = 0; i < num; ++i) {
      ret[i] = foo_array_getitem(result, i);
    }
    return ret;
  }  
%}

我们在哪里重命名头文件中的getFoo()并使其与相应的 numFoo() private ,即实现细节。

Where we make rename the getFoo() from the header file and make it and the corresponding numFoo() private, i.e. implementation details.

使用这两个私有函数,我们可以编写一个真实的, public Foo [] getFoo(),调用这两个,然后将结果复制到已知大小的实际数组中。

Using these two private functions we can then write a real, public Foo[] getFoo(), that calls these two and then copies the results into an actual array of known size.

我测试了这个:

public class main {
  public static void main(String[] argv) {
    System.loadLibrary("test");
    Foo[] foos = test.getFoo();
    System.out.println(foos[2].getV());
  }
}

在我看来,这个解决方案比相应的JNI更干净基于示例 - 编写更简单,更难以引入错误,使其更易于维护。任何查看它的Java C程序员都可以看到正在发生的事情。在性能方面可能并没有太差,在一些关键路径上可能不会是一大块时间 - 如果基准测试显示它是一个问题,那么以后它仍然很容易走下JNI之路。

In my view this solution is cleaner than the corresponding JNI based example - it's simpler to write and harder to introduce bugs which makes it more maintainable. Any Java or C programmer that looks at it can pretty much see what's going on. It's probably not much worse in terms of performance and probably not going to be a big chunk of time on some critical path - if benchmarks show it to be a problem then it's still easy to go down the JNI road later.

为了完成使其私人这一方面,您可能还需要执行以下操作:

For completeness on the "making it private" aspect you might also want to do something like:

%javamethodmodifiers foo_array_getitem "private";
%ignore foo_array_setitem;
%ignore delete_foo_array;
%ignore new_foo_array;
%include <carrays.i>
%array_functions(struct Foo, foo_array);

隐藏由%array_functions生成的所有函数宏。

这篇关于使用SWIG处理C函数返回Java中结构数组的指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆