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?

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

4 Comments

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?
@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).
Thanks for the update awoodland, unfortunately I cannot make decisions to change the design. But I will definetly suggest using vectors.
Hi awoodland, I have another query on swig. I would really appreciate your expertise on this. stackoverflow.com/questions/10624736/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.