C++;Python中的静态 我有一个C++类,它包含某种“静态”(在这个特定的情况下为“MyEngEngress”): 此类在我的项目中广泛使用,在C++级别。

C++;Python中的静态 我有一个C++类,它包含某种“静态”(在这个特定的情况下为“MyEngEngress”): 此类在我的项目中广泛使用,在C++级别。,c++,boost-python,C++,Boost Python,通过Boost.Python公开RndGenerator后: class_<RndGenerator, boost::noncopyable>("RndGenerator", no_init) .def("setInitialSeed", &RndGenerator::setInitialSeed) .staticmethod("setInitialSeed") .def("rndNumber", &RndGenerator::rndNumber) .

通过Boost.Python公开RndGenerator后:

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

我想,在这一行之后,所有调用RNDeGeulver::RNDNUBER(),在C++级别,都会考虑到指定的初始种子(1234)。 但事实并非如此

包含暴露于Python的静态成员的类有问题吗?
或者我的问题与RNGnGrand的性质有关吗?

< P>使用BC++类中的静态数据成员或静态成员函数,Boosi.Python不应该有任何问题。这可能是假阳性吗?或者,对于在多个翻译单元中实例化同一模板的更复杂和更具体的情况,则对于动态库,具有相同符号名的静态数据成员的多个实例可能位于同一进程空间中

无论如何,下面是一个完整的示例,演示了Boost.Python公开的类上静态成员函数和静态数据成员的预期行为:

class_<RndGenerator, boost::noncopyable>("RndGenerator", no_init)
  .def("setInitialSeed", &RndGenerator::setInitialSeed)
  .staticmethod("setInitialSeed")
  .def("rndNumber", &RndGenerator::rndNumber)
  .staticmethod("rndNumber")
  ;
#包括
//基本模型类型。
类垃圾邮件
{
公众:
静态无效集_x(无符号整数x){x_x=x;}
静态无符号int get_x(){return x_;};
私人:
垃圾邮件(){};
垃圾邮件(const spam&);
垃圾邮件和运算符=(const spam&);
静态无符号整数x;
};
无符号int spam::x_ux=0;
//辅助功能。
bool spam\u check\u x(无符号整数x)
{
return x==spam::get_x();
}
BOOST_PYTHON_模块(示例)
{
名称空间python=boost::python;
python::class_(“垃圾邮件”,python::no_init)
.def(“setX”,&spam::set_x)
.静态方法(“setX”)
.def(“getX”&垃圾邮件::get_x)
.staticmethod(“getX”)
.def(“检查x”&垃圾邮件检查x)
.静态方法(“检查X”)
;
}
互动使用:

>>来自示例导入垃圾邮件
>>>x=42
>>>断言(Spam.getX()!=x)
>>>断言(不是垃圾邮件。检查x(x))
>>>Spam.setX(x)
>>>断言(Spam.getX()==x)
>>>断言(Spam.checkX(x))
>>>x=43
>>>断言(Spam.getX()!=x)
>>>断言(不是垃圾邮件。检查x(x))

我意识到这是一个老问题,但我最近遇到了同样的问题,我想我应该与大家分享

我们能够通过以下步骤在使用Boost 1.56的Windows上重现该问题:

    在C++中,创建两个单独的升压Python模块:
    • 模块A公开了一个函数来设置类Foo中的静态变量
    • 模块B公开了一个函数来访问Foo的静态变量
  • 在Python中,先调用A的setter,然后调用B的getter。您可能希望该值匹配,但(至少在本例中)B的static仍将设置为其默认值
这只会跨越扩展模块边界(单独的.pyd文件)。这个问题与Windows上的动态链接行为有关。是讨论同一问题的不同表现形式的wiki页面

我们的解决方案是将C++模块合并为一个BooSo.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();
    }

    ...
}
//将当前作用域中的以下所有定义放入命名空间式模块中
#定义MAKE_模块(modName)\
对象模块(boost::python::handle(boost::python::借用(PyImport_AddModule(“pymod.”#modName)))\
scope().attr(#modName)=模块\
范围s(模块);
使用名称空间boost::python;
BOOST_PYTHON_模块(pymod)
{
对象包=范围();
package.attr(“\uuuu路径”=“pymod”;
//pymod.a
{
制作模块(a);
exportModuleA();
}
//pymod.b
{
制作模块(b);
exportModuleB();
}
...
}

谢谢您的回复。在我的情况下,我怀疑这可能与同一进程中的多个静态数据成员实例有关。@user765572当我遇到这种类型的问题时,我记录了所寻址的内存以确认存在差异。某些编译器和链接器需要为类提供存储信息,如答案中所示。
// 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();
    }

    ...
}