较新版本的Boost Python是否支持从C ++导出完整的32位枚举?我使用1.48并且能够导出最多30位但由于"访问冲突读取位置0x00000001"它每次都会失败。当我尝试导出32位数字时。深入研究enum.cpp文件,似乎在创建对象x时,它将字节20设置为1,这会在以后尝试在存在之前递减p-> name时导致失败。我只需要升级到更新版本的boost python,还是不能导出完整的32位数字?感谢您的投入!
答案 0 :(得分:2)
编辑:由Tigger在工作中找到,在此为后人记录:
问题在于enum_object结构的定义。 base_object中的基础数字存储允许15位数字(作为短路)或30位数字(作为int)粒度,但base_object仅包含2x 15位数字或1x 30位数字的足够空间。当一个>存储30位枚举值,编码需要3个短路或2个整数,具体取决于编译的格式。结果是名称成员占用了额外数字存储所需的空间。引用减量失败,因为该值已放置在名称成员期望的位置。
解决方案是在名称成员之前添加至少 32位填充以处理32位枚举值。如果在稍微遥远的未来需要64位枚举,则应添加2个填充字。
struct enum_object
{
#if PY_VERSION_HEX >= 0x03000000
PyLongObject base_object;
#else
PyIntObject base_object;
#endif
// ADD PADDING HERE TO FIX ALIGNMENT ISSUE
PyObject* name;
};
结束编辑
TL / DR:根错误是通过enum_base :: add_value函数的堆栈变量进行转换或假定对象对齐,但是最简单的方法是逐步通过转换器来查看值是否被破坏某种程度上来说。我尝试的另一个实验是交换.value调用的顺序(这可能有助于确定是否存在与堆栈相关的问题)。
详细信息:enum_base :: add_value函数在1.48和1.58(最新)之间保持不变。此外,基于python :: api :: object类和object_base_initializer模板的显式转换“(* this)(value)”似乎也没有改变。我没有进一步遍历object_base构造函数,看看是否有任何改变;我建议使用违规值逐步执行转换序列,看看是否有任何异常发生在高位的两位(我不确定你会在那里找到任何东西,但值得检查)。
请记住,转换后的值会被复制到堆栈“object x =( this)(value);”并且enum_object p的向下转换覆盖了一个大于x.ptr()引用的对象的对象(即m_ptr成员)。我不确定此时m_ptr是堆栈还是堆(没有遍历那些细节),但无论哪种方式,如果p现在覆盖陈旧或未初始化的内存,那么p-> name的引用减量将失败,如果它没有指向有效的记忆(正如你所发现的那样)。
我不确定p->名称引用减量是否必要(对象生命周期是本地的)......我将不得不考虑更多。我们可以在周一讨论更多...这是一个周末......休息一下(就像我应该说话!)
void enum_base::add_value(char const* name_, long value)
{
// Convert name to Python string
object name(name_);
// Create a new enum instance by calling the class with a value
object x = (*this)(value);
// Store the object in the enum class
(*this).attr(name_) = x;
dict d = extract<dict>(this->attr("values"))();
d[value] = x;
// Set the name field in the new enum instanec
enum_object* p = downcast<enum_object>(x.ptr());
Py_XDECREF(p->name);
p->name = incref(name.ptr());
dict names_dict = extract<dict>(this->attr("names"))();
names_dict[x.attr("name")] = x;
}