I have been developing some classes to encapsulate the Python API. This
message will contain an example of use. A second message will contain the
main header file. I'm not sending out all the pieces and I don't mean for
anyone to use it yet, as it has not been tested properly. However, I thought
it might be useful to have others see it and comment at this point.
Unlike our previous effort, this work should compile with many compilers (I
used Microsoft Visual C++ so far). While it uses the STL it does not itself
have templated functions or classes. It has an emphasis on safety and
cleanliness rather than speed or cleverness. It has a single inheritance
hierarchy rooted at class Object (in namespace Py). Each Object holds a
PyObject* which it owns a reference to. More specific Objects, such as
Tuple, verify their Tupleness at the moment of creation or assignment. When
something goes wrong, an exception derived from the class PyException is
thrown, thus cleaning up all the Objects in the current scope (and thus
fixing up all the reference counts of the pointers owned by local Objects).
Here is a typical extension file. It has two methods "sum" (sums up the
floating-point arguments) and "test" (which calls a lot of test routines).
Note that any PyExceptions are caught and turned back into Python
exceptions. (Py_Null is just a correctly cast 0)
#include "Python.h"
#include "CXX_Objects.h"
using namespace Py;
static PyObject *
ex_sum(PyObject* self, PyObject* args)
{
Tuple t(args);
Float f, g;
int i;
f = 0.0;
try {
for(i = 0; i < t.length(); i++)
g = t[i];
f = f + g;
}
return new_reference_to(f);
}
catch(const PyException&) {
return Py_Null;
}
}
static String
test_String() {
String s("hello");
String t("world in brief", 6);
s += " ";
t *= 2;
s += t;
return s;
}
static Object
test_numbers() {
// test the basic numerical classes
List result;
Int i;
Int j(2);
Int k = Int(3);
i = j + k + 1;
Float a;
a = 3 + i;
Float b(3.0);
result.append(i);
result.append(1.0 + 2*a + (b*3.0)/2.0 + k/Float(i) + 2);
Float c;
c = k;
result.append(c);
return result;
}
static List
test_List() {
// test the List class
List a;
Object b(Py_None);
Int i(3);
Float x(6.0);
Float c(10.0), d(20.0);
a.append(i);
a.append(x);
a.append(Float(0.0));
b = a[0];
a[2] = b;
a.append(c+d);
a.append(a.getSlice(0,2));
return a;
}
static Dict
test_Dict() {
// test the Dict class
Dict a;
String s("ho");
a["hi"] = s;
a["h"] = s[0];
Dict b;
List v;
b["key 1"] = s;
b["key 2"] = Float(2.0);
v = b.values();
a["bkeys"] = b.keys();
a["bvalues"] = v;
b.clear();
if(b.keys().length() != 0) {
throw PyException_RuntimeError("dict clear failed");
}
return a;
}
static Tuple
test_Tuple() {
// test the Tuple class
Tuple a(3);
Tuple t1;
Float f1(1.0), f2(2.0), f3(3.0);
a[0] = f1; // should be ok since no other reference owned
a[1] = f2;
a[2] = f3;
Tuple b(a);
t1 = a;
try {
t1[0] = Int(1); // should fail
}
catch (const PyException& e) {
e.clear();
cout << "OK, incorrect tuple assignment prevented\n";
}
return Tuple(*(b.repeat(2)));
}
static PyObject*
ex_test (PyObject* self, PyObject* args)
{
try {
cout << "Numbers: " << test_numbers() << "\n";
cout << "String: " << test_String() << "\n";
cout << "List: " << test_List() << "\n";
cout << "Dict: " << test_Dict() << "\n";
Tuple t(args);
List a(t);
Tuple c(a);
cout << "List from tuple: " << a << "\n";
cout << "Tuple from list: " << c << "\n";
pair<Object,Object> result = coerce(Float(1.0), Int(2));
cout << "Result of coerce: " << result.first << ", " <<
result.second << "\n";
cout << "Result of +: " << Float(1.0) + Int(2) << "\n";
cout << "Result of -: " << Float(1.0) - Int(2) << "\n";
cout << "Result of *: " << Float(1.0) * Int(2) << "\n";
cout << "Result of /: " << Float(1.0) / Int(2) << "\n";
cout << "Result of 7 % 2: " << (Int(7) % Int(2)) << "\n";
cout << "Result of -7: " << -Int(7) << "\n";
cout << "Result of +7: " << +Int(7) << "\n";
cout << "Result of abs(-7): " << abs(Int(-7)) << "\n";
return Nothing;
}
catch (const PyException&) {
return Py_Null;
}
}
static PyMethodDef example_methods[] = {
{"sum", ex_sum, 1, "sum(arglist)"},
{"test", ex_test, 1, "test(arglist)"},
{NULL, NULL}
};
extern "C" {
void
initexample()
{
Py_InitModule("example", example_methods);
}
}
_______________
C++-SIG - SIG for Development of a C++ Binding to Python
send messages to: c++-sig(a)python.org
administrivia to: c++-sig-request(a)python.org
_______________