C++ unions
renautomation opened this issue · comments
Hello,
I have code like this:
typedef union u_signalValue_t {
float flt;
int32_t i32;
double dbl;
int64_t i64;
} signalValue_t;
I already overcame the issue related to the usage of "typedef", by pre-processing the code, as suggested here:
#7
So, my pre-processed code is now:
union signalValue_t {
float flt;
int32_t i32;
double dbl;
int64_t i64;
};
however, it seems the the union type is not processed by litgen: I see all other types in the pybind11 C++ code, like enums, classes, structs, etc. except this union.
Any suggestion?
Union types are very, very, C/C++ specific.
There is no such thing as unions in Python: object and base types will always occupy different memory locations.
Solutions:
1/ Either you write a wrapper And use it in the API you want to publish.
class MySignal
{
int as_int();
...
private:
signalValue_t xxx;
};
2/ And/or you write a custom caster And give it appropriate methods.
https://pybind11.readthedocs.io/en/stable/advanced/cast/custom.html
Hi, I used the wrapper approach suggested above by ChatGPT. Now, I'm trying to add the original union type in the exclude options, but I don't find the proper option. I only found:
fn_exclude_by_name__regex
class_exclude_by_name__regex
member_exclude_by_name__regex
but of course they don't work because I don't have neither a function nor a class, I have a union.
The problem is that, if I don't exclude it, in the generated code, in the bindings related to the functions and classes that use my union, I find stuff like:
..., py::arg("value") = signalValue_t(), ... (in pybind11_module.cpp)
...value: signalValue_t ... (in init.pyi)
the build process works, but then when I go to Python:
`>>> from MyPythonBindings import *
Traceback (most recent call last):
File "", line 1, in
File "/My/Path/init.py", line 1, in
from MyPythonBindings._MyPythonBindings import * # type: ignore # noqa: F403
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ImportError: arg(): could not convert default argument into a Python object (type not registered yet?). #define PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for more information.
`
# Exclude certain functions and methods by a regex on any of their parameter type and/or return type
# (those should be decorated type)
# For example:
# options.fn_exclude_by_param_type__regex = "^char\s*$|^unsigned\s+char$|Callback$"
# would exclude all functions having params of type "char *", "unsigned char", "xxxCallback"
#
# Note: this is distinct from `fn_params_exclude_types__regex` which removes params
# from the function signature, but not the function itself.
fn_exclude_by_param_type__regex: str = ""
ok, I was doing confusion before on what I really needed... I didn't need to exclude the "union" (also because it was already excluded by litgen by default, in fact I opened the issue exactly for this reason.
So, now I found the way to expose union types, and I resume the procedure for eventual future users:
- wrap the union as described above
- force the exposed functions to use the wrapped version and not the original union by pre-processing the header via options.srcmlcpp_options.code_preprocess_function
- exclude the creation of the binding for the union element present into the wrapper, by using options.member_exclude_by_type__regex
Now the bindings are correctly generaed and the wrapped union works s expected. Thanks a lot for your support, @pthom