在c++中运行python

Run python in C++

本文关键字:python 运行 c++      更新时间:2023-10-16

我有一个用c++编写的应用程序和一个测试系统(也是用c++)。测试系统非常复杂,很难改变(我只想做小的改变)。我的类是这样的:

class Derived : public Base {
public:
    void somefunc(const AnotherClass& file) {
}
};

里面有几个函数。我的测试系统创建了派生类实例,然后使用它的方法来做一些事情。

现在我想用Python写一个解决方案。我需要一个双向积分。我的想法是写一个Python函数,每次调用somefunc时都会执行这个函数。我不想在Python中从一个函数启动到另一个函数启动时丢失变量的值。我还希望能够使用在python的基类实例中定义的方法。我怎样才能实现这些目标?

我选择Boost。Python用于这些目的。现在,我明白了,如何使用c++函数,甚至简单的类在Python经过一些工作。但是我不明白如何从c++中启动Python函数。

第二个问题-是Boost。Python是一个好的选择?我需要一种速度快,同时又好用的软件。

谢谢你的帮助。

我建议使用Cython来做这类事情。改编自另一个问题的例子。(Edit:根据要求,我添加了一个扩展的示例,该示例包装了一个c++类,见下文。)


编辑: 简单的例子,一个方法(C + + -> Python)。

quacker.py:

def quack():
    print("Quack!")

cquacker.pyx:

from quacker import quack
cdef public void cquack():
    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();
}
int main()
{
  Py_Initialize();
  PySys_SetPath(getSysPath().c_str());
  PyInit_cquacker();
  if (PyErr_Occurred())
  {
    PyErr_Print();
    return -1;
  }
  cquack();
  Py_Finalize();
  return 0;
}

编辑:扩展示例,往返(c++ -> Python -> c++)。

quacker.py:

def qcallback(duck):
    duck.quack()

鸭子/Duck.hpp

#include <iostream>
namespace quacker {
class Duck
{
public:
    void quack() { std::cout << "Quack!" << "n"; }
};
}

cquacker_defs.pxd:

cdef extern from "quacker/Duck.hpp" namespace "quacker":
    cdef cppclass 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
cdef class Duck:
    cdef shared_ptr[cquacker_defs.Duck] _this
    @staticmethod
    cdef inline Duck _from_this(shared_ptr[cquacker_defs.Duck] _this):
        cdef Duck result = Duck.__new__(Duck)
        result._this = _this
        return result
    def __init__(self):
        self._this.reset(new cquacker_defs.Duck())
    def quack(self):
        assert self._this != NULL
        deref(self._this).quack()

cdef public 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();
}
int main()
{
  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();
  return 0;
}