Home > database >  Dealing with in/out string parameters in Swig Python
Dealing with in/out string parameters in Swig Python

Time:12-31

Maybe someone know, how to rewrite getVersion to get in Python version and legacyVersion as a result of function instead of passing them as in/out parameters

   class DeviceInterface {
   public:
      virtual uint32_t getVersion(uint8_t* version, uint8_t* legacyVersion ) = 0;
   };

For now I create additional function in SWIG inteface file, but current implementation returns only one parameter instead of two.

%ignore DeviceInterface::getVersion( uint8_t* version, uint8_t* legacyVersion );

%extend DeviceInterface {
    virtual char * getVersion() {
        static uint8_t _v[200];
        static uint8_t _lv[200];
        $self->getVersion(_v, _lv);
        return (char *)_lv;
    }
};

UPDATE

Now I use @ignore and @extend features. But I guess there is more elegant way. Here is my working SWIG interface snippet:

%extend DeviceInterface {
    virtual PyObject *getVersion() {
        static uint8_t _v[200];
        static uint8_t _lv[200];
        uint32_t libCode = $self->getVersion(_v, _lv);
        return Py_BuildValue("(l,s,s)", libCode, (char *)_v, (char *)_lv);
    }
};

CodePudding user response:

You can define your own typemaps to handle the output parameters. In this case, the typemaps treat all uint32_t* parameters as 200-byte output buffers. This is a minimal example without error checking.

%module test

%include <stdint.i>

// Require no input parameter.  Just allocate a fixed-sized buffer.
%typemap(in,numinputs=0) uint8_t* %{
    $1 = new uint8_t[200];
%}

// Free the temporary buffer when done converting the argument
%typemap(freearg) uint8_t* %{
    delete [] $1;
%}

// On output, convert the buffer to a Python byte string
%typemap(argout) uint8_t* %{
    $result = SWIG_Python_AppendOutput($result, PyBytes_FromString(reinterpret_cast<char*>($1)));
%}

// Example implementation
%inline %{
#include <stdint.h>
class DeviceInterface {
public:
    virtual uint32_t getVersion(uint8_t* version, uint8_t* legacyVersion ) {
        strcpy(reinterpret_cast<char*>(version),"1.0.0");
        strcpy(reinterpret_cast<char*>(legacyVersion),"2.0.0");
        return 0;
    }
};
%}

Output:

>>> import test
>>> d=test.DeviceInterface()
>>> d.getVersion()
[0, b'1.0.0', b'2.0.0']

Note the output is a concatenation of the return value and two output parameters.

  • Related