[C++-SIG] Python calling C++ issues

Adrian Eyre a.eyre at optichrome.com
Wed Dec 1 14:12:05 CET 1999


> Unfortunately, as of this moment, we have not yet successfully run our
> simple spam program.

You give up too easily... :)

Assuming you haven't changed the source from the original post:

The problem lies in the differences between Python extension modules and
Python extension types. You have written an extension module, but are
returning the values as if it were a type.

Here's how to fix it:

1. The file c_spam.cpp is pointless, so get rid of it.

2. In ext_spam.cxx:

static PyObject*
ext_new_Spam(PyObject* self, PyObject* args)
{
	int a, b;

	if (!PyArg_ParseTuple(args, "ii", &a, &b))
		return NULL;

	Spam* spam = new_Spam(a, b);

	return Py_BuildValue("O", spam);
}

'Spam' is a C++ object, not a python object, and you can't just cast it
to a PyObject* and expect it to work. One way to do this is to pass back
a pointer to the object as a long:

static PyObject*
ext_new_Spam(PyObject* self, PyObject* args)
{
	int a, b;

	if (!PyArg_ParseTuple(args, "ii", &a, &b))
		return NULL;

	Spam* spam = new Spam(a, b);
	return Py_BuildValue("l", (long) spam); // Or return PyInt_FromLong((long)
spam);
}

The Python script now stores this as a Python integer object.

3. In all other functions in ext_spam.cxx:

e.g.

static PyObject*
ext_Spam_Display(PyObject* self, PyObject* args)
{

	Spam* spam;

	if (!PyArg_ParseTuple(args, "O", &spam))
		return NULL;

	Spam_Display(spam);

	return Py_BuildValue("");
}

Use:

static PyObject*
ext_Spam_Display(PyObject* self, PyObject* args)
{
	Spam* spam;

	if (!PyArg_ParseTuple(args, "l", &spam))
		return NULL;

	Spam_Display(spam);

	Py_INCREF(Py_None);	// Use these lines when you don't
	return Py_None;		// want to return a value
}

That should just about fix it.

A couple of other things:

o If you don't already have Mark Lutz's book "Programming Python",
  get yourself a copy, and have a look through the chapters on
  embedding and extending Python.

o If you want a better response, try posting to the main Python
  mailing list, not the C++ binding one. This list is more to
  do with the procedures for automating the process of creating
  Python objects which mirror C++ objects.

o There are ways to do this sort of thing in a much more groovy way.
  Judging by the test script:

#!/usr/bin/python

import c_spam

myspam=c_spam.new_Spam(8, 5)
c_spam.Spam_Display(myspam)
c_spam.delete_Spam(myspam)

print "python end"


...you are using it like a module, not a type. There are ways to get
Python to make your Spam object usable like this:

import c_spam
myspam = c_spam.Spam(8, 5)
myspam.Display()
del myspam

I don't really want to give too much away, then you'll never learn
how to do things yourself, but if you need any more assistance, don't
hesistate to mail back.

Good luck.

--------------------------------------------
Adrian Eyre <mailto:a.eyre at optichrome.com>
Optichrome Computer Solutions Ltd
Maybury Road, Woking, Surrey, GU21 5HX, UK
Tel: +44 1483 740 233  Fax: +44 1483 760 644
http://www.optichrome.com
--------------------------------------------





More information about the Cplusplus-sig mailing list