Skip to content

Finegrained control over bindings generation of class members #3248

@zopsicle

Description

@zopsicle

As far as I understand, currently:

  • If bindings are generated for a class, bindings are also generated for all members of the class, as far as this is supported (e.g. no virtual methods).
  • This can be limited very coarsely using --generate. For example, --generate functions,types,vars,constructors,destructors will not generate bindings for any methods.
  • Base objects and fields can be hidden using --opaque-type.

But you can't allowlist or blocklist specific constructors, destructors, methods, and nested types.

A pattern that in my experience often comes up is where most members are suitable for direct bindgen, but a handful require custom glue code to be callable from Rust:

// library.h, third party
#include <string>

class Foo
{
public:
    Foo();
    enum Type { Static, Dynamic };
    void bar(Type);
    void baz(std::string);
};

// glue.cpp, my code
#include <library.h>

void Foo_baz(Foo* self, char const* ptr, std::size_t len)
{
    self->baz(std::string(ptr, len));
}
clang++ -c glue.cpp

# Do not generate bindings for Foo::baz, as it uses std::string which is too complex.
bindgen --allowlist-type Foo|Foo::Type \
        --allowlist-constructor Foo::Foo \
        --allowlist-method Foo::bar \
        --allowlist-function Foo_baz \
        glue.cpp

My current workaround is to just have bindings generated for all members, pass --no-recursive-allowlist, and define manual opaque types that are used in parameters and return types as needed, e.g. #[repr(C)] pub struct std_string([u8; 0]);. :P

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions