当前位置: 首页 > 面试题库 >

使用SWIG处理C函数,将指针返回Java中的结构数组

厍华清
2023-03-14
问题内容

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

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您喜欢的一个或任何集合

首先是头文件,其内联实现紧凑性:

#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,即实现细节。

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

我用以下方法对此进行了测试

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仍然很容易。

为了“制作private”方面的完整性,您可能还需要执行以下操作:

%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宏生成的函数。



 类似资料:
  • 我有一些C语言的代码,其中一个方法有一个函数指针作为参数。我正在尝试在我的Android应用程序中使用C代码。 我决定使用SWIG来完成生成所需java文件的所有工作。常规函数(没有函数指针作为参数的函数)一切都很好。 但是我不确定如何将我的JAVA方法作为回调传递给C函数。 下面是一个例子: 这是我的密码。h文件 这是我的密码。c文件 这是我的接口文件multiply-swigi 然后我运行以下

  • 问题内容: 我正在尝试为C库编写SWIG包装器,该包装器使用指向其结构中函数的指针。我不知道如何处理包含函数指针的结构。下面是一个简化的示例。 test.i: 样本会议: 有人知道是否有可能让 t.my_func(1) 返回2吗? 谢谢! 问题答案: 我找到了答案。如果我将函数指针声明为SWIG“成员函数”,则它似乎可以按预期工作: 会议: 我希望不需要编写任何特定于SWIG的自定义代码(我希望仅

  • C++ 指针 在上一章中,我们已经了解了 C++ 中如何从函数返回数组,类似地,C++ 允许您从函数返回指针。为了做到这点,您必须声明一个返回指针的函数,如下所示: int * myFunction() { . . . } 另外,C++ 不支持在函数外返回局部变量的地址,除非定义局部变量为 static 变量。 现在,让我们来看下面的函数,它会生成 10 个随机数,并使用表示指针的数组名(即第

  • 我已经创建了swig接口文件来为我的C文件创建JNI。但是我的一些C文件包含一些函数,这些函数接受指针作为参数,比如(void*),C BOOL和Swig将其转换为SWIGTYPE_p_int32_t如何从java传递这种数据类型? 例如,函数的一个实际原型在C中如下所示 它通过swig转换成Java文件 如何从java传递这样的值? 我有许多类在函数中包含此类参数。有什么方法可以让我尽可能简单地

  • 我在玩C语言中的函数指针只是为了学习。我尝试调用一个空函数,并将其结果设置为int。 我从中得到的结果是: 在对它进行了一点研究之后,我意识到main正在函数()中打印printf语句中的字符数。为什么会这样?这是预期产出吗?

  • 这已经超出我的想象了,我们开始吧。 我正在用C语言设置一个函数指针,该指针带有一个Java接口对象,看起来像Java端的接口对象: 其中,是只有一种方法的接口: 而指的是Java本机方法,它在C端反映如下: 所有这些都是基于JNI中使用接口实现回调函数编写的 我已经尝试在C端调用Java中定义的方法,它可以工作(就像上面的链接一样),但是现在我正在尝试在C下设置这样的上的值 因此,稍后我想把作为一