2014-05-06 23 views
1

我有一個C++類的靜態含有某種(在這種特殊情況下「m_engine」)「靜態」:C++中的Boost.Python

class RndGenerator 
{ 
public: 
    static void setInitialSeed(unsigned int seed); 
    static unsigned int rndNumber(); 
    ... 
private: 
    ... 
    RndGenerator(); 
    static std::mt19937 m_engine; 
}; 

這個類是在我的項目中廣泛使用,對C++級別。

通過Boost.Python的暴露RndGenerator後:

class_<RndGenerator, boost::noncopyable>("RndGenerator", no_init) 
    .def("setInitialSeed", &RndGenerator::setInitialSeed) 
    .staticmethod("setInitialSeed") 
    .def("rndNumber", &RndGenerator::rndNumber) 
    .staticmethod("rndNumber") 
    ; 

我想有可能從Python的級別設置的初始種子:

RndGenerator.setInitialSeed(1234) 

我所期望的,這條線後,所有通話到RndGenerator :: rndNumber(),在C++級別,將考慮到剛纔指定的初始種子(1234)。 但事實並非如此。

包含暴露給Python的靜態成員的類有任何問題嗎? 或者我的問題涉及到RndGenerator的單態性質?

回答

2

在使用靜態數據成員或靜態成員函數公開C++類時,Boost.Python應該沒有問題。這是否可能是假陽性?或者,對於其中相同模板以多個翻譯單元實例化的更復雜和特定情況,則對於動態庫,具有相同符號名稱的靜態數據成員的多個實例可駐留在同一個進程空間內。

無論如何,這裏是一個完整的例子展示的靜態成員函數和靜態數據成員與Boost.Python的露出的類預期的行爲:

#include <boost/python.hpp> 

// Basic mockup type. 
class spam 
{ 
public: 
    static void set_x(unsigned int x) { x_ = x; } 
    static unsigned int get_x() { return x_; }; 
private: 
    spam() {}; 
    spam(const spam&); 
    spam& operator=(const spam&); 
    static unsigned int x_; 
}; 

unsigned int spam::x_ = 0; 

// Auxiliary function. 
bool spam_check_x(unsigned int x) 
{ 
    return x == spam::get_x(); 
} 

BOOST_PYTHON_MODULE(example) 
{ 
    namespace python = boost::python; 
    python::class_<spam, boost::noncopyable>("Spam", python::no_init) 
    .def("setX", &spam::set_x) 
     .staticmethod("setX") 
    .def("getX", &spam::get_x) 
     .staticmethod("getX") 
    .def("checkX", &spam_check_x) 
     .staticmethod("checkX") 
    ; 
} 

交互式用法:

>>> from example import Spam 
>>> x = 42 
>>> assert(Spam.getX() != x) 
>>> assert(not Spam.checkX(x)) 
>>> Spam.setX(x) 
>>> assert(Spam.getX() == x) 
>>> assert(Spam.checkX(x)) 
>>> x = 43 
>>> assert(Spam.getX() != x) 
>>> assert(not Spam.checkX(x)) 
+0

感謝您的回覆。就我而言,我懷疑,這可能與同一進程中的多個靜態數據成員實例有關。 – user765572

+0

@ user765572當我遇到這種類型的問題時,我記錄了內存以確認是否有區別。一些編譯器和鏈接器需要爲該類提供存儲信息,如[this](http://stackoverflow.com/a/3492124/1053968)中所示。 –

0

我意識到這是一個古老的問題,但我最近遇到了同樣的問題,並認爲我應該分享。

我們能夠重現該問題在Windows與升壓1.56以下步驟:

  • 在C++中,創建兩個單獨的Boost.Python模塊:
    • 模塊,曝露出一個功能設置在類Foo
    • 模塊B的靜態變量暴露一個函數來訪問Foo的靜態變量
  • 在Python,呼叫A的接下來是B的getter。你會期望值匹配,但是(至少在我們的情況下)B的靜態仍然會被設置爲默認值。

這隻會擴展擴展模塊邊界(單獨的.pyd文件)。這個問題與Windows上的動態鏈接行爲有關。 Here是一個wiki頁面,討論同一問題的不同表現。

我們的解決方案是將C++模塊合併到一個Boost.Python模塊中,因此是一個共享對象。爲了模仿我們的舊設置,我們添加了子模塊以保持庫之間的分離:

// Put all following definitions in the current scope into a namespace-esque module 
#define MAKE_MODULE(modName) \ 
    boost::python::object module(boost::python::handle<>(boost::python::borrowed(PyImport_AddModule("pymod."#modName)))); \ 
    scope().attr(#modName) = module; \ 
    scope s(module); 

using namespace boost::python; 

BOOST_PYTHON_MODULE(pymod) 
{ 
    object package = scope(); 
    package.attr("__path__") = "pymod"; 

    // pymod.a 
    { 
     MAKE_MODULE(a); 
     exportModuleA(); 
    } 

    // pymod.b 
    { 
     MAKE_MODULE(b); 
     exportModuleB(); 
    } 

    ... 
}