2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-27 19:12:16 +00:00

commented

[SVN r12209]
This commit is contained in:
Dave Abrahams
2002-01-04 02:06:21 +00:00
parent 1201761ff3
commit 586e6178b4
3 changed files with 90 additions and 16 deletions

View File

@@ -5,7 +5,7 @@
// to its suitability for any purpose.
// Seems to be neccessary to suppress an ICE with MSVC
#include "boost/mpl/comparison/less.hpp"
#include <boost/mpl/comparison/less.hpp>
#include "simple_type.hpp"
#include "complicated.hpp"
@@ -21,12 +21,14 @@
#include <boost/mpl/type_list.hpp>
#include <string.h>
// Declare some straightforward extension types
extern "C" void
dealloc(PyObject* self)
{
PyObject_Del(self);
}
// Noddy is a type we got from one of the Python sample files
struct NoddyObject : PyObject
{
int x;
@@ -50,6 +52,22 @@ PyTypeObject NoddyType = {
0, /*tp_hash */
};
// Create a Noddy containing 42
extern "C" PyObject*
new_noddy(PyObject* self, PyObject* args)
{
NoddyObject* noddy;
if (!PyArg_ParseTuple(args,":new_noddy"))
return NULL;
noddy = PyObject_New(NoddyObject, &NoddyType);
noddy->x = 42;
return (PyObject*)noddy;
}
// Simple is a wrapper around a struct simple, which just contains a char*
struct SimpleObject : PyObject
{
simple x;
@@ -73,20 +91,7 @@ PyTypeObject SimpleType = {
0, /*tp_hash */
};
extern "C" PyObject*
new_noddy(PyObject* self, PyObject* args)
{
NoddyObject* noddy;
if (!PyArg_ParseTuple(args,":new_noddy"))
return NULL;
noddy = PyObject_New(NoddyObject, &NoddyType);
noddy->x = 42;
return (PyObject*)noddy;
}
// Create a Simple containing "hello, world"
extern "C" PyObject*
new_simple(PyObject* self, PyObject* args)
{
@@ -101,12 +106,21 @@ new_simple(PyObject* self, PyObject* args)
return (PyObject*)simple;
}
// Initial method table for the module
static PyMethodDef methods[] = {
{ "new_noddy", new_noddy, METH_VARARGS },
{ "new_simple", new_simple, METH_VARARGS },
{0, 0, 0, 0}
};
//
// Declare some wrappers/unwrappers to test the low-level conversion
// mechanism. See boost/python/converter/source.hpp,target.hpp for a
// description of how the type parameters to wrapper<> and unwrapper<>
// are selected.
//
// Wrap an int by converting it to a Python Int
struct int_wrapper
: boost::python::converter::wrapper<int const&>
{
@@ -116,6 +130,7 @@ struct int_wrapper
}
};
// Wrap a simple by converting it to a Simple
struct simple_wrapper
: boost::python::converter::wrapper<simple const&>
{
@@ -127,6 +142,10 @@ struct simple_wrapper
}
};
// wrap a mutable reference to a simple by converting it to a
// Simple. Normally we wouldn't do it this way, since modifications to
// the result clearly don't change the original object, but here we're
// just proving that the mechanism works.
struct simple_ref_wrapper
: boost::python::converter::wrapper<simple&>
{
@@ -138,6 +157,9 @@ struct simple_ref_wrapper
}
};
// extract an int from a Python Int by converting it to an int. Since
// int is a scalar type, we convert by-value. Since Python Ints are
// immutable, there's no non-const reference converter.
struct native_int_unwrapper
: boost::python::converter::unwrapper<int>
{
@@ -152,6 +174,7 @@ struct native_int_unwrapper
}
};
// Extract an int from a Noddy
struct noddy_int_unwrapper
: boost::python::converter::unwrapper<int>
{
@@ -166,6 +189,7 @@ struct noddy_int_unwrapper
}
};
// Extract a mutable reference to an int from a Noddy.
struct noddy_int_ref_unwrapper
: boost::python::converter::unwrapper<int&>
{
@@ -180,6 +204,7 @@ struct noddy_int_ref_unwrapper
}
};
// Extract a mutable reference to a simple from a Simple
struct simple_ref_unwrapper
: boost::python::converter::unwrapper<simple&>
{
@@ -194,6 +219,7 @@ struct simple_ref_unwrapper
}
};
// Extract a const reference to a simple from a Simple
struct simple_const_ref_unwrapper
: boost::python::converter::unwrapper<simple const&>
{
@@ -208,11 +234,17 @@ struct simple_const_ref_unwrapper
}
};
//
// Some C++ functions to expose to Python
//
// Returns the length of s's held string
int f(simple const& s)
{
return strlen(s.s);
}
// A trivial passthru function for simple objects
simple const& g(simple const& x)
{
return x;
@@ -222,6 +254,7 @@ BOOST_PYTHON_MODULE_INIT(m1)
{
PyObject* m1 = Py_InitModule(const_cast<char*>("m1"), methods);
// Create the converters; they are self-registering/unregistering.
static int_wrapper wrap_int;
static simple_wrapper wrap_simple;
static native_int_unwrapper unwrap_int1;
@@ -233,32 +266,41 @@ BOOST_PYTHON_MODULE_INIT(m1)
// These compilers will need additional converters
static simple_ref_wrapper wrap_simple_ref;
#endif
// This unwrapper extracts pointers and references to the "complicated" class.
static boost::python::converter::class_unwrapper<complicated> unwrap_complicated;
PyObject* d = PyModule_GetDict(m1);
if (d == NULL)
return;
// Insert the extension metaclass object
if (PyDict_SetItemString(
d, "xclass", (PyObject *)boost::python::object::class_metatype()) < 0)
return;
// Insert the base class for all extension classes
if (PyDict_SetItemString(
d, "xinst", (PyObject *)boost::python::object::class_type()) < 0)
return;
// Expose f()
if (PyDict_SetItemString(
d, "f", boost::python::make_function(f)) < 0)
return;
// Expose g()
if (PyDict_SetItemString(
d, "g", boost::python::make_function(g)) < 0)
return;
// Expose complicated's get_n() member function. See newtest.py
// for how it's used to build an extension class.
if (PyDict_SetItemString(
d, "get_n", boost::python::make_function(&complicated::get_n)) < 0)
return;
// Expose complicated::complicated(simple const&, int) as init1
if (PyDict_SetItemString(
d, "init1"
, boost::python::make_constructor<
@@ -268,6 +310,7 @@ BOOST_PYTHON_MODULE_INIT(m1)
) < 0)
return;
// Expose complicated::complicated(simple const&) as init2
if (PyDict_SetItemString(
d, "init2"
, boost::python::make_constructor<

View File

@@ -4,6 +4,13 @@
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
// This module exercises the converters exposed in m1 at a low level
// by exposing raw Python extension functions that use wrap<> and
// unwrap<> objects.
// Seems to be neccessary to suppress an ICE with MSVC
#include <boost/mpl/comparison/less.hpp>
#include <boost/python/convert.hpp>
#include <boost/python/module.hpp>
#include "simple_type.hpp"
@@ -11,7 +18,10 @@
using boost::python::wrap;
using boost::python::unwrap;
extern "C" {
extern "C"
{
// Get a simple (by value) from the argument, and return the
// string it holds.
PyObject*
unwrap_simple(PyObject* self, PyObject* args)
{
@@ -28,6 +38,8 @@ extern "C" {
return PyString_FromString(x.s);
};
// Likewise, but demands that its possible to get a non-const
// reference to the simple.
PyObject*
unwrap_simple_ref(PyObject* self, PyObject* args)
{
@@ -44,6 +56,7 @@ extern "C" {
return PyString_FromString(x.s);
};
// Likewise, with a const reference to the simple object.
PyObject*
unwrap_simple_const_ref(PyObject* self, PyObject* args)
{
@@ -60,6 +73,8 @@ extern "C" {
return PyString_FromString(x.s);
};
// Get an int (by value) from the argument, and convert it to a
// Python Int.
PyObject*
unwrap_int(PyObject* self, PyObject* args)
{
@@ -76,6 +91,7 @@ extern "C" {
return PyInt_FromLong(x);
};
// Get a non-const reference to an int from the argument
PyObject*
unwrap_int_ref(PyObject* self, PyObject* args)
{
@@ -92,6 +108,7 @@ extern "C" {
return PyInt_FromLong(x);
};
// Get a const reference to an int from the argument.
PyObject*
unwrap_int_const_ref(PyObject* self, PyObject* args)
{
@@ -110,8 +127,12 @@ extern "C" {
// -------------------
}
// MSVC6 bug workaround
template <class T> struct xxxx;
// rewrap<T> extracts a T from the argument, then converts the T back
// to a PyObject* and returns it.
template <class T>
PyObject*
rewrap(PyObject* self, PyObject* args, xxxx<T>* = 0)
@@ -134,6 +155,10 @@ rewrap(PyObject* self, PyObject* args, xxxx<T>* = 0)
extern "C"
{
//
// Use rewrap<T> to test simple, simple&, simple const&, int,
// int&, int const&
//
PyObject*
wrap_simple(PyObject* self, PyObject* args)
{

View File

@@ -59,11 +59,17 @@ try: wrap_int_ref(n)
>>> f(g(s))
12
Create an extension class which wraps "complicated" (init1 and get_n)
are a complicated constructor and member function, respectively.
>>> C = xclass('C', (xinst,), {'__init__': init1, 'get_n': get_n})
>>> c = C(s, 99)
>>> c.get_n()
99
Create another extension class which wraps "complicated" (init2 is a
different constructor -- no overloading yet).
>>> D = xclass('D', (xinst,), {'__init__': init2, 'get_n': get_n})
>>> d = D(s)
>>> d.get_n()