通过Python将C++对象传递给C++代码?

6 投票
1 回答
868 浏览
提问于 2025-04-15 22:28

我写了一些物理模拟的代码,使用的是C++,但是解析输入的文本文件成了一个瓶颈。作为输入参数之一,用户需要指定一个数学函数,这个函数在运行时会被多次计算。C++代码里有一些预定义的函数类(这些在数学上其实挺复杂的),还有一些有限的解析能力,但我对这个结构并不满意。

我需要的是算法和函数的计算都要快速,所以把它们都保持为编译后的代码是有好处的(最好是把数学函数做成C++的函数对象)。不过我想到了用Python把整个模拟过程连接起来:用户可以在Python脚本中指定输入参数,同时也可以用Python来实现结果的存储、可视化(用matplotlib)和图形界面。

我知道大多数情况下,可以通过SWIG等工具把C++类暴露出来,但我还有一个问题,关于如何在Python中解析用户定义的数学函数:

有没有办法在Python中构建一个C++函数对象,并把它传递给C++算法?比如,当我在Python中调用

f = WrappedCPPGaussianFunctionClass(sigma=0.5)
WrappedCPPAlgorithm(f)

时,它会返回一个指向C++对象的指针,然后这个指针可以传递给需要这样的指针的C++例程,或者类似的东西……(不过关于内存管理的问题就别问我了 :S)

关键是算法中不应该有任何对Python代码的回调。之后我想扩展这个例子,在Python端做一些简单的表达式解析,比如函数的和或积,并返回一些复合的、像解析树的C++对象,但现在先从基础开始。

抱歉发了这么长的帖子,提前感谢大家的建议。

1 个回答

3

我经常做类似的事情。最简单的解决办法,也是我通常选择的方式,因为说实话,我比较懒,就是把你的API简化成类似C语言的API,然后在Python(或者你喜欢的其他语言)之间传递指针。

首先,创建你的类。

class MyFunctionClass
{
  public:
    MyFunctionClass(int Param)
    ...
};

class MyAlgorithmClass
{
  public:
    MyAlgorithmClass(myfunctionclass& Func)
    ...
};

然后,创建一组C风格的函数,用来创建和销毁这些类。我通常会把它们简化成传递void*,因为我用的语言本来就不太注重类型安全。这样做更简单。只要在实际使用void*之前,确保把它转换回正确的类型就可以了。

    void* CreateFunction(int Param)
    {
      return new MyFunctionClass(Param);
    }

    void DeleteFunction(void* pFunc)
    {
        if (pFunc)
            delete (MyFunctionClass*)pFunc;
    }

    void* CreateAlgorithm(void* pFunc)
    {
      return new MyAlgorithmClass(*(MyFunctionClass*)pFunc)
    }

    void DelteAlgorithm(void* pAlg)
    {
       if (pAlg)
           delete (MyAlgorithmClass*)pAlg;
    }

现在你只需要让Python调用这些C风格的函数。实际上,它们可以(而且应该)是extern "c"的函数,这样链接起来会更简单。

撰写回答