mirror of
https://github.com/boostorg/python.git
synced 2026-01-23 05:42:30 +00:00
added first virtual function tests
[SVN r13183]
This commit is contained in:
118
test/virtual_functions.cpp
Normal file
118
test/virtual_functions.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#include <boost/python/class.hpp>
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/returning.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
struct X
|
||||
{
|
||||
explicit X(int x) : x(x), magic(7654321) { ++counter; }
|
||||
X(X const& rhs) : x(rhs.x), magic(7654321) { ++counter; }
|
||||
virtual ~X() { assert(magic == 7654321); magic = 6666666; x = 9999; --counter; }
|
||||
|
||||
void set(int x) { assert(magic == 7654321); this->x = x; }
|
||||
int value() const { assert(magic == 7654321); return x; }
|
||||
static int count() { return counter; }
|
||||
private:
|
||||
void operator=(X const&);
|
||||
private:
|
||||
int x;
|
||||
long magic;
|
||||
static int counter;
|
||||
};
|
||||
|
||||
struct Y : X
|
||||
{
|
||||
Y(int x) : X(x) {};
|
||||
};
|
||||
|
||||
struct abstract : X
|
||||
{
|
||||
abstract(int x) : X(x) {};
|
||||
int call_f(Y const& y) { return f(y); }
|
||||
virtual int f(Y const& y) = 0;
|
||||
};
|
||||
|
||||
struct concrete : X
|
||||
{
|
||||
concrete(int x) : X(x) {};
|
||||
int call_f(Y const& y) { return f(y); }
|
||||
virtual int f(Y const& y) { set(y.value()); return y.value(); }
|
||||
};
|
||||
|
||||
struct abstract_callback : abstract
|
||||
{
|
||||
abstract_callback(PyObject* p, int x)
|
||||
: abstract(x), self(p)
|
||||
{}
|
||||
|
||||
int f(Y const& y)
|
||||
{
|
||||
return returning<int>::call_method(self, "f", boost::ref(y));
|
||||
}
|
||||
|
||||
PyObject* self;
|
||||
};
|
||||
|
||||
struct concrete_callback : concrete
|
||||
{
|
||||
concrete_callback(PyObject* p, int x)
|
||||
: concrete(x), self(p)
|
||||
{}
|
||||
|
||||
int f(Y const& y)
|
||||
{
|
||||
return returning<int>::call_method(self, "f", boost::ref(y));
|
||||
}
|
||||
|
||||
int f_impl(Y const& y)
|
||||
{
|
||||
return this->concrete::f(y);
|
||||
}
|
||||
|
||||
PyObject* self;
|
||||
};
|
||||
|
||||
int X::counter;
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(virtual_functions_ext)
|
||||
{
|
||||
module("virtual_functions_ext")
|
||||
.add(
|
||||
class_<concrete, bases<>, objects::value_holder_generator<concrete_callback> >("concrete")
|
||||
.def_init(args<int>())
|
||||
.def("value", &concrete::value)
|
||||
.def("set", &concrete::set)
|
||||
.def("call_f", &concrete::call_f)
|
||||
.def("f", &concrete_callback::f_impl))
|
||||
|
||||
#if 0
|
||||
.add(
|
||||
class_<abstract, bases<>
|
||||
, objects::pointer_holder_generator<
|
||||
boost::python::objects::shared_ptr_generator
|
||||
, abstract_callback>
|
||||
>("abstract")
|
||||
|
||||
.def_init(args<int>())
|
||||
.def("value", &abstract::value)
|
||||
.def("call_f", &abstract::call_f)
|
||||
.def("set", &abstract::set))
|
||||
#endif
|
||||
|
||||
.add(
|
||||
class_<Y>("Y")
|
||||
.def_init(args<int>())
|
||||
.def("value", &Y::value)
|
||||
.def("set", &Y::set)
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
#include "module_tail.cpp"
|
||||
100
test/virtual_functions.py
Normal file
100
test/virtual_functions.py
Normal file
@@ -0,0 +1,100 @@
|
||||
'''
|
||||
>>> from virtual_functions_ext import *
|
||||
|
||||
>>> class C1(concrete):
|
||||
... def f(self, y):
|
||||
... return concrete.f(self, Y(-y.value()))
|
||||
|
||||
>>> class C2(concrete):
|
||||
... pass
|
||||
|
||||
<<<>>> class A1(abstract):
|
||||
<<<... def f(self, y):
|
||||
<<<... return abstract.f(self, Y(-y.value()))
|
||||
<<<
|
||||
<<<>>> class A2(abstract):
|
||||
<<<... pass
|
||||
<<<
|
||||
|
||||
>>> y1 = Y(16)
|
||||
>>> y2 = Y(17)
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Test abstract with f overridden
|
||||
#
|
||||
<<<>>> a1 = A1(42)
|
||||
<<<>>> a1.value()
|
||||
<<<42
|
||||
<<<
|
||||
<<<# Call f indirectly from C++
|
||||
<<<>>> a1.call_f(y1)
|
||||
<<<-16
|
||||
<<<
|
||||
<<<# Call f directly from Python
|
||||
<<<>>> a1.f(y2)
|
||||
<<<-17
|
||||
<<<
|
||||
<<<#
|
||||
<<<# Test abstract with f not overridden
|
||||
<<<#
|
||||
<<<>>> a2 = A2(42)
|
||||
<<<>>> A2.value()
|
||||
<<<42
|
||||
<<<
|
||||
<<<# Call f indirectly from C++
|
||||
<<<>>> c1.call_f(y1)
|
||||
<<<16
|
||||
<<<
|
||||
<<<# Call f directly from Python
|
||||
<<<>>> c1.f(y2)
|
||||
<<<17
|
||||
<<<
|
||||
############# Concrete Tests ############
|
||||
|
||||
#
|
||||
# Test concrete with f overridden
|
||||
#
|
||||
>>> c1 = C1(42)
|
||||
>>> c1.value()
|
||||
42
|
||||
|
||||
# Call f indirectly from C++
|
||||
>>> c1.call_f(y1)
|
||||
-16
|
||||
|
||||
# Call f directly from Python
|
||||
>>> c1.f(y2)
|
||||
-17
|
||||
|
||||
#
|
||||
# Test concrete with f not overridden
|
||||
#
|
||||
>>> c2 = C2(42)
|
||||
>>> c2.value()
|
||||
42
|
||||
|
||||
# Call f indirectly from C++
|
||||
>>> c2.call_f(y1)
|
||||
16
|
||||
|
||||
# Call f directly from Python
|
||||
>>> c2.f(y2)
|
||||
17
|
||||
|
||||
|
||||
'''
|
||||
|
||||
def run(args = None):
|
||||
import sys
|
||||
import doctest
|
||||
|
||||
if args is not None:
|
||||
sys.argv = args
|
||||
return doctest.testmod(sys.modules.get(__name__))
|
||||
|
||||
if __name__ == '__main__':
|
||||
print "running..."
|
||||
import sys
|
||||
sys.exit(run()[0])
|
||||
Reference in New Issue
Block a user