Revision: 521
http://svn.sourceforge.net/pygccxml/?rev=521&view=rev
Author: roman_yakovenko
Date: 2006-09-04 03:09:55 -0700 (Mon, 04 Sep 2006)
Log Message:
-----------
renaming the document
Added Paths:
-----------
pyplusplus_dev/docs/peps/function_transformation.rest
Copied: pyplusplus_dev/docs/peps/function_transformation.rest (from rev 518, pyplusplus_dev/docs/peps/call_wrapper_policies.rest)
===================================================================
--- pyplusplus_dev/docs/peps/function_transformation.rest (rev 0)
+++ pyplusplus_dev/docs/peps/function_transformation.rest 2006-09-04 10:09:55 UTC (rev 521)
@@ -0,0 +1,254 @@
+=====================
+call wrapper policies
+=====================
+
+.. contents:: Table of contents
+
+-------------------
+What is useful for?
+-------------------
+Not all C++ functions could be exposed to Python as is. For example, next function
+could not be exposed:
+::
+
+ void get_size( int& size );
+
+In order to expose ``get_size`` function, an user need to create next wrapper:
+::
+
+ int get_size_wrapper( ){
+ int size(0);
+ get_size( size );
+ return size;
+ }
+
+|cwp| will provide the user with simple and intuitive way to instruct
+`Py++`_ to generate right wrapper. Also, it will be possible to create
+a custom policies.
+
+This document describes what is *going to be implemented*.
+
+--------
+Analysis
+--------
+
+C++ function arguments usage
+----------------------------
+
+In C++ function argument can be used to:
+
+* to pass some data to function ( in )
+
+ there is no need to return variable from the function
+
+* to return some data from function ( out )
+
+ there is no need to force Python programmer to pass the variable as argument
+ to the function
+
+* both ( in/out )
+
+Function-wrapper signature will be a little bit different in every case.
+
+Variable names
+--------------
+I think it should be possible to apply few |cwp| on a single function.
+The main, (read unresolved) issue, is management of variable names within
+function-wrapper. I see next problems, which we should solve, before proceeding
+to implementation:
+
+1. To share variable name, between different pieces of code.
+
+ Right now I think, that every |cwp| will have ``pre-call`` and ``post-call``
+ code creators. This design will allow the user to mix few |cwp|'s within
+ single function-wrapper.
+
+2. To insure name uniqueness.
+
+3. To give meaningful name.
+
+I think that is it very easy to solve the problem, if I remove "readability"
+requirement.
+
+Call policies
+-------------
+I don't have any solution to the next problem.
+I am going to change a little an example, from `Boost.Python`_ tutorials:
+http://www.boost.org/libs/python/doc/tutorial/doc/html/python/functions.html#python.call_policies
+::
+
+ //C++ code
+ struct Y
+ {
+ X x; Z* z;
+ int z_value() { return z->value(); }
+ };
+
+ X& f(Y& y, Z* z, int& error)
+ {
+ y.z = z;
+ return y.x;
+ }
+
+ //Boost.Python code
+ def("f", f, return_internal_reference<1, with_custodian_and_ward<1, 2> >() );
+
+What is the difference? Function ``f`` now takes 3rd argument - ``int&``. This
+function could not be called from `Python`_. (Hint: numbers are immutable
+objects in `Python`_ ). So in order to expose function ``f`` to `Python`_,
+an user need to create a wrapper. And now he has a problem: how to wrap the function?
+
+I see only one solution user have to change signature of function ``f``.
+Now some speculations:
+
+1. May be it is possible with `Boost.Python`_ library to set call policies on the
+ part of the return value?
+ ::
+
+ boost::tuple f_wrapper( Y& y, Z* z ){
+ int error(0);
+ X& x = f( y, z, error );
+ return boost::tuple<X&, int>( x, error );
+ }
+
+ def("f", f_wrapper, smart call policies that will work only on first element within the tuple );
+
+2. May be it is possible to create Boost.Python ``object`` with life-time management
+ hint?
+ ::
+
+ boost::python::tuple f_wrapper( Y& y, Z* z ){
+ int error(0);
+ X& x = f( y, z, error );
+ boost::python::object x_obj( x, x is internal reference of y );
+ return boost::python::make_tuple( x_obj, error );
+ }
+
+Anyway, I think we will just ignore the problem - software ( == Boost.Python )
+should not be perfect - it should work in most ( != all ) cases!
+
+------------
+Common |cwp|
+------------
+Those names are not final and could( may be should ) be changed.
+
+immutable by reference
+-----------------------
+::
+
+ //function to be exported
+ something f( int& i, std::string& str )
+
+I suppose this is very common use case. More over this use case `Py++`_
+can and will treat by its own - no user action is needed. The wrapper
+generated by `Py++`_ will very similar to the next code:
+::
+
+ void f_wrapper( const int& i, const std::string& str ){
+ int i_out( i );
+ std::string str_out( str );
+ boost::python::object f_return = f( i_out, str_out );
+ return boost::python::make_tuple( f_return, i, str );
+ }
+
+
+The only customization available for user is to setup argument type:
+[in\|out\|in,out]
+
+array
+-----
+Arrays are a little bit different beasts. Python does not have arrays.
+So, `Py++`_, should implement arrays convertion: from/to C++/Python.
+This is not the only difference, consider next function:
+::
+
+ void fill( char* buffer, int index ){
+ buffer[ index ] = 'c';
+ }
+
+
+There are few ways to expose this function:
+::
+
+ ??? fill_wrapper( boost::python:list buffer, index ){
+ long buffer_size = boost::python::extract<long>( buffer.attr("__len__") );
+ boost::scoped_array<char> buffer_( new char[ buffer_size ] );
+ for( long i = 0; i < buffer_size; ++i ){
+ buffer_[ i ] = boost::python::extract<char>( buffer[i] );
+ }
+ fill( buffer_.get(), index );
+ //Now the question: how to return buffer_ to the caller?
+ //by constructing new list?
+ boost::python::list return_;
+ for( long i = 0; i < buffer_size; ++i ){
+ return_.insert( i, buffer_[i] );
+ }
+ return return_;
+ //or by modifying the buffer argument? In this case `Py++`_ will
+ //delete all items from buffer and will copy into it items from buffer_
+ //variable.
+ }
+
+Arrays size
+^^^^^^^^^^^
+1. static array - size of array is known at compile time.
+2. dynamic array
+
+ + size of array is one of the function arguments
+
+ + other ( will not be implemented in the first phase )
+
+ - size of array is some global/local variable
+
+ - size of array is returned by invocation some function
+
+
+status as exception
+-------------------
+There a lot of code, that returns success status and/or error description by
+using one of the function arguments. It will be possible to instruct `Py++`_
+to create wrapper for those functions, that will throw exception.
+::
+
+ bool do_smth( error_description& error_desc );
+
+ bool do_smth_wrapper(){
+ error_description error_desc;
+ bool return_ = do_smth( error_desc );
+ if( some user code that will check that error_desc contains error ){
+ throw some user code that will construct an exception from the error_desc;
+ }
+ return return_;
+ }
+
+pythread safe
+-------------
+Why not :-)? See next FAQ: http://boost.org/libs/python/doc/v2/faq.html#threadsupport
+So, how `Py++`_ can help? `Py++`_ can generate exception safe code,
+that will acquire and release Python global interpreter lock.
+
+-------
+Summary
+-------
+
+It still not clear to me how it should be implemented. There are also some issues
+with `Boost.Python`_ library before we can implement some policies.
+
+If you can help or have some nice idea, please share:
+https://lists.sourceforge.net/lists/listinfo/pygccxml-development
+
+
+.. _`Py++` : ./../pyplusplus.html
+.. |cwp| replace:: *"call wrapper policies"*
+.. _`Boost.Python`: http://www.boost.org/libs/python/doc/index.html
+.. _`Python`: http://www.python.org
+.. _`GCC-XML`: http://www.gccxml.org
+
+..
+ Local Variables:
+ mode: indented-text
+ indent-tabs-mode: nil
+ sentence-end-double-space: t
+ fill-column: 70
+ End:
+
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|