* Alf P. Steinbach /Usenet, on 17.07.2010 11:50:
[Cross-posted comp.lang.c++ and comp.lang.python]
[snip]
this occurred to me:
#define CPPY_GETSET_FORWARDERS( name ) \
::progrock::cppy::forwardersGetSet( \
&CppClass::name \
).themForwarders< &CppClass::name >()
Here forwardersGetSet is a templated function that via argument type
deduction produces an instance of a templated struct, thereby "knowing"
the member type, which struct in turn has a member function templated on
the member pointer, which the macro supplies *twice*, once as run-time
arg and once as compile-time.
That trick allowed uniform treatment of data and function member pointers. :-)
So, with cppy the complete noddy2 example from the docs (I'm sort of working my
way through the Python doc examples) now looks as shown below.
The "typelessness" of the 'first' and 'last' members is in order to recreate as
close as possible the noddy2 functionality, or, lack of it. Also, I haven't got
around to sort of backporting the 'Exposition' scheme to modules. So, exposure
of module functionality looks a little different from same for types, for now.
<code>
// The Python 3.1.1 docs' Noddy 2 example rewritten using cppy.
// Docs: "Extending and Embedding the Python Interpreter" ยง2.1.1
#include <progrock/cppy/PyClass.h> // PyWeakPtr, PyPtr, PyModule, PyClass
using namespace progrock;
namespace {
using namespace cppy;
struct Noddy
{
PyPtr first;
PyPtr last;
int number;
Noddy( PyWeakPtr pySelf, PyPtr args, PyPtr kwArgs )
: number( 0 )
{
devsupport::suppressUnusedWarning( pySelf );
PyWeakPtr pFirstName = 0;
PyWeakPtr pLastName = 0;
static char* kwlist[] = { "first", "last", "number", 0 };
::PyArg_ParseTupleAndKeywords(
args.rawPtr(), kwArgs.rawPtr(), "|OOi", kwlist,
pointerTo( pFirstName ), pointerTo( pLastName ), &number
)
>> Accept< IsNonZero >()
|| throwX( "Invalid args" );
if( pFirstName != 0 ) { first = pFirstName; }
if( pLastName != 0 ) { last = pLastName; }
}
PyPtr name()
{
(first != 0)
|| throwX( ::PyExc_AttributeError, "first" );
(last != 0)
|| throwX( ::PyExc_AttributeError, "last" );
return (PyString( first ) + L" " + PyString( last )).pyPtr();
}
};
struct NoddyPyClass: PyClass< Noddy >
{
NoddyPyClass( PyModule& m, PyString const& name, PyString const& doc )
: PyClass< Noddy >( m, name, doc, Exposition()
.method(
L"name", CPPY_GLUE( name ),
L"Return the name, combining the first and last name"
)
.attribute(
L"first", CPPY_GLUE( first ), L"first name"
)
.attribute(
L"last", CPPY_GLUE( last ), L"last name"
)
.attribute(
L"number", CPPY_GLUE( number ), L"noddy number"
)
)
{}
};
class NoddyModule: public PyModule
{
private:
NoddyPyClass noddyPyClass_;
public:
NoddyModule()
: PyModule(
L"noddy2", L"Example module that creates an extension type." )
, noddyPyClass_( *this,
L"Noddy", L"A Noddy object has a name and a noddy number" )
{}
};
} // namespace <anon>
PyMODINIT_FUNC
PyInit_noddy2()
{
return cppy::safeInit< NoddyModule >();
}
</code>
I wonder if this is readable / self-documenting, or not?
Cheers,
- Alf
--
blog at <url: http://alfps.wordpress.com>
--
http://mail.python.org/mailman/listinfo/python-list