Gri*_*rim 5 c++ python boost-python
我在C++中有以下代码:
class Person
{
public:
enum Gender {Male, Female};
Gender GetGender() const;
}
Run Code Online (Sandbox Code Playgroud)
我用这种方式将它包装在boost :: python中:
BOOST_PYTHON_MODULE(TestPython)
{
scope the_scope = class_<Person>("Person")
.def("GetGender", &Person::GetGender);
enum_<Person::Gender>("Gender")
.value(Male, Person::Male)
.value(Female, Person::Female)
.export_values();
}
Run Code Online (Sandbox Code Playgroud)
当我尝试person.GetGender()从Python 调用时,我得到以下异常:
Can't pickle : attribute lookup **PyBF.TestPython.Gender**. It guesses the namespace of the Gender (which is actually **PyBF.TestPython.Person.Gender**) enum return type incorrectly.
如何告诉GetGender函数显式返回什么类型?
由于我们没有产生错误的代码,我假设当您尝试 pickle Person 对象时会发生错误。
您的问题与 boost 的使用没有具体关系。它位于 cPickle 模块中。它在使用嵌套类酸洗对象时存在问题。请参阅此答案以获取解释。这是一个产生错误的简单代码示例:
import cPickle
class MyOuterClass(object):
class MyInnerClass(object):
pass
def __init__(self):
self.my_inner_class = self.MyInnerClass()
def pickle_error():
print "Pickling ..."
my_outer_class = MyOuterClass()
print cPickle.dumps(my_outer_class)
if __name__ == "__main__":
pickle_error()
Run Code Online (Sandbox Code Playgroud)
运行它会产生以下输出:
Pickling ...
Traceback (most recent call last):
File "pickle.py", line 18, in <module>
pickle_error()
File "pickle.py", line 15, in pickle_error
print cPickle.dumps(my_outer_class)
cPickle.PicklingError: Can't pickle <class '__main__.MyInnerClass'>:
attribute lookup __main__.MyInnerClass failed
Run Code Online (Sandbox Code Playgroud)
正如链接答案中提到的,当 cPickle 询问内部类的名称时,它会返回'__main__.MyInnerClass'。但是,在模块的命名空间中找不到该名称,因此会出现异常。
现在您会遇到这种情况,因为由于 python 中没有类似于枚举类型的东西,所以 boost 创建一个对象来表示它。enum_ 构造在当前范围内声明一个类。通过捕获类作用域,您最终会在 Person 中创建一个嵌套类,并收到上面提到的 pickle 错误。
有几种解决方案可以解决您的问题。
最简单的方法是在 Person 范围之外声明枚举。除了用于代码组织之外,您可能不想公开 Person 的相关枚举。然后,您可以在子模块中声明 Person 类,以便您的枚举在某种程度上声明为接近您的类,而不会过于公开。
您还可以查看boost 的 pickle 支持。不过我还没有尝试过。
第三种解决方案可能是使用 pickle 之外的其他东西来存储您的对象。