Skip to content

Commit 5c63a71

Browse files
msorvigMorten Sørvig
andauthored
Make embind work with -fvisibility=hidden (#22095)
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. Co-authored-by: Morten Sørvig <[email protected]>
1 parent 340aa0f commit 5c63a71

File tree

3 files changed

+33
-2
lines changed

3 files changed

+33
-2
lines changed

system/include/emscripten/val.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ struct WireTypePack {
285285
static const char name##_symbol[] = #name; \
286286
static const ::emscripten::internal::symbol_registrar<name##_symbol> name##_registrar
287287

288-
class val {
288+
class EMBIND_VISIBILITY_DEFAULT val {
289289
public:
290290
// missing operators:
291291
// * ~ - + ++ --

system/include/emscripten/wire.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <string>
2525

2626
#define EMSCRIPTEN_ALWAYS_INLINE __attribute__((always_inline))
27+
#define EMBIND_VISIBILITY_DEFAULT __attribute__((visibility("default")))
2728

2829
#ifndef EMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES
2930
#define EMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES 1
@@ -430,7 +431,7 @@ constexpr bool typeSupportsMemoryView() {
430431
} // namespace internal
431432

432433
template<typename ElementType>
433-
struct memory_view {
434+
struct EMBIND_VISIBILITY_DEFAULT memory_view {
434435
memory_view() = delete;
435436
explicit memory_view(size_t size, const ElementType* data)
436437
: size(size)

test/test_core.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7717,6 +7717,36 @@ def test_source_map(self, args):
77177717
else:
77187718
self.assertTrue(seen_lines.issuperset([6, 7, 11, 12]), seen_lines)
77197719

7720+
@needs_dylink
7721+
def test_embind_dylink_visibility_hidden(self):
7722+
# Check that embind is usable from a library built with "-fvisibility=hidden"
7723+
7724+
create_file('liblib.cpp', r'''
7725+
#include <emscripten/val.h>
7726+
#define EXPORT __attribute__((visibility("default")))
7727+
using namespace emscripten;
7728+
EXPORT void liba_fun() {
7729+
unsigned char buffer[1];
7730+
val view(typed_memory_view(1, buffer));
7731+
}
7732+
''')
7733+
self.build_dlfcn_lib('liblib.cpp', emcc_args=['-fvisibility=hidden'])
7734+
7735+
self.prep_dlfcn_main()
7736+
self.clear_setting('NO_AUTOLOAD_DYLIBS')
7737+
create_file('main.cpp', r'''
7738+
#include <stdio.h>
7739+
#include <emscripten/val.h>
7740+
using namespace emscripten;
7741+
void liba_fun();
7742+
int main() {
7743+
liba_fun();
7744+
printf("done\n");
7745+
return 0;
7746+
}
7747+
''')
7748+
self.do_runf('main.cpp', 'done\n', emcc_args=['--bind'])
7749+
77207750
@no_wasm2js('TODO: source maps in wasm2js')
77217751
def test_dwarf(self):
77227752
self.emcc_args.append('-g')

0 commit comments

Comments
 (0)