How can Python get binary data (char *) from C ++ SWIG?

I am using C ++ functions in Python by SWIG, and now I am facing a problem. When I pass char * from C ++ to Python, char * translates to Python.

For instance:

example.h:

char * fun() { return "abc\0de"; } 

now in Python, we call example.fun () it only prints "A" instead of "A \ 0de" the data behind '\ 0' is deleted using Python.

I want to get all the characters (this is binary data that can contain '\ 0') from fun () in C ++, and any advice is welcome

+4
source share
3 answers

C / C ++ lines end with NULL, which means that the first character \0 marks the end of the line.

When a function returns a pointer to such a string, the calling object (SWIG in this case) does not know if there is more data after the first \0 , so you only get the first part.

So, first you need to change the C function to return not only the string, but also its length. Since there can only be one return value, we will use pointer arguments.

 void fun(char** s, int *sz) { *s = "abc\0de"; *sz = 6; } 

SWIG documents suggest using cstring.i library to port such functions. In particular, the last macro does exactly what you need.

 %cstring_output_allocate_size(parm, szparm, release) 

Read the docs to find out how to use it.

+6
source

First of all, you should not use char * if you are dealing with binary data (swig considers these to be ordinary strings). You should use void * instead. swig provides a module called "cdata.i" - you must include this in the interface definition file.

As soon as you enable this, it gives two functions - cdata() and memmove() .

  • Given void * and the length of the binary data, cdata() converts it to the string type of the target language.
  • memmove() does the opposite - the specified type of string, it will copy the contents of the string (including embedded zero bytes) into type C void* .

Processing binary data with this module is much easier. Hope this is what you need.

 example.i %module example %include "cdata.i" %{ void *fun() { return "abc\0de"; } %} test.py import example print example.cdata(example.fun(), 6) 
+7
source

See 8.3 C String Processing in the documentation.

Also from the documentation :

The char * data type is treated as an ASCII string with NULL termination. SWIG maps this to an 8-bit character string in the target language script. SWIG converts character strings in the target language to NULL complete strings before passing them to C / C ++. By default, processing these strings does not allow them to have embedded NULL bytes. Therefore, the char * data type is usually not suitable for binary data transfer. However, this change can be changed by defining a printed SWIG card. See the chapter on Typemaps for more information. about it.

0
source

Source: https://habr.com/ru/post/1381637/


All Articles