开发者

C++'s char * by swig got problem in Python 3.0

开发者 https://www.devze.com 2022-12-29 16:59 出处:网络
Our C++ lib works fine with Python2.4 using Swig, returning a C++ char* back to a python str. But this solution hit problem in Python3.0, error is:

Our C++ lib works fine with Python2.4 using Swig, returning a C++ char* back to a python str. But this solution hit problem in Python3.0, error is:

Exception=(, UnicodeDecodeError('utf8', b"\xb6\x9d\xa.....",0, 1, 'unexpected code byte')

Our definition is like(working fine in Python 2.4):

void  cGetPubModulus(
 void*  pSslRsa,
    char*  cMod,
    int*   nLen );

%include "cstring.i"
%cstring_output_withsize开发者_开发知识库( char* cMod, int* nLen );

Suspect swig is doing a Bytes->Str conversion automatically. In python2.4 it can be implicit but in Python3.0 it's no long allowed.. Anyone got a good idea? thanks


It's rather Python 3 that does that conversion. In Python 2 bytes and str are the same thing, in Python 3 str is unicode, so something somewhere tries to convert it to Unicode with UTF8, but it's not UTF8.

Your Python 3 code needs to return not a Python str, but a Python bytes. This will not work with Python 2, though, so you need preprocessor statements to handle the differences.


I came across a similar problem. I wrote a SWIG typemap for a custom char array (an unsigned char in fact) and it got SEGFAULT when using Python 3. So I debugged the code within the typemap and I realized the problem Lennart states.

My solution to that problem was doing the following in that typemap:

%typemap(in) byte_t[MAX_FONTFACE_LEN] {
   if (PyString_Check($input))
   {
     $1 = (byte_t *)PyString_AsString($input);
   }
   else if  (PyUnicode_Check($input))
   {
     $1 = (byte_t *)PyUnicode_AsEncodedString($input, "utf-8", "Error ~");
     $1 = (byte_t *)PyBytes_AS_STRING($1);
   }
   else
   {
     PyErr_SetString(PyExc_TypeError,"Expected a string.");
     return NULL;
   }
}   

That is, I check what kind of string object PyObject is. The functions PyString_AsString() and PyUnicode_AsString() will return > 0 if its input it's an UTF- 8 string or an Unicode string respectively. If it's an Unicode string, we convert that string to bytes in the call PyUnicode_AsEncodedString() and later on we convert those bytes to a char * with the call PyBytes_AS_STRING().

Note that I vaguely use the same variable for storing the unicode string and converting it later to bytes. Despite of being that questionable and maybe, it could derive in another coding-style discussion, the fact is that I solved my problem. I have tested it out with python3 and python2.7 binaries without any problems yet.

And lastly, the last line is for replicating an exception in the python call, to inform about that input wasn't a string, either utf nor unicode.

0

精彩评论

暂无评论...
验证码 换一张
取 消