3

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

Mannaggia
  • 4,559
  • 12
  • 34
  • 47
  • why are you doing this? this does not seem like the "correct" solution to whatever the issue is ... normally this type of thing is to expose C/C++ to python not vice versa ...(in fact that might be what you want is to expose C/C++ functionality to python that python can than pass an instance of test to. – Joran Beasley Dec 17 '13 at 20:10
  • These near trivial functions could easily be implemented in C++. Is it really that simple? – moooeeeep Dec 17 '13 at 20:12
  • @JoranBeasley: it turned out that there is some functionality which I can implement much easier in python, using all the types and modules of this language, e.g. parsing,...So I think there are use cases where you just want to do something in python for convenience – Mannaggia Dec 17 '13 at 20:13
  • 1
    @moooeeeep: this is to make the example easy, the real case would be very hard to implement in C++ because I use a lot of python functions and data structures – Mannaggia Dec 17 '13 at 20:14
  • then do it in python ;P (almost everything can be done easier with less code, if thats what your looking for) ... I think the closest you will find is something like `system("python my_script.py some arguments")` and then check the string output ... (I think there are some python to C++ compilers that work with a limited subset of the language that you may be able to export a dll or something ...) – Joran Beasley Dec 17 '13 at 20:18
  • 1
    this thread may be of interest to you http://stackoverflow.com/questions/4650243/convert-python-program-to-c-c-code – Joran Beasley Dec 17 '13 at 20:23

1 Answers1

5

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.

Community
  • 1
  • 1
moooeeeep
  • 31,622
  • 22
  • 98
  • 187
  • yes thanks, I saw these links, I did not find these explanations so useful. I was hoping to find a concrete example about wrapping a class, the boost doc is always rather minimalistic. I find it strange that there are lots of examples on extending python with C++ but the opposite is quite rare – Mannaggia Dec 17 '13 at 20:31
  • @Mannaggia This imbalance is probably because the one approach is just more common: _"The best approach is often to write only the performance-critical parts of the application in C++ or Java, and use Python for all higher-level control and customization."_ (http://www.python.org/doc/essays/omg-darpa-mcc-position.html) – moooeeeep Dec 17 '13 at 22:13
  • yes, that's the way to go, classes in C++ are just objects and their methods can be accessed with PyObject_GetAttrString and PyObject_CallObject can be used to call the constructor on the class or other functions of the class – Mannaggia Dec 18 '13 at 22:23