emscripten-core / emscripten

Emscripten: An LLVM-to-WebAssembly Compiler
Other
25.36k stars 3.25k forks source link

Make embind work with -fvisibility=hidden #22095

Open msorvig opened 2 weeks ago

msorvig commented 2 weeks ago

Export emscripten::val and emscripten::memory_view in order to prevent embind errors:

BindingError: _emval_take_value has unknown type N10emscripten11memory_viewIhEE

Embind generates a numerical type id from the address of the std::type_info object resulting from evaluating a typeid expressiion (e.g. 'void *id = &typeid(T)').

However, C++ does not guarantee that this address is identical for all evaluations of the typeid expression. In practice it is when using static linking, but not when using dynamic linking when the libraries are built with the '-fvisibility=hidden' compiler option.

The non-identical id's then cause embind to decide that types have not been registered when used from a library, since they have been registered with a different id by the main wasm module.

Exporting the types in question makes typeid addresses identical again, and fixes/works around the issue.

msorvig commented 2 weeks ago

This looks to be sufficient for Qt's use case. More types can be exported if needed.

There's a bit more to it: ideally embind should work with non-exported ("hidden") types as well, and it looks like C++ API like std::type_info::hash_code() and std::type_index may not work correctly for non-exported types.

Looking at at system/lib/libcxx/include/typeinfo, there are two options from implementing typeinfo:

  1. _LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION = 1: (default): "This implementation of type_info assumes a unique copy of the RTTI for a given type inside a program"
  2. _LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION = 2: "This implementation of type_info does not assume there is always a unique copy of the RTTI for a given type inside a program"

Emscripten currently uses the default option 1, but does not generate unique RTTI for non-exported types in libraries/side modules.

brendandahl commented 2 weeks ago

@sbc100 Do you think there's some way we could properly have unique rtti for the program?

msorvig commented 2 weeks ago

Note previous discussion on https://github.com/emscripten-core/emscripten/issues/16711

sbc100 commented 2 weeks ago

@sbc100 Do you think there's some way we could properly have unique rtti for the program?

I think the way to achieve that is make sure the types are marked as defaultand not hidden visibility.

This fix seems correct to me for the core embind types. They always want to be shared I think.

We also have -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 which looks like it tells embind not to use RTTI info at all... although I don't really understand the naming of that macro.