[C++-sig] Re: Automatic PyUnicode to 'const char*'

David Abrahams dave at boost-consulting.com
Fri Aug 1 13:15:29 CEST 2003


"Lijun Qin" <qinlj at solidshare.com> writes:

> Hi, all:
>
> I have found a method to do this, by register a convert function:
>
> inline void* convert_to_cstring_from_unicode(PyObject* obj)
> {
>     if (!PyUnicode_Check(obj)) return 0;
>     PyObject* str = PyUnicode_AsEncodedString(obj, "mbcs", NULL);
>      if (!str) throw_error_already_set();
>
>      //We must release the str before we return to python, gard here
>      static leak_gard _gard;
>
>      unicode_str_map[obj] = str;
>      return PyString_AsString(str);
> }
>
> converter::registry::insert(convert_to_cstring_from_unicode,
> type_id<char>());
>
> But the problem is that the PyString object must be freed when the
> call is completed, I currently do this by applying a custom call
> policy to the methods using 'const char*' type of parameters, but if
> there were reclusive

"recursive", I think.

> calls into the same fuction, it'll much complex.
>
> In this procedure, I found that if we can apply the call policies
> before the argument conversion procedure and in the context of the
> call policy object (a call policy object is always attached with a
> method, right?)

Right.

> the problem will be solved much easier and safer. We'll be able to
> replace the PyUnicode object with a PyString object (in Windows
> platform, always MBCS encoding), maybe save the original args tuple
> in the call policy object

This is the key thing which I had forgotten: call policies can have
state.  You can keep a stack (linked list) of "original args tuples"
in the call policy in order to deal with recursion.

> then convert the args to C++ (it'll success because the arg is a
> PyString) and call the C++ function, when postcall(args, result)
> called, we can just release the newly allocated args tuple, replace
> it with the original one. This will give us more control on how the
> args be processed.

Yes, that sounds brilliant!  So this approach does not use the
convert_to_cstring_from_unicode converter, correct?

I think it has inspired me, also, to consider expanding the conversion
interface.  I was looking for a way for converters to maintain state
(e.g. to be able to keep a PyString alive during the conversion, or to
be able to fabricate a vector<int> from a Python list and then write
the modified elements of the vector back into the list after the call)
without incurring the cost of a polymorphic postcall operation for
each converter in a function call.  One possibility might be to define
an abstract postcall object, and pass a pointer to a chain of those,
which lives in the call policy, to all converters during function
calls.  Any converter which needed to maintain state could add a
postcall object to the chain.  That would essentially reduce the
postcall check to a single step for N arguments, in the usual case
that there were no postcall operations.  In non-function contexts,
such as

     char const* p = extract<char*>(s);

the pointer to the postcall chain would be NULL, so any converters
which required a postcall chain could simply report "no match".


-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com





More information about the Cplusplus-sig mailing list