pybind11:用可选数据表示并集
pybind11: Represent union with optional data
我的结构如下所示:
/// Enumeration describing register data types.
typedef enum RegDataType
{
RegDataType_Unknown = 0x0, ///< Unknown register data type.
RegDataType_ImmMultiData = 0x1, ///< Register data type is consecutive register values from a single offset.
RegDataType_ImmMultiPairs = 0x2, ///< Register data type is register offset and value pairs.
RegDataType_IndirectData = 0x3, ///< Register data type is consecutive register values from a single offset at
/// a specified address.
RegDataType_IndirectPairs = 0x4, ///< Register data type is register offset and value pairs at a specified
/// address.
} RegDataType;
/// Structure representing a register data pair of offset and value.
typedef struct PktRegDataPair
{
uint32_t offset; ///< The register offset.
uint32_t value; ///< The register value.
} PktRegDataPair;
/// Structure representing different types of register data that can be found within a packet.
typedef struct PktRegData
{
RegDataType type; ///< Register data type.
uint32_t numRegs; ///< The number of register represented.
union
{
struct
{
uint32_t regOffset; ///< Starting register offset.
const uint32_t* pData; ///< Pointer to consecutive register values.
} immMultiData;
struct
{
const PktRegDataPair* pData; ///< Pointer to register pairs of offsets/values.
} immMultiPairs;
struct
{
uint64_t address; ///< Address of consecutive register values/pairs of offsets/values.
uint32_t addrOffset; ///< Offset to an existing address. Valid only if address above is zero.
struct
{
uint32_t regOffset; ///< Starting register offset.
} data;
} indirect;
};
} PktRegData;
我想将它包装在 pybind11 中,这样当结构返回到 Python 时,只存在有效的成员变量。同样,当从Python加载时,我需要将其翻译成PktRegData结构。
我不知道在 pybind11 中执行此操作的最佳方法。我看过 custom type casters and polymorphic type hooks 的文档,但我不确定哪一个最适合我的用例。
感谢您的帮助!
您有一堆未定义的类型,并且没有指定哪些类型组合有效,因此无法制作 运行 示例,但也许下面的代码可以帮助您。
这个想法是使用 属性 来表示数据,这样你就可以得到一个钩子并在表示方面做任何你想做的事情(我充实了下面的阅读方面,写作会相似)。在钩子中,创建一个占位符对象,检查联合体中哪些成员有效,然后根据需要填充占位符的属性。
#include <pybind11/pybind11.h>
#include <pybind11/pytypes.h>
#include "PktRegData.h"
namespace py = pybind11;
struct PyRegData {}; // placeholder
PYBIND11_MODULE(PktRegData, m)
{
py::class_<PyRegData>(m, "RegData", py::dynamic_attr())
.def(pybind11::init<>());
py::class_<PktRegData>(m, "PktRegData")
.def(pybind11::init<>())
.def_property("data", [](PktRegData &d) -> pybind11::object {
auto this_mod = py::module::import("PktRegData");
py::object data_type = this_mod.attr("RegData");
py::object data_obj = data_type();
if (d.type == ...) {
// just one example of setting properties
data_obj.attr("regOffset") = py::cast(d.immMultiData.regOffset);
} else if (d.type == ...) {
...
}
return data_obj;
}, [](PktRegData& d) {});
}
上面的代码在您的 "only the valid member variables are present" 之后。就个人而言,如果访问当前无效的属性,我会将所有数据成员绑定为属性并简单地引发 ValueError(或 AttributeError 以更接近您的设计)。
我的结构如下所示:
/// Enumeration describing register data types.
typedef enum RegDataType
{
RegDataType_Unknown = 0x0, ///< Unknown register data type.
RegDataType_ImmMultiData = 0x1, ///< Register data type is consecutive register values from a single offset.
RegDataType_ImmMultiPairs = 0x2, ///< Register data type is register offset and value pairs.
RegDataType_IndirectData = 0x3, ///< Register data type is consecutive register values from a single offset at
/// a specified address.
RegDataType_IndirectPairs = 0x4, ///< Register data type is register offset and value pairs at a specified
/// address.
} RegDataType;
/// Structure representing a register data pair of offset and value.
typedef struct PktRegDataPair
{
uint32_t offset; ///< The register offset.
uint32_t value; ///< The register value.
} PktRegDataPair;
/// Structure representing different types of register data that can be found within a packet.
typedef struct PktRegData
{
RegDataType type; ///< Register data type.
uint32_t numRegs; ///< The number of register represented.
union
{
struct
{
uint32_t regOffset; ///< Starting register offset.
const uint32_t* pData; ///< Pointer to consecutive register values.
} immMultiData;
struct
{
const PktRegDataPair* pData; ///< Pointer to register pairs of offsets/values.
} immMultiPairs;
struct
{
uint64_t address; ///< Address of consecutive register values/pairs of offsets/values.
uint32_t addrOffset; ///< Offset to an existing address. Valid only if address above is zero.
struct
{
uint32_t regOffset; ///< Starting register offset.
} data;
} indirect;
};
} PktRegData;
我想将它包装在 pybind11 中,这样当结构返回到 Python 时,只存在有效的成员变量。同样,当从Python加载时,我需要将其翻译成PktRegData结构。
我不知道在 pybind11 中执行此操作的最佳方法。我看过 custom type casters and polymorphic type hooks 的文档,但我不确定哪一个最适合我的用例。
感谢您的帮助!
您有一堆未定义的类型,并且没有指定哪些类型组合有效,因此无法制作 运行 示例,但也许下面的代码可以帮助您。
这个想法是使用 属性 来表示数据,这样你就可以得到一个钩子并在表示方面做任何你想做的事情(我充实了下面的阅读方面,写作会相似)。在钩子中,创建一个占位符对象,检查联合体中哪些成员有效,然后根据需要填充占位符的属性。
#include <pybind11/pybind11.h>
#include <pybind11/pytypes.h>
#include "PktRegData.h"
namespace py = pybind11;
struct PyRegData {}; // placeholder
PYBIND11_MODULE(PktRegData, m)
{
py::class_<PyRegData>(m, "RegData", py::dynamic_attr())
.def(pybind11::init<>());
py::class_<PktRegData>(m, "PktRegData")
.def(pybind11::init<>())
.def_property("data", [](PktRegData &d) -> pybind11::object {
auto this_mod = py::module::import("PktRegData");
py::object data_type = this_mod.attr("RegData");
py::object data_obj = data_type();
if (d.type == ...) {
// just one example of setting properties
data_obj.attr("regOffset") = py::cast(d.immMultiData.regOffset);
} else if (d.type == ...) {
...
}
return data_obj;
}, [](PktRegData& d) {});
}
上面的代码在您的 "only the valid member variables are present" 之后。就个人而言,如果访问当前无效的属性,我会将所有数据成员绑定为属性并简单地引发 ValueError(或 AttributeError 以更接近您的设计)。