3

我是 swig 的新手,我正在尝试创建一个 swig 包装器,以便在 python 中使用一些 C++ 文件。我有以下 C++ 类。

以下是我要转换的代码片段:

/*packet_buffer.h*/
class CPacketBuffer {
 public:
    // construct based on given buffer, data is not copied
    CPacketBuffer(uint8_t* data, uint32_t length) {
        mpBuffer = data;
        mLength  = length;
        mHead    = 0;
        mTail    = length;
    }
    uint8_t* GetBuffer() {
        return (mpBuffer + mHead);
    }
    void Add(const uint8_t* data, uint32_t length) {
            if ((mTail + length) > mLength) {
            length = (mLength - mTail);
        }
//....
}

我一直在尝试使用 swig 文档的帮助编写一个 example.i 文件,该文件今天整天都接受指向 typedefs(uint8_t *) 的指针,但我没有成功。

以下是我尝试过的一个 packet_buffer.i 文件,但它不起作用。

%module packet_buffer
%include typemaps.i
%apply unsigned char* {uint8_t*};
%apply unit8_t *INPUT {uint8_t *data};



%{
    #define SWIG_FILE_WITH_INIT
    #include "../include/packet_buffer.h"
%}
%include "../include/packet_buffer.h"
  1. 如何为使用指向 typedef 的指针的成员函数编写 swig 代码?
  2. 我可以编写一个可以在代码中使用的通用 %apply,还是必须为每个 INPUT、OUTPUT 参数编写细节?
4

1 回答 1

3

如果我正确理解了这一点,那么您面临的问题不是它们是指针,而是它们可能是无界数组。

您可以使用 carrays.i 和“%array_class”宏来扭曲无界 C 数组,例如:

%module packet
%include "stdint.i"

%{
    #include "packet.h"
%}

%include "carrays.i"
%array_class(uint8_t, buffer);

%include "packet.h"

然后允许您在 Python 中编写如下内容:

a = packet.buffer(10000000) 
p = packet.CPacketBuffer(a.cast(), 10000000)

请注意,您需要确保缓冲区的生命周期足够长 - 如果 Python 对象在 C++ 代码不知道的情况下被释放,您最终会出现未定义的行为。

您可以使用宏还创建的方法将uint8_t*指针(无界数组)转换为 Python 中的缓冲区实例,例如:frompointer%array_class

r = packet.GetBuffer()
buf = packet.buffer_frompointer(r)

如果需要,您可以添加额外的 Python 代码来自动化/隐藏缓冲区之间的大部分转换,或者使用MemoryViews在 C API 端与 Python 更紧密地集成。

一般来说,虽然这是 C++,但我建议使用std::vector它 - 在 Python 端使用它比无界数组更好,并且成本最低,因为它为您提供了安全性和简单性。

于 2012-05-08T09:12:00.010 回答