Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SWIG 'cstring.i' Python return byte type instead of string type

Tags:

python

swig

I have a C function like

int foo(void ** buf, int * buf_size)

And I use cstring.i to wrap it for use in Python 3. The result of the wrapped Python function is of type string.

Is there a way to get the result as type binary?

Background: The data buf gets filled with is msgpack encoded data, so using str.decode in Python is not an option. The msgpack implementations for Python only accept binary data.

like image 479
Joern Weissenborn Avatar asked Apr 26 '26 20:04

Joern Weissenborn


1 Answers

If you use %cstring_output_allocate_size the wrapper function _wrap_foo calls SWIG_FromCharPtrAndSize() which has the following decoding logic:

#if PY_VERSION_HEX >= 0x03000000
#if defined(SWIG_PYTHON_STRICT_BYTE_CHAR)
      return PyBytes_FromStringAndSize(carray, (Py_ssize_t)(size));
#else
#if PY_VERSION_HEX >= 0x03010000
      return PyUnicode_DecodeUTF8(carray, (Py_ssize_t)(size), "surrogateescape");
#else
      return PyUnicode_FromStringAndSize(carray, (Py_ssize_t)(size));
#endif
#endif
#else
  return PyString_FromStringAndSize(carray, (Py_ssize_t)(size));
#endif

So you can get bytes instead of unicode string by #defining SWIG_PYTHON_STRICT_BYTE_CHAR. This is documented in http://www.swig.org/Doc3.0/Python.html so it's an official feature. But since it's a global switch, it's only useful if you want all string parameters to be mapped to bytes. If you need a mix of str and bytes in your API the only solution I can see is a custom typemap.

like image 152
marcin Avatar answered Apr 28 '26 14:04

marcin