修改SWIG接口文件,以支持C无效*和结构的返回类型(Modifying SWIG Interfac

2019-10-30 01:41发布

我使用痛饮,产生了很大的集合C的API我JNI层,我想知道什么是以下情况下的最佳实践。 下面不仅涉及痛饮,但JNI一般。

当C函数返回指针结构,应在SWIG接口文件(JNI逻辑)被频繁使用的或应该被创建C包装功能来在块(即,包含各种数据元素字符数组)返回数据? 当C函数返回void *应在C的API进行修改,以返回实际的数据类型,无论是原始或结构类型? 我不确定我是否要添加逻辑的大规模量,并创建一个中间层(痛饮接口文件/ JNI逻辑)。 思考?

Answer 1:

我对这种做法在过去一直写尽可能少的代码,尽可能使其工作。 当我有写代码,使其工作我把它写在优先顺序如下:

  1. 写在原有的库C或C ++ -每个人都可以使用此代码,您不必写什么Java或痛饮特定的(如添加在C ++更过载,在C添加更多版本的功能,即SWIG知道使用的返回类型关于它们)

  2. 写更多目标语言的 -供应“胶水”,使图书馆的一些位在一起。 在这种情况下,这将是Java的。

    这并不重要,如果这是“纯粹”的Java,痛饮之外完全,或者从我的角度来看,痛饮接口文件的一部分。 Java界面的用户不应该能够区分这两种。 您可以使用痛饮,以帮助避免在一些案件中,虽然重复。

  3. 通过写痛饮typemaps一些JNI。 这是丑陋的,容易出错,如果你不熟悉,写它,难以维持(可以说),只有有用痛饮+ Java的。 使用痛饮typemaps并至少意味着你只写一次为每个类型你包。

    本次我赞成这种过2是一种或多种:

    1. 当谈到了很多(可以节省重复的编码)
    2. 我不知道目标语言可言,在这种情况下使用该语言的C API可能比该语言写的东西更容易
    3. 用户将希望这种
    4. 或者,它只是无法使用以前的样式。

基本上,这些指导原则,我建议试图同时最小化您必须编写额外的,目标语言特定的代码量,降低了它的复杂性时,你必须把它写图书馆尽可能多的用户所提供的功能。


对于一个特定的情况下, sockaddr_in*

方法1

我会尝试做的第一件事就是避免包装什么比一个指针,它更多。 这是什么痛饮的默认操作与SWIGTYPE_p_sockaddr_in事情。 如果你做的是一件事情把它传递到另一个店容器可以在Java中使用这种“未知”类型相当愉快/作为成员等,如

public static void main(String[] argv) {
  Module.takes_a_sockaddr(Module.returns_a_sockaddr());
}

如果不这样做的工作,你可以不喜欢写另一个函数,在C:

const char * sockaddr2host(struct sockaddr_in *in); // Some code to get the host as a string
unsigned short sockaddr2port(struct sockaddr_in *in); // Some code to get the port

这是不是很大在这种情况下,虽然-你有一些复杂与我猜你宁愿避免(这就是为什么你正在使用的地址族来处理有sockaddr_in摆在首位),但它不是Java具体的,它不是晦涩的语法,这一切为你自动发生除此之外。

方法2

如果仍然不够好,然后我会开始考虑编写Java的一点-你可以通过隐藏暴露出更好的接口SWIGTYPE_p_sockaddr_in类型作为自己的Java类型的私有成员,和包装的调用函数,它返回它在某些Java中构造你的类型适合你,如

public class MyExtension {
  private MyExtension() { }
  private SWIGTYPE_p_sockaddr_in detail;
  public static MyExtension native_call() {
    MyExtension e = new MyExtension();
    e.detail = Module.real_native_call();
    return e;
  }

  public void some_call_that_takes_a_sockaddr() {
    Module.real_call(detail);
  }
}

没有多余的SWIG来写,没有JNI来写。 你可以使用通过痛饮做到这一点%pragma(modulecode)使其实际模块SWIG所有重载生成-这感觉更自然的Java用户可能(它看起来并不像一个特例),是不是真的任何更复杂。 居功甚伟正在痛饮做的是,这只是提供了一些润色,避免在Java端重复编码。

方法3

这主要是第二部分我以前的答案 。 这是很好的,因为它的外观和感觉,原产于Java的用户和C库不必进行任何修改。 从本质上讲类型映射提供了一个干净上下的语法封装JNI调用从什么Java的用户期望什么C可与转换任何一方都不知道对方的前景。

不足之处是,它虽然是难以维持,真让人难以调试。 我的经验是,呷有这样的事情一个陡峭的学习曲线,但一旦你达到一个地步,它不会耗费太多精力写这样typemaps他们给你通过C的重复使用和封装的功率类型 - > Java类型映射是非常有用和强大。

如果你是一个团队的一部分,但谁真正明白SWIG接口的唯一的人那么把一个大大的“如果你是不是被车撞了?” 因素对项目的全过程。 (让你们unfirable虽然可能相当不错!)



文章来源: Modifying SWIG Interface file to Support C void* and structure return types