pthom / litgen

litgen: a pybind11 automatic generator for humans who like nice code and API documentation. Also a C++ transformer tool
https://pthom.github.io/litgen
GNU General Public License v3.0
36 stars 3 forks source link

Structures with typedef #7

Open integerfn opened 2 months ago

integerfn commented 2 months ago

Hi! Thanks for the tremendous work. I've been looking for something like this for a long time.

I'm just getting started and trying to get the hang of it. The first issue I encountered which I have not been able to solve is related to structures defined with typedef. I have a mixed C/C++ codebase and we have several structs typedef'd like this:

typedef struct {
    int x;
} MyStruct ;

From what I have seen, litgen ignores these type definitions. Also tried using and got a similar results. Is there a configuration I need to enable to have type aliases included? I'm working with cppimport, but as far as I can tell the binding code is already missing for these types so I don't think that makes a difference.

Here's a simple example:

typedef struct {
    int x;
    int y;
} Vector2D;

int VectorNorm2( Vector2D v )
{
    return v.x * v.x + v.y * v.y;
}

This produces something that is missing the type definition

# stub
def vector_norm2(v: Vector2D) -> int:
    pass

// pydef
m.def("vector_norm2",
    VectorNorm2, py::arg("v"));

Any help is appreciated Thanks!

pthom commented 2 months ago

Hello, thanks for the compliment, litgen was indeed a lot of work!

Concerning your issue I would think that you should use the code pre-processing utilities, and thus write a small Python function that transforms those structs into standard C++ structs.

I did ask ChatGPT and he had a proposition which I did not test:

https://chat.openai.com/share/e0cea5b6-7cb3-4e0e-9fd3-d982c915911c

integerfn commented 2 months ago

Hi again, thanks for the super fast answer. Your suggested workaround worked great for my case, at least for the simple example I was playing around with, I'll have to try it with the full codebase at some point and see if something else breaks.

I did find something else that looks like a bug, which is related to this. See this simple type alias:

struct Vector2D {
    int x;
    int y;
};

using VectorAlias = Vector2D;

int VectorNorm2( VectorAlias v )
{
    return v.x * v.x + v.y * v.y;
}

Now the produced pybind code is alright:

auto pyClassVector2D =
    py::class_<Vector2D>
        (m, "Vector2D", "")
    .def(py::init<>([](
    int x = int(), int y = int())
    {
        auto r = std::make_unique<Vector2D>();
        r->x = x;
        r->y = y;
        return r;
    })
    , py::arg("x") = int(), py::arg("y") = int()
    )
    .def_readwrite("x", &Vector2D::x, "")
    .def_readwrite("y", &Vector2D::y, "")
    ;

m.def("vector_norm2",
    VectorNorm2, py::arg("v"));

However, the stub isn't:

class Vector2D:
    x: int
    y: int
    def __init__(self, x: int = int(), y: int = int()) -> None:
        """Auto-generated default constructor with named params"""
        pass

def vector_norm2(v: VectorAlias) -> int:
    pass

As VectorAlias hasn't been defined, the autocomplete doesn't work in PyCharm. Is this intended?

Thanks!

pthom commented 2 months ago

In this case, manually add this:

VectorAlias: TypeAlias = Vector2D

In the stub file (before the autogenerated part)