[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