Preprocessor and macros#

Export macro values into the python module#

Some #define macros can be exported:

Simple preprocessor defines can be exported as global variables, e.g.:

    #define MYLIB_VALUE 1
    #define MYLIB_FLOAT 1.5
    #define MYLIB_STRING "abc"
    #define MYLIB_HEX_VALUE 0x00010009

This is limited to simple defines.

You can also apply a simple renaming to the macro value: see example below.

cpp_code = """
    #define MYLIB_VALUE 1
    #define MYLIB_FLOAT 1.5
    #define MYLIB_STRING "abc"
    #define MYLIB_HEX_VALUE 0x00010009
"""

import litgen
from litgen.demo import litgen_demo

options = litgen.LitgenOptions()
options.macro_define_include_by_name__regex = "^MYLIB_"
# Suppress the "MYLIB_" prefix:
options.macro_name_replacements.add_first_replacement(r"^MYLIB_([A-Z_]*)", r"\1")
litgen_demo.demo(options, cpp_code, show_pydef=True)
    #define MYLIB_VALUE 1
    #define MYLIB_FLOAT 1.5
    #define MYLIB_STRING "abc"
    #define MYLIB_HEX_VALUE 0x00010009
VALUE = 1
FLOAT = 1.5
STRING = "abc"
HEX_VALUE = 0x00010009


m.attr("VALUE") = 1;
m.attr("FLOAT") = 1.5;
m.attr("STRING") = "abc";
m.attr("HEX_VALUE") = 0x00010009;
m.attr("VALUE") = 1;
m.attr("FLOAT") = 1.5;
m.attr("STRING") = "abc";
m.attr("HEX_VALUE") = 0x00010009;

Set numeric macro values#

Sometimes, it is necessary to tell litgen the value of certain numeric macros. In the example below, the member values can be exposed as a numpy array, but litgen needs to know it size.

We set it via the option:

    options.srcmlcpp_options.named_number_macros["MY_COUNT"] = 256
cpp_code = """
#define MY_COUNT 256

struct Foo
{
    int values[MY_COUNT];
};
"""

options = litgen.LitgenOptions()
options.srcmlcpp_options.named_number_macros["MY_COUNT"] = 256

litgen_demo.demo(options, cpp_code)
#define MY_COUNT 256

struct Foo
{
    int values[MY_COUNT];
};
class Foo:
    values: np.ndarray  # ndarray[type=int, size=256]
    def __init__(self) -> None:
        """Auto-generated default constructor"""
        pass


auto pyClassFoo =
    py::class_<Foo>
        (m, "Foo", "")
    .def(py::init<>()) // implicit default constructor 
    .def_property("values",
        [](Foo &self) -> pybind11::array
        {
            auto dtype = pybind11::dtype(pybind11::format_descriptor<int>::format());
            auto base = pybind11::array(dtype, {256}, {sizeof(int)});
            return pybind11::array(dtype, {256}, {sizeof(int)}, self.values, base);
        }, [](Foo& self) {},
        "")
    ;
auto pyClassFoo =
    nb::class_<Foo>
        (m, "Foo", "")
    .def(nb::init<>()) // implicit default constructor 
    .def_prop_ro("values",
        [](Foo &self) -> nb::ndarray<int, nb::numpy, nb::shape<256>, nb::c_contig>
        {
            return self.values;
        },
        "")
    ;