[C++-sig] wchar_t* type conversion

Nicolas Lara nicolaslara at gmail.com
Mon Jun 22 21:03:22 CEST 2009


Thanks!
I'm trying to create an interface for a third party library, so I
can't actually change it. I also tried using ctypes.pointer but didn't
work either. I'll probably need to create a wrapper that does the type
conversion.

Thanks again Renato!
If anyone knows how to make it work with wchar_t* i'd appreciate it!

On Mon, Jun 22, 2009 at 11:57 AM, Renato Araujo<renatox at gmail.com> wrote:
> Hi Nicolas
>
> At my first look I get this working changing the register function:
>
> << to_python_converter<wchar_t*,wchar_t_to_python_str>();
>>> to_python_converter<wchar_t,wchar_t_to_python_str>();
>
> << static PyObject* convert(wchar_t* const& w)
>>> static PyObject* convert(wchar_t const& w)
>
> <<    wchar_t* w2 = w;
> <<   while(*w2++ != 0){
> <<      s += *w2;
>>>   wchar_t w2 = w;
>>>   while(w2++ != 0){
>>>      s += w2;
>
> and the function signature:
>
> << void testArgument(wchar_t * w){
>>> void testArgument(const wchar_t &w){
>
> this make everything works fine:
>
> I don't know how get this working with wchar_t* in function signature.
> Maybe create a class_ for w_char_t.
>
>
>
> On Mon, Jun 22, 2009 at 2:27 PM, Nicolas Lara<nicolaslara at gmail.com> wrote:
>> Hi Renato,
>> Thanks for the reply. Here's some test code. (I pasted it to make it
>> more friendly =)
>> http://paste.pocoo.org/show/124521/
>>
>> Testing it in python: http://paste.pocoo.org/show/124523/
>>
>> Thanks in advance!
>> Best Regards
>>
>> For the archives:
>>
>> === test.cpp
>>
>> #include "CLucene.h"
>> #include <string>
>> #include <boost/python.hpp>
>>
>> using namespace boost::python;
>>
>> struct wchar_t_to_python_str
>> {
>>  static PyObject* convert(wchar_t* const& w)
>>  {
>>    string s = "";
>>    wchar_t* w2 = w;
>>    while(*w2++ != 0){
>>      s += *w2;
>>    }
>>    return boost::python::incref(boost::python::object(s).ptr());
>>  }
>> };
>>
>> struct wchar_t_from_python_str
>> {
>>  wchar_t_from_python_str()
>>  {
>>    boost::python::converter::registry::push_back(
>>                           &convertible,
>>                           &construct,
>>                           boost::python::type_id<wchar_t>());
>>  }
>>
>>  static void* convertible(PyObject* obj_ptr)
>>  {
>>    if (!PyString_Check(obj_ptr)) return 0;
>>    return obj_ptr;
>>  }
>>
>>  static void construct(
>>                        PyObject* obj_ptr,
>>
>> boost::python::converter::rvalue_from_python_stage1_data* data)
>>  {
>>    const char* value = PyString_AsString(obj_ptr);
>>    Py_ssize_t l = PyString_Size(obj_ptr);
>>    if (value == 0) boost::python::throw_error_already_set();
>>    void* storage = (
>>
>> (boost::python::converter::rvalue_from_python_storage<wchar_t*>*)
>>                     data)->storage.bytes;
>>
>>    wchar_t* w = new wchar_t[l];
>>    for(int i=0;i<l;i++){
>>      w[i] = value[i];
>>    }
>>    data->convertible = w;
>>  }
>> };
>>
>> void init_module()
>> {
>>  to_python_converter<wchar_t*,wchar_t_to_python_str>();
>>  wchar_t_from_python_str();
>> }
>>
>>
>> struct Test {
>>  Test(){}
>>
>>  wchar_t * testReturnValue(string s){
>>    wchar_t *p=new wchar_t[s.size()];
>>    for(string::size_type i=0; i<s.size(); ++i)
>>      p[i]=s[i];
>>    return p;
>>  }
>>
>>  void testArgument(wchar_t * w){
>>    printf("ok\n");
>>  }
>> };
>>
>>
>> BOOST_PYTHON_MODULE(test){
>>  init_module();
>>  class_<Test>("Test")
>>    //.def("testReturnValue", &Test::testReturnValue) // <- desn't compile
>>    .def("testArgument", &Test::testArgument);
>>  ;
>>
>> }
>>
>> ==== testing it in python
>>>>> import test
>>
>>>>> t = test.Test()
>>
>>>>> t.testArgument(u"")
>> ---------------------------------------------------------------------------
>> ArgumentError                             Traceback (most recent call last)
>>
>> /home/.../build/<ipython console> in <module>()
>>
>> ArgumentError: Python argument types in
>>    Test.testArgument(Test, unicode)
>> did not match C++ signature:
>>    testArgument(Test {lvalue}, wchar_t*)
>>
>>>>> t.testArgument("")
>> ---------------------------------------------------------------------------
>> ArgumentError                             Traceback (most recent call last)
>>
>> /home/.../build/<ipython console> in <module>()
>>
>> ArgumentError: Python argument types in
>>    Test.testArgument(Test, str)
>> did not match C++ signature:
>>    testArgument(Test {lvalue}, wchar_t*)
>>
>>>>> from ctypes import c_wchar_p
>>
>>>>> c_wchar_p("hello")
>>>>> c_wchar_p(u'hello')
>>
>>>>> w = c_wchar_p("hello")
>>
>>>>> t.testArgument(w)
>> ---------------------------------------------------------------------------
>> ArgumentError                             Traceback (most recent call last)
>>
>> /home/nicolas/devel/CyLucene/build/<ipython console> in <module>()
>>
>> ArgumentError: Python argument types in
>>    Test.testArgument(Test, c_wchar_p)
>> did not match C++ signature:
>>    testArgument(Test {lvalue}, wchar_t*)
>>
>>
>> On Mon, Jun 22, 2009 at 1:48 PM, Renato Araujo<renatox at gmail.com> wrote:
>>> Hi Nicolas,
>>>
>>> Can  you send a simple example, where the convention fail (c++ to
>>> python or python to c++)? What kind of test you are running?
>>>
>>> BR
>>> Renato
>>>
>>>
>>>
>>> On Mon, Jun 22, 2009 at 8:31 AM, Nicolas Lara<nicolaslara at gmail.com> wrote:
>>>> Hello,
>>>> I'm new to Boost::Python and am encountering a problem that seem to be
>>>> quite common: I need to expose a class to C++ whose constructor takes
>>>> a wchar_t* as a parameter.
>>>> The problem is that there is no default type converter from wchar_t to
>>>> python and vice-versa.
>>>>
>>>> I wanted to know if there was a standard way of doing this. Or if
>>>> anyone could point me to an implementation of this type conversion.
>>>>
>>>> So far I'm doing this (based on the faq):
>>>>
>>>> struct wchar_t_to_python_str
>>>> {
>>>>  static PyObject* convert(wchar_t* const& w)
>>>>  {
>>>>    string s = "";
>>>>    wchar_t* w2 = w;
>>>>    while(*w2++ != 0){
>>>>      s += *w2;
>>>>    }
>>>>    return boost::python::incref(boost::python::object(s).ptr());
>>>>  }
>>>> };
>>>>
>>>> struct wchar_t_from_python_str
>>>> {
>>>>  wchar_t_from_python_str()
>>>>  {
>>>>    boost::python::converter::registry::push_back(
>>>>                           &convertible,
>>>>                           &construct,
>>>>                           boost::python::type_id<wchar_t>());
>>>>  }
>>>>
>>>>  static void* convertible(PyObject* obj_ptr)
>>>>  {
>>>>    if (!PyString_Check(obj_ptr)) return 0;
>>>>    return obj_ptr;
>>>>  }
>>>>
>>>>  static void construct(
>>>>                        PyObject* obj_ptr,
>>>>
>>>> boost::python::converter::rvalue_from_python_stage1_data* data)
>>>>  {
>>>>    const char* value = PyString_AsString(obj_ptr);
>>>>    Py_ssize_t l = PyString_Size(obj_ptr);
>>>>    if (value == 0) boost::python::throw_error_already_set();
>>>>    void* storage = (
>>>>
>>>> (boost::python::converter::rvalue_from_python_storage<wchar_t*>*)
>>>>                     data)->storage.bytes;
>>>>
>>>>    wchar_t* w = new wchar_t[l];
>>>>    for(int i=0;i<l;i++){
>>>>      w[i] = value[i];
>>>>    }
>>>>    data->convertible = w;
>>>>  }
>>>> };
>>>>  void init_module()
>>>>  {
>>>>    to_python_converter<wchar_t*,wchar_t_to_python_str>();
>>>>    wchar_t_from_python_str();
>>>>   }
>>>>
>>>> BOOST_PYTHON_MODULE(queryparser){
>>>>  init_module();
>>>> }
>>>>
>>>> But it doesn't seem to be working. It compiles, but python doesn't
>>>> understand the conversion.
>>>> Any thoughts?
>>>>
>>>>
>>>> Thanks in advance!
>>>>
>>>> --
>>>> Nicolas Lara
>>>> Linux user #380134
>>>> http://nicolas-lara.blogspot.com/
>>>> Public key id: 0x152e7713 at http://subkeys.pgp.net/
>>>> _______________________________________________
>>>> Cplusplus-sig mailing list
>>>> Cplusplus-sig at python.org
>>>> http://mail.python.org/mailman/listinfo/cplusplus-sig
>>>>
>>>
>>>
>>>
>>> --
>>> Renato Araujo Oliveira Filho
>>> _______________________________________________
>>> Cplusplus-sig mailing list
>>> Cplusplus-sig at python.org
>>> http://mail.python.org/mailman/listinfo/cplusplus-sig
>>>
>>
>>
>>
>> --
>> Nicolas Lara
>> Linux user #380134
>> http://nicolas-lara.blogspot.com/
>> Public key id: 0x152e7713 at http://subkeys.pgp.net/
>> _______________________________________________
>> Cplusplus-sig mailing list
>> Cplusplus-sig at python.org
>> http://mail.python.org/mailman/listinfo/cplusplus-sig
>>
>
>
>
> --
> BR
> Renato Araujo Oliveira Filho
> _______________________________________________
> Cplusplus-sig mailing list
> Cplusplus-sig at python.org
> http://mail.python.org/mailman/listinfo/cplusplus-sig
>



-- 
Nicolas Lara
Linux user #380134
http://nicolas-lara.blogspot.com/
Public key id: 0x152e7713 at http://subkeys.pgp.net/


More information about the Cplusplus-sig mailing list