Search code examples
c++pythonpython-c-api

C++ Python import class; call methods


I am using Python 2.7. It is not clear to me how to embed Python inside C++ as found here: http://docs.python.org/2.7/extending/embedding.html.

I have a simple python example here in a file named test.py:

class math:
    #def __init__(self):
    def add(self, num1, num2):
        return num1 + num2

    def subtract(self, num1, num2):
        return num1 - num2

From python, I would do something like this:

>>> from test import math
>>> m = math()
>>> a = m.add(1, 2)
>>> s = m.subtract(1, 2)

I have the beginning of some C++ code to do this:

PyObject *pName, *pModule;
Py_Initialize();
pName = PyString_FromString("test");
pModule = PyImport_Import(pName);

That seems to work just fine. But, that seems to be the equivalent of doing this in Python:

import test

How do I import the Python class math?

Thanks


Solution

  • Here's a quick n' dirty example in C which does the equivalent of...

    >>> import mymath
    >>> m = mymath.math()
    >>> print '1 + 2 = %d' % m.add(1, 2)
    

    Note that I've renamed the module from test to mymath because there's a module called test in the standard Python library.

    #include <stdio.h>
    #include <stdlib.h>
    #include <assert.h>
    #include <python2.7/Python.h>
    
    int main()
    {
        setenv("PYTHONPATH", ".", 1);
    
        Py_Initialize();
    
        PyObject* module = PyImport_ImportModule("mymath");
        assert(module != NULL);
    
        PyObject* klass = PyObject_GetAttrString(module, "math");
        assert(klass != NULL);
    
        PyObject* instance = PyInstance_New(klass, NULL, NULL);
        assert(instance != NULL);
    
        PyObject* result = PyObject_CallMethod(instance, "add", "(ii)", 1, 2);
        assert(result != NULL);
    
        printf("1 + 2 = %ld\n", PyInt_AsLong(result));
    
        Py_Finalize();
    
        return 0;
    }
    

    ...which outputs...

    $ gcc foo.c -lpython2.7 && ./a.out
    1 + 2 = 3
    

    However, if you do any major amount of work with the Python/C API between Py_Initialize and Py_Finalize, you'll have to watch your reference counts, and use Py_INCREF and Py_DECREF when appropriate.