Skip to main content

Command Palette

Search for a command to run...

Connecting C++ to Python using Boost.Python...

Updated
3 min read
S
In search of WhoAmI...

Gyan.... Knowledge...Wisdom... my wife Reema reciting her own poem...

Many modern C++ applications provide a Python interface because it combines performance (C++) with ease of use (Python). Here’s why this trend has become so popular:

✔ It allows rapid prototyping.
✔ It combines speed (C++) with flexibility (Python).
✔ Python is popular in AI, ML, and scientific computing.
✔ Users can extend software via Python scripting.

Boost.Python is a powerful library that enables seamless integration between C++ and Python. It allows C++ functions and classes to be exposed to Python, enabling direct interaction between the two languages.

As I was playing around with Boost.Python, I made my existing Factory Pattern project written in C++ to expose itself to the python using Boost.Python library.

The most important part is the following lines of code. This is kind of self explanatory - how we expose the C++ classes and methods to Python code.

// Expose Singleton Factory to Python
BOOST_PYTHON_MODULE(FactoryPattern) {
    using namespace boost::python;

    class_<Food, boost::noncopyable>("Food", no_init)
        .def("getName", pure_virtual(&Food::getName));

    class_<Biscuit, bases<Food>>("Biscuit")
        .def("getName", &Biscuit::getName); // Ensure Biscuit has getName

    class_<Chocolate, bases<Food>>("Chocolate")
        .def("getName", &Chocolate::getName); // Ensure Chocolate has getName

    class_<Factory, boost::noncopyable>("Factory", no_init)
        .def("getInstance", &Factory::getInstance, return_value_policy<reference_existing_object>())
        .staticmethod("getInstance")
        .def("makeFood", &Factory::makeFood, return_value_policy<manage_new_object>());
}

Here's the complete source code of the C++ Factory Pattern... We will have to make a shared object (so) from this C++ project.

/*
 * Food.h
 *
 * Created on: Mar 10, 2021
 * Author: som
 */

#ifndef FOOD_H_
#define FOOD_H_

#include <string>

using namespace std;

class Food {
public:
    virtual string getName() = 0;
    virtual ~Food() {}
};

#endif // FOOD_H_
/*
 * Chocolate.h
 *
 * Created on: Mar 10, 2021
 * Author: som
 */

#ifndef CHOCOLATE_H_
#define CHOCOLATE_H_

#include <iostream>
#include "Food.h"

class Chocolate : public Food {
public:
    Chocolate();
    virtual ~Chocolate();
    std::string getName();
};

#endif /* CHOCOLATE_H_ */
/*
 * Chocolate.cpp
 *
 * Created on: Mar 10, 2021
 * Author: som
 */

#include "Chocolate.h"

Chocolate::Chocolate() {
    // TODO Auto-generated constructor stub
    cout << "Chocolate is made..." << endl;
}

Chocolate::~Chocolate() {
    // TODO Auto-generated destructor stub
}

string Chocolate::getName() {
    return "It's a Chocolate";
}
/*
 * Biscuit.h
 *
 * Created on: Mar 10, 2021
 * Author: som
 */

#ifndef BISCUIT_H_
#define BISCUIT_H_

#include "Food.h"

class Biscuit : public Food {
public:
    Biscuit();
    string getName();
    ~Biscuit();
};

#endif /* BISCUIT_H_ */
/*
 * Biscuit.cpp
 *
 * Created on: Mar 10, 2021
 * Author: som
 */

#include <iostream>
#include "Biscuit.h"

using namespace std;

Biscuit::Biscuit() {
    // TODO Auto-generated constructor stub
    cout << "Biscuit is made..." << endl;
}

Biscuit::~Biscuit() {}

string Biscuit::getName() {
    return "It's a Biscuit";
}
/*
 * Factory.h
 * Created on: Mar 10, 2021
 * Author: som
 */

#ifndef FACTORY_H_
#define FACTORY_H_

#include <boost/python.hpp>
#include <iostream>
#include <string>
#include "Biscuit.h"
#include "Chocolate.h"

using namespace std;

class Factory {
public:
    static Factory* instance;
    static Factory* getInstance();
    Food* makeFood(const string& type);

private:
    Factory() {}

    // Delete copy constructor & assignment operator (Singleton pattern)
    Factory(const Factory&) = delete;
    Factory& operator=(const Factory&) = delete;
};

#endif /* FACTORY_H_ */
/*
 * Factory.cpp
 *
 * Created on: Jan 30, 2025
 * Author: som
 */

#include "Factory.h"

Factory* Factory::instance = NULL;

Factory* Factory::getInstance() {
    if (Factory::instance == NULL) {
        Factory::instance = new Factory();
    }
    return Factory::instance;
}

Food* Factory::makeFood(const string& type) {
    if (type.compare("bi") == 0) {
        return new Biscuit();
    }
    if (type.compare("ch") == 0) {
        return new Chocolate();
    }
    return NULL;
}

// Expose Singleton Factory to Python
BOOST_PYTHON_MODULE(FactoryPattern) {
    using namespace boost::python;

    class_<Food, boost::noncopyable>("Food", no_init)
        .def("getName", pure_virtual(&Food::getName));

    class_<Biscuit, bases<Food>>("Biscuit")
        .def("getName", &Biscuit::getName); // Ensure Biscuit has getName

    class_<Chocolate, bases<Food>>("Chocolate")
        .def("getName", &Chocolate::getName); // Ensure Chocolate has getName

    class_<Factory, boost::noncopyable>("Factory", no_init)
        .def("getInstance", &Factory::getInstance, return_value_policy<reference_existing_object>())
        .staticmethod("getInstance")
        .def("makeFood", &Factory::makeFood, return_value_policy<manage_new_object>());
}

And here's the python script to access the C++ methods.

import FactoryPattern

factory = FactoryPattern.Factory.getInstance()

biscuit = factory.makeFood("bi")
print(biscuit.getName())  # Expected: "Biscuit"
chocolate = factory.makeFood("ch")
print(chocolate.getName())  # Expected: "Chocolate"

Jai Hind... Jai Bharat...

More from this blog

Som's Tech World...

149 posts

I am in search of WhoAmI. This is my own world of technologies and software. I believe in the following simple fact of life... To win is no more than this... To rise each time you fall...