Skip to content Skip to sidebar Skip to footer

Run Python In C++

I have an application written in C++ and a testing system (also in C++). Testing system is pretty complicated and hard to change (I want to make only small changes). My class looks

Solution 1:

I would recommend using Cython for this sort of thing. Adapted examples from another question. (Edit: Upon request, I added an extended example that wraps a C++ class, see further below.)


Edit: Simple example, one way (C++ -> Python).

quacker.py:

defquack():
    print("Quack!")

cquacker.pyx:

from quacker import quack

cdef publicvoidcquack():
    quack()

main.cpp:

#if _WIN32#include<direct.h>#define getcwd _getcwd#define PATH_SEPARATOR ';'#else#include<unistd.h>#define PATH_SEPARATOR ':'#endif#include<iostream>#include<string>#include<sstream>#include<Python.h>#include"cquacker.h"std::wstring getSysPath(){
  char cwd[FILENAME_MAX];
  getcwd(cwd, FILENAME_MAX);
  std::wstringstream path;
  path << Py_GetPath() << PATH_SEPARATOR << cwd;
  return path.str();
}

intmain(){
  Py_Initialize();
  PySys_SetPath(getSysPath().c_str());
  PyInit_cquacker();
  if (PyErr_Occurred())
  {
    PyErr_Print();
    return-1;
  }
  cquack();
  Py_Finalize();
  return0;
}

Edit: Extended example, round trip (C++ -> Python -> C++).

quacker.py:

defqcallback(duck):
    duck.quack()

quacker/Duck.hpp

#include<iostream>namespace quacker {

classDuck
{
public:
    voidquack(){ std::cout << "Quack!" << "\n"; }
};

}

cquacker_defs.pxd:

cdefexternfrom"quacker/Duck.hpp" namespace "quacker":
    cdefcppclass Duck:
        Duck() except +
        void quack()

cquacker.pyx:

from cython.operator cimport dereference as deref
from libcpp.memory cimport shared_ptr

cimport cquacker_defs

from quacker import qcallback

cdefclass Duck:
    cdefshared_ptr[cquacker_defs.Duck] _this

    @staticmethod
    cdefinline Duck _from_this(shared_ptr[cquacker_defs.Duck] _this):
        cdefDuck result = Duck.__new__(Duck)
        result._this = _this
        return result

    def__init__(self):
        self._this.reset(new cquacker_defs.Duck())

    defquack(self):
        assert self._this != NULL
        deref(self._this).quack()


cdefpublic void cqcallback(shared_ptr[cquacker_defs.Duck] duck):
    qcallback(Duck._from_this(duck))

main.cpp:

#if _WIN32#include<direct.h>#define getcwd _getcwd#define PATH_SEPARATOR ';'#else#include<unistd.h>#define PATH_SEPARATOR ':'#endif#include<iostream>#include<memory>#include<string>#include<sstream>#include"quacker/Duck.hpp"#include<Python.h>#include"cquacker.h"std::wstring getSysPath(){
  char cwd[FILENAME_MAX];
  getcwd(cwd, FILENAME_MAX);
  std::wstringstream path;
  path << Py_GetPath() << PATH_SEPARATOR << cwd;
  return path.str();
}

intmain(){
  Py_Initialize();
  PySys_SetPath(getSysPath().c_str());
  PyInit_cquacker();
  if (PyErr_Occurred())
  {
    PyErr_Print();
    return-1;
  }
  auto duck = std::make_shared<quacker::Duck>();
  cqcallback(duck);
  Py_Finalize();
  return0;
}

Post a Comment for "Run Python In C++"