Mannaggia
Mannaggia

Reputation: 4819

How to wrap a python class into a C++ class?

I have a python class which implements a given functionality, eg the file Test_script.py is:

class Test(object):
    def __init__(self,name):
        self.name=name
    def f1(self,n):
        return n**2
    def f2(self,n,m):
        return n+m
    def f3(self,word):
        print word

How can I build a C++ class which simply wraps this class and all the functions so that this class can in turn by used by other C++ classes/code? Is boost::python helpful in providing some shortcuts?

Why is this relevant? Because there can be concrete use cases for which it is much faster and easier to implement a given functionality in python since lots of well tested and documented modules can be reused (e.g. parsing, numpy functions, ...) rather than doing it from scratch in C++. The above class is a toy problem, once it is clear how to wrap/embed this in C++ it will be easy to deal with more complex functionality.

Thx

Upvotes: 3

Views: 2707

Answers (1)

moooeeeep
moooeeeep

Reputation: 32512

Have you looked up the docs on embedding Python functionality in C++ applications? Take note of the Boost.Python Interface, but also and especially of the Python Interpreter C API. (Boost.Python puts more focus on writing Python extensions in C++ rather than the other way around.)

For reference:

Also have a look at my answer here for a simple application of the C API (to use matplotlib from a C application):

Here's another simple example how the C API could be used to import Python modules and execute their functions from within a C++ application. For the details please refer to the documentation.

#include <Python.h>
#include <boost/algorithm/string/join.hpp>
#include <vector>
#include <string>
#include <iostream>

int main(int argc, const char** argv) {
    // get data to hash
    if (argc < 2) {
        std::cout << "please add some command line args\n";
        return -1;
    }
    std::string data = boost::algorithm::join(
            std::vector<std::string>(argv+1, argv+argc), " ");
    std::cout << "compute md5 of string: '" << data << "'\n";
    // initialize Python API
    Py_Initialize();
    // import hashlib module
    PyObject *pHashlib = PyImport_ImportModule("hashlib");
    // get hash function
    PyObject *pHashlibMd5 = PyObject_GetAttrString(pHashlib, "md5");
    // build function argument tuple
    PyObject *pFuncParams = PyTuple_New(1);
    PyTuple_SetItem(pFuncParams, 0, PyString_FromString(data.c_str()));
    // call function
    PyObject *pMd5 = PyObject_CallObject(pHashlibMd5, pFuncParams);
    // get function to retrieve hex digest
    PyObject *pMd5Hexdigest = PyObject_GetAttrString(pMd5, "hexdigest");
    // call function
    PyObject *pRet = PyObject_CallObject(pMd5Hexdigest, 0);
    // print result
    std::cout << PyString_AsString(pRet) << "\n";
    // deinitialize
    Py_DECREF(pRet);
    Py_DECREF(pMd5Hexdigest);
    Py_DECREF(pMd5);
    Py_DECREF(pFuncParams);
    Py_DECREF(pHashlibMd5);
    Py_DECREF(pHashlib);
    Py_Finalize();
}

Build and run:

$ g++ test.cc -I /usr/include/python2.7 -l python2.7
$ ./a.out Hello World
compute md5 of string: 'Hello World'
b10a8db164e0754105b7a99be72e3fe5

For comparison:

>>> import hashlib
>>> print hashlib.md5('Hello World').hexdigest()
b10a8db164e0754105b7a99be72e3fe5

Hope this helps.

Upvotes: 5

Related Questions