3

我正在使用 Swig 2.0.7 并尝试使用 SWIG 包装 C 库以从 C# 访问它。这个 C 库通过 USB 与一些自定义硬件通信,因此我需要能够向/从这个库发送/接收原始字节 [] 数据。我可以完全控制这个 C 库,并且可以以任何我需要的方式对其进行修改,以使我的生活更轻松。

我的 Swig 包装器已经取得了很好的进展,我认为我已经得到了它可以很好地编译输入/输出字符串,以及将 byte[] 数据发送到库中。但是,我在尝试读取数据时遇到了问题。

我的数据包采用自定义 C 结构,如下所示:

typedef struct message_in message_in;
struct message_in {
    unsigned char* msg_data;    // Pointer to the data buffer received.
    int data_len;               // The total length of the data buffer received.
    char* dev_path;             // The device that sent us this message.
    message_in*  next;          // Used for the linked list
};

从 C 库中检索此消息的函数如下所示:

message_in* hhcPopIncomingMessage();

我用我的 .i 文件包装它,如下所示:

%include "arrays_csharp.i"
// Attempt to use byte[] instead of SWIGTYPE_p_unsigned_char
%apply unsigned char OUTPUT[]  { unsigned char* msg_data }

// Mark this function as owning the memory that it receives, 
//   so that it knows to deallocate
%newobject hhcPopIncomingMessage;

// Mark this structure to use a custom destructor
%extend device_message_in {
    ~device_message_in() {
       hhcFreeMessageIn($self);
    }
}

// Ignore the Linked List member in the data strucutre
%ignore next; 

我遇到的主要问题是——虽然它似乎可以很好地生成这个结构——但对于msg_data成员来说,它使用的是自动生成的 SWIGTYPE_p_unsigned_char,而不是 byte[]。我应用的类型映射改变了 msg_data 访问器的返回值,但它仍然在内部使用 SWIGTYPE_p_unsigned_char,自然不会编译:

  public byte[] msg_data {
    set {
      hiqusbPINVOKE.message_in_msg_data_set(swigCPtr, value);
    } 
    get {
      IntPtr cPtr = hiqusbPINVOKE.message_in_msg_data_get(swigCPtr);
      SWIGTYPE_p_unsigned_char ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_unsigned_char(cPtr, false);
      return ret;
    } 
  }

(以上编译失败,出现错误:

error CS0029: Cannot implicitly convert type `byte[]' to `System.IntPtr'
error CS0029: Cannot implicitly convert type `SWIGTYPE_p_unsigned_char' to `byte[]'

从我的数据结构中读取缓冲区作为字节 [] 的正确方法是什么?

在此先感谢您的帮助!

编辑更新: 我想我想出了我希望它生成的代码——现在我只是不知道如何让 SWIG 生成该代码。

它当前生成的内容:

  public byte[] msg_data {
    set {
      hiqusbPINVOKE.hiq_hid_device_message_in_msg_data_set(swigCPtr, value);
    } 
    get {
      IntPtr cPtr = hiqusbPINVOKE.hiq_hid_device_message_in_msg_data_get(swigCPtr);
      SWIGTYPE_p_unsigned_char ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_unsigned_char(cPtr, false);
      return ret;
    } 
  }

我希望它产生什么:

  public byte[] msg_data {
    // No 'set' member is needed, as this value is only ever read from this structure.
    get {
      int len = this.data_len;
      byte[] managedArray = new byte[len];
  IntPtr cPtr = hiqusbPINVOKE.hiq_hid_device_message_in_msg_data_get(swigCPtr);
      System.Runtime.InteropServices.Marshal.Copy(cPtr, managedArray, 0, len);
      return managedArray;
    } 
  }
4

0 回答 0