Skip to content

Commit bd45403

Browse files
author
Morten Sørvig
committed
Make embind work with -fvisibility=hidden
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.
1 parent 9e21488 commit bd45403

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
@@ -7718,6 +7718,36 @@ def test_source_map(self, args):
77187718
else:
77197719
self.assertTrue(seen_lines.issuperset([6, 7, 11, 12]), seen_lines)
77207720

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

0 commit comments

Comments
 (0)