【问题标题】:How to use SWIG Generated C structures in Java as input to C functions via SWIG/JNI如何通过 SWIG/JNI 在 Java 中使用 SWIG 生成的 C 结构作为 C 函数的输入
【发布时间】:2011-11-22 23:19:30
【问题描述】:

我有一个 SWIG 接口文件,它向我的 Java 应用程序公开一些 C 函数(通过 JNI),这些 C 结构用作 C 函数的输入(通过 SWIG/JNI)。 SWIG 将结构生成为 Java 类,但我不确定如何设置结构属性,因为设置器采用 SWIG 生成的类型。我需要先设置结构属性,然后再将其作为输入从我的 Java 类传递给 C 函数。 example_location_id_t_ 是我需要通过的类,但 IdPhy_idx 的设置器采用以下 SWIG 类型。如何填充SWIGTYPE_p_unsigned_charSWIGTYPE_p_uint32_t 以便我可以设置SWIGTYPE_p_uint32_t 类的IdPhy_idx 属性?

setId(SWIGTYPE_p_unsigned_char value)setPhy_idx(SWIGTYPE_p_uint32_t value)

package com.test.jni;

public class SWIGTYPE_p_unsigned_char {
  private long swigCPtr;

  protected SWIGTYPE_p_unsigned_char(long cPtr, boolean futureUse) {
    swigCPtr = cPtr;
  }

  protected SWIGTYPE_p_unsigned_char() {
    swigCPtr = 0;
  }

  protected static long getCPtr(SWIGTYPE_p_unsigned_char obj) {
    return (obj == null) ? 0 : obj.swigCPtr;
  }
}


package com.test.jni;

public class SWIGTYPE_p_uint32_t {
  private long swigCPtr;

  protected SWIGTYPE_p_uint32_t(long cPtr, boolean futureUse) {
    swigCPtr = cPtr;
  }

  protected SWIGTYPE_p_uint32_t() {
    swigCPtr = 0;
  }

  protected static long getCPtr(SWIGTYPE_p_uint32_t obj) {
    return (obj == null) ? 0 : obj.swigCPtr;
  }
}

package com.test.jni;

public class example_location_id_t_ {
  private long swigCPtr;
  protected boolean swigCMemOwn;

  public example_location_id_t_ (long cPtr, boolean cMemoryOwn) {
    swigCMemOwn = cMemoryOwn;
    swigCPtr = cPtr;
  }

  public static long getCPtr(example_location_id_t_ obj) {
    return (obj == null) ? 0 : obj.swigCPtr;
  }

  protected void finalize() {
    delete();
  }

  public synchronized void delete() {
    if (swigCPtr != 0) {
      if (swigCMemOwn) {
        swigCMemOwn = false;
        ExampleJNI.delete_example_location_id_t_(swigCPtr);
      }
      swigCPtr = 0;
    }
  }

  public void setId(SWIGTYPE_p_unsigned_char value) {
      ExampleJNI.example_location_id_t__id_set(swigCPtr, this, SWIGTYPE_p_unsigned_char.getCPtr(value));
  }

  public SWIGTYPE_p_unsigned_char getId() {
    long cPtr = ExampleJNI.example_location_id_t__id_get(swigCPtr, this);
    return (cPtr == 0) ? null : new SWIGTYPE_p_unsigned_char(cPtr, false);
  }

  public void setPhy_idx(SWIGTYPE_p_uint32_t value) {
    ExampleJNI.example_location_id_t__phy_idx_set(swigCPtr, this, SWIGTYPE_p_uint32_t.getCPtr(value));
  }

  public SWIGTYPE_p_uint32_t getPhy_idx() {
    return new SWIGTYPE_p_uint32_t(ExampleJNI.example_location_id_t__phy_idx_get(swigCPtr, this), true);
  }

  public example_location_id_t_() {
    this(ExampleJNI.new_example_location_id_t_(), true);
  }

}

【问题讨论】:

    标签: java java-native-interface swig


    【解决方案1】:

    在没有提供任何额外信息的情况下,SWIG 默认假设您希望将事物包装为一种可以返回并从一个函数传递到另一个函数的类型,即使它不能用目标语言进行有意义的包装。

    每次您看到以 SWIGTYPE_... 开头的类型时,都意味着 SWIG 不知道如何生成更好的包装器,而这是它设法想出的最好的包装器。

    SWIG 确实提供了默认类型映射,但可以在这里为您提供帮助:

    • 对于setPhy_idx(uint32_t value);,您只需在界面中添加:

      %include "stdint.i"
      
      void setPhy_idx(uint32_t value);
      

      并且可以表示uint32_t 的类型将在目标语言中使用。

    • 对于setId(unsigned char *value);,这完全取决于value 实际上是什么——如果它是一个NULL 终止的字符串,您可以执行以下操作:

      %apply char * { unsigned char * };
      
      void setId(unsigned char *value);
      

      String 将用于您的目标语言。

      如果你想将指针作为整数类型传递,你可以使用类似的东西:

      %apply unsigned long { unsigned char * };
      
      void setId(unsigned char *value);
      

      改为。

      如果unsigned char *value 是指向单个unsigned char 的指针,您可以这样做:

      %include "typemaps.i"
      %apply unsigned char *INPUT { unsigned char *value };
      
      void setId(unsigned char *value);
      

      指示 SWIG 将指针视为单个指针。 (如果uint32_t也是一个指针,这也可以应用)

    【讨论】:

    • 嗨,awoodland,您提供的示例非常适合 phy_idx,但后来我发现 Id 是 C 端的 32 字节字符数组。它在头文件中定义为 typedef unsigned char example_id_v1_t[32];是否存在可以创建可用 Java 结构的包含或应用?
    • @c12 - 我认为%include "arrays_java.i" 将覆盖unsigned char[32] -> short[] 用于Java。 (它必须是short,因为它没有签名并且不适合byte)。如果它不起作用,请告诉我,我会再看看它。
    • 以上两个例子都很棒,但是对于一个以 (void* input) 作为输入的函数来说呢?如果我想将字符串从 Java 传递给函数,需要添加什么类型的 SWIG 接口?
    • 还是最好推动创建一个采用特定类型的新 C 函数?
    • 如果您想为您的void * 传递一个字符串(即char *),您可以使用%applychar* 的规则应用于特定参数——例如%apply char * { void* input }
    猜你喜欢
    • 1970-01-01
    • 2013-05-15
    • 2010-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-02
    • 2011-02-10
    相关资源
    最近更新 更多