3

I a very new to swig and I am trying to create a swig wrapper in order to use a few C++ files in python. I have the following C++ class.

The following is a snippet of the code that I am trying to convert:

/*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);
        }
//....
}

I have been trying to write a example.i file that would accept pointers to typedefs(uint8_t *) all day today using help from swig documentation, but I have been unsuccessful.

The following is a packet_buffer.i file that I have tried which doesn't work.

%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. How do I write a swig code for member functions that take pointers to typedefs?
  2. Can I write a common %apply that can be used across the code or will I have to write specifics for each INPUT, OUTPUT parameter?
Flexo
  • 87,323
  • 22
  • 191
  • 272
Gatothgaj
  • 1,633
  • 2
  • 16
  • 27

1 Answers1

3

If I've understood this correctly the problem you're facing isn't that they're pointers, it's that they're potentially unbounded arrays.

You can warp an unbounded C array using carrays.i and the "%array_class" macro, e.g.:

%module packet
%include "stdint.i"

%{
    #include "packet.h"
%}

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

%include "packet.h"

Would then allow you to in Python write something like:

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

Note that you'll need to ensure the life of the buffer is sufficient - if the Python object gets released without the C++ code being aware you'll end up with undefined behaviour.

You can convert uint8_t* pointers (unbounded arrays) to buffer instances in Python using the frompointer methods that the %array_class macro also creates, e.g.:

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

You can add additional Python code to automate/hide most of the conversion between buffers if desired, or use MemoryViews to integrate tighter with Python on the C API side.

In general though since this is C++ I'd suggest using std::vector for this - it's much nicer to use on the Python side than the unbounded arrays and the cost is minimal for the safety and simplicity it gives you.

Flexo
  • 87,323
  • 22
  • 191
  • 272
  • Thanks a lot for the response. Since these are low level packet handlers we are not allowed to use STLs. This worked without errors, but I was not sure how to convert a function like this uint8_t* GetBuffer() { return (mpBuffer + mHead); }, where it returns a pointer to a member? – Gatothgaj May 08 '12 at 17:53
  • @GuruGovindan - I've added an update with the syntax for going the other way. Personally I still think it's a mistake to rule out `std::vector`, it's likely to reduce your defect rate and I'd be *very* surprised if you can make a realistic benchmark where it makes a difference. (Especially one from the Python side). – Flexo May 08 '12 at 18:15
  • Thanks for the update awoodland, unfortunately I cannot make decisions to change the design. But I will definetly suggest using vectors. – Gatothgaj May 08 '12 at 18:22
  • Hi awoodland, I have another query on swig. I would really appreciate your expertise on this. http://stackoverflow.com/questions/10624736/swig-error-with-nested-enums-in-c – Gatothgaj May 16 '12 at 23:15