python扩展模块中的C ++静态成员初始化

时间:2014-04-20 03:34:41

标签: python c++ swig python-extensions

短版

我不明白如何可靠地初始化python扩展的静态成员。特别是,如何确保来自不同编译单元的代码的特定加载顺序,以便满足某些依赖性?

长版

我有一些代码可以多次计算各种组合函数,比如阶乘,二项式等。只为这些事物构造一次表,然后对它们进行查找,效率要高得多。我需要一个很好的接口来获取值,所以我只创建c ++类,将表作为静态成员。

作为最简单的例子,为了计算阶乘,我有以下几点。在Combinatorics.hpp

  class FactorialFunctor {
  private:
    static const std::vector<double> FactorialTable;
  public:
    FactorialFunctor() { };
    inline double operator()(const unsigned int i) const {
      return FactorialTable[i];
    }
  };

Combinatorics.cpp

const std::vector<double> FactorialFunctor::FactorialTable = FactorialTableCalculator();

其中FactorialTableCalculator是一个只返回适当向量的局部函数。 [那些operator()对于二项式等更复杂,这就是我使用类来包装这些东西的原因。]

我使用SWIG来包装c++代码,并从python中使用它。直到我在我正在使用的新集群​​上编译代码之前,这一切都进展顺利。现在我觉得我以前刚刚幸运。

一旦我在新集群上导入我的python模块,python就会发生段错误。 Python甚至没有从导入步骤中恢复过来。使用gdb,我将其跟踪到代码的另一部分,其初始化调用Factorial仿函数。但是FactorialTable还没有被初始化,所以整个事情都嘶哑了。

所以我需要确保在计算其他代码之前计算我的阶乘。我按照理想的顺序告诉distutils,但显然这不是他们在这个集群上调用的顺序。在链接过程中是否有一些我需要小心的事情?

如果您真的有动力,可以浏览代码herehere,以及提供段错误here的行。

1 个答案:

答案 0 :(得分:2)

没有可靠的方法来强制静态成员的初始化顺序。

查看代码但我认为您需要的不是静态成员而不是单例。 C ++中的单例通常使用如下函数实现:

FactorialFunctorData& _FactorialFunctorData()
{
    static FactorialFunctorData data_;
    return data_;
}

通过这种方式,您可以强制执行时间(通过按所需顺序调用函数)。