【问题标题】:Set base to object of undetermined size将基础设置为未确定大小的对象
【发布时间】:2015-02-23 09:25:59
【问题描述】:

我想描述一下我最近遇到的情况,以便为这个问题提供一些背景信息。

我正在编写一个 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++ 的限制是什么?

【问题讨论】:

  • 你当然可以声明一些基类或第一个成员是PyObject的类,然后任何其他成员。
  • CxxWrapper* cxxw = static_cast&lt;CxxWrapper*&gt;(p);
  • @JonathanPotter,但是 CxxWrapper 自己的构造函数没有机会构造派生对象。
  • cxxw 是一个指针,它没有构造函数。
  • 我的错,我应该解释一下 CxxWrapper 实际上是一个完整的 C++ 类,它有自己的数据。将其称为“包装器”具有误导性,抱歉。

标签: python c++ c++11 memory-management base-class


【解决方案1】:

这是错误的做法,因为你永远无法构造你的对象!你可以做的是在PyObjects 和你的对象之间定义一个映射:

std::unordered_map<PyObject*, CxxStff> stuff;

void foo(PyObject* o) {
    CxxStuff& extra = stuff[o];
    // etc
} 

在额外的课程中放任何你想要的东西,你会很高兴的。

【讨论】:

  • 没看到c++11标签。
  • 谢谢,我没有考虑过这种方法。它看起来相当昂贵,虽然我不知道类型转换 base->derived 的成本是多少。
  • 强制转换的成本为零,但这并不重要,因为您永远不会有派生对象。
【解决方案2】:

一个格式不正确的问题。 20:20 事后看来,事情是这样的:

我正在处理一个使用 C 风格继承方案的 C 库,即

struct CBase{
    int a,b;
}

struct CDer{
    CBase ab;
    int c;
}

我正在计划我的 C++ 代码:

class CxxBase : CBase

因此,如果我从 C 中获得一个指针,我可以将类型转换为等效的 CxxBase 对象,反之亦然。

问题是 C++ 管理继承与 C 示例几乎相同。 Final: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); }

【讨论】:

    猜你喜欢
    • 2016-01-28
    • 2016-06-09
    • 1970-01-01
    • 2013-09-18
    • 2013-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-01
    相关资源
    最近更新 更多