es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cualquier macro de C++ que pueda exportar todas las variables miembro de una estructura para pybind11.

Tengo una estructura simple como esta:
“`c++
struct Config {
bool option1;
bool option2;
int arg1;
};

<pre><code>Usando pybind11, debo exportar las variables miembro así:
“`c++
py::class_<config>(m, “Config”)
.def_readwrite(“option1”, &Config::option1)
.def_readwrite(“option2”, &Config::option2)
.def_readwrite(“arg1”, &Config::arg1);

Esto está bien si tengo unas pocas estructuras. Pero se vuelve tedioso cuando tengo un gran número de estructuras simples.

¿Existe una macro conveniente que pueda escribir así?
“`c++
PYBIND_EXPORT_STRUCT(Config1);
PYBIND_EXPORT_STRUCT(Config2);

<pre><code>y cada una escanea y exporta todas las variables miembro de la estructura dada?

¿Será útil si ya escribo las estructuras de la siguiente manera?
“`c++
struct Config {
ADD_PROPERTY(bool, option1);
ADD_PROPERTY(bool, option2);
ADD_PROPERTY(int, arg1);
};

Mi pregunta involucra dos partes:

  1. Reflejar una variable miembro y devolver su cadena de nombre.
  2. Iterar a través de los miembros de la struct.

Soy consciente de la introspección para resolver la primera parte, usando typeid(arg1).name() para recuperar la cadena de nombre.

Para la segunda parte, C++ no la soporta directamente. Sin embargo, estoy tratando de descubrirlo a través de algunas respuestas aquí.

El resto de la pregunta es cómo fusionar las dos partes anteriores para obtener una implementación de trabajo para mi función imaginada PYBIND_EXPORT_STRUCT().

Dicho esto, no me importa expresar mis estructuras de una manera totalmente diferente (como usar macros o como tuplas). Cualquier forma es aceptable, siempre y cuando no tenga que enumerar nuevamente los miembros de mi struct cuando los exporto con pybind11, y todavía pueda usar las variables como config1.option1 = true en el código C++.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Para lograr la funcionalidad deseada, podemos escribir una macro que use el preprocesador para generar una lista iterable de los miembros de la estructura y sus nombres correspondientes.

    Aquí hay una implementación de ejemplo usando la macro BOOST_PP_SEQ_FOR_EACH:

    “`c++
    #include

    #define ADD_PROPERTY(type, name) \
    type name; \
    static constexpr const char* get_name_##name() { return #name; }

    #define PYBIND_EXPORT_STRUCT(struct_name) \
    PYBIND11_MODULE(struct_name, m) { \
    py::class_(m, #struct_name) \
    BOOST_PP_SEQ_FOR_EACH(PYBIND_EXPORT_STRUCT_HELPER, ~, \
    BOOST_PP_TUPLE_TO_SEQ(BOOST_PP_VARIADIC_SIZE(VA_ARGS), \
    BOOST_PP_VARIADIC_TO_TUPLE(VA_ARGS))); \
    } \
    BOOST_PP_SEQ_FOR_EACH(PYBIND_EXPORT_STRUCT_MEMBER, struct_name, \
    BOOST_PP_TUPLE_TO_SEQ(BOOST_PP_VARIADIC_SIZE(VA_ARGS), \
    BOOST_PP_VARIADIC_TO_TUPLE(VA_ARGS)));

    #define PYBIND_EXPORT_STRUCT_HELPER(r, data, elem) \
    .def_readwrite(#elem, &data::elem)

    #define PYBIND_EXPORT_STRUCT_MEMBER(r, struct_name, elem) \
    constexpr const char* struct_name####elem##_name = \
    struct_name::get_name
    ##elem();


    En la definición de macro anterior, se utiliza `ADD_PROPERTY` para definir las propiedades de la estructura de tal manera que permita el acceso a sus nombres en tiempo de compilación. A continuación, `PYBIND_EXPORT_STRUCT` se define para tomar el nombre de la estructura y una lista variadica de sus propiedades. Esta macro genera el código necesario para exportar la estructura con pybind11 y también genera una lista de los miembros de la estructura y sus nombres correspondientes utilizando la macro auxiliar `PYBIND_EXPORT_STRUCT_MEMBER`. Aquí hay un ejemplo de uso de la macro: ```c++ // definir la estructura usando ADD_PROPERTY struct Config { ADD_PROPERTY(bool, option1); ADD_PROPERTY(bool, option2); ADD_PROPERTY(int, arg1); }; // utilice la macro PYBIND_EXPORT_STRUCT para exportar la estructura PYBIND_EXPORT_STRUCT(Config, option1, option2, arg1);

    Esto generará el código necesario para exportar la estructura Config y producir una lista de sus nombres de miembros:

    “`c++
    // código generado
    PYBIND11_MODULE(Config, m) {
    py::class_(m, “Config”)
    .def_readwrite(“option1”, &Config::option1)
    .def_readwrite(“option2”, &Config::option2)
    .def_readwrite(“arg1”, &Config::arg1)
    ;
    }

    constexpr const char* Config_option1_name = Config::get_name_option1();
    constexpr const char* Config_option2_name = Config::get_name_option2();
    constexpr const char* Config_arg1_name = Config::get_name_arg1();
    “`

    Tenga en cuenta que esta implementación supone que todos los miembros de la estructura son públicos y que sus tipos se pueden usar directamente con pybind11. Si no es así, pueden ser necesarias algunas modificaciones adicionales.

Comments are closed.