我想最近描述一下我面临的情况,以便提出一些问题。
我正在编写Python C ++包装器。 Python的基本单元是PyObject。 Python中的每个实体都是PyObject +更多可选的东西。
也就是说保证第一个sizeofPyObject)
字节填写PyObject的字段,但各种对象可能会分配额外的连续内存。
这样做的好处(原因?)是任何东西都可以被强制转换回有意义的PyObject
。
我试图包裹这样一只野兽:
class CxxWrapper : PyObject {}
假设我创建了一个void foo(PyObject* p)
,并将foo
插入到一个Python运行时的函数指针表中。
然后运行时将触发此函数(无论出于何种原因)将指针传递给相关的PyObject
。
我希望能够将这种直接类型转换回相应的CxxWrapper对象:
CxxWrapper* cxxw = static_cast<CxxWrapper>p;
但是,我无法通过任何方式让这种机制发挥作用。因为我无法找到将基础对象设置为PyObjectPlusExtra
的任何方法。
有没有办法做到这一点?如果没有,那么C ++的限制是什么?
答案 0 :(得分:1)
这是错误的做法,因为你永远无法构建你的对象!你可以做的是在PyObject
和你的对象之间定义一个地图:
std::unordered_map<PyObject*, CxxStff> stuff;
void foo(PyObject* o) {
CxxStuff& extra = stuff[o];
// etc
}
把你想要的东西放在那个额外的课堂上,你会很高兴。
答案 1 :(得分:0)
一个形成错误的问题。事后20:20,这是正在发生的事情:
我正在处理C库使用C风格的继承方案,即
struct CBase{
int a,b;
}
struct CDer{
CBase ab;
int c;
}
我正在计划我的C ++代码:
class CxxBase : CBase
因此,如果我从C获得指针,我可以将类型转换为等效的CxxBase对象,反之亦然。
问题是C ++管理的继承与C示例几乎相同。最后:Der:Base将存储一个Base然后是Der,然后是一个Final对象在连续的内存中。
所以不可能完成这个联盟。 CDer和CxxDer的大小都是未知的。
需要一种不同的技术,例如Barry提出的映射。
然而,这涉及相当昂贵的查询。
我看不到比我正在进行的项目中的现有解决方案更好的解决方案:
struct Bridge {
CObj cob;
CxxObj* p_cxxob;
}
const CxxObj& to_cxx(CObj* cob) { return *(cob->p_cxxob); }