1

简洁版本

我不明白如何可靠地初始化 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();

whereFactorialTableCalculator是一个本地函数,它只返回适当的向量。[operator()对于二项式等,这些变得更加复杂,这就是我使用类来包装这些东西的原因。]

我使用 SWIG 来包装c++代码,并从 python 中使用它。这一切都很顺利,直到我在我正在使用的新集群​​上编译了我的代码。现在我想我以前只是运气好。

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

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

如果你真的有动力,你可以在这里这里浏览代码,以及在这里给出段错误的那一行。

4

1 回答 1

2

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

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

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

这样,您可以强制执行时间的顺序(通过按需要的顺序调用函数)。

于 2014-04-20T05:43:05.113 回答