Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C++ unions #9

Closed
renautomation opened this issue Apr 30, 2024 · 5 comments
Closed

C++ unions #9

renautomation opened this issue Apr 30, 2024 · 5 comments

Comments

@renautomation
Copy link

renautomation commented Apr 30, 2024

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?

@pthom
Copy link
Owner

pthom commented Apr 30, 2024

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

@pthom
Copy link
Owner

pthom commented Apr 30, 2024

@renautomation
Copy link
Author

renautomation commented May 30, 2024

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.

`

@pthom
Copy link
Owner

pthom commented May 30, 2024

https://github.com/pthom/litgen/blob/226992d4e30be298963fa96e52254e2e45af6477/src/litgen/options.py#L110C1-L118C46

    # 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 = ""

@renautomation
Copy link
Author

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

@pthom pthom closed this as completed Aug 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants