Skip to content

Commit 789474b

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 1236ec0 commit 789474b

File tree

3 files changed

+38
-2
lines changed

3 files changed

+38
-2
lines changed

system/include/emscripten/val.h

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

27+
#define EMSCRIPTEN_EXPORT __attribute__((visibility("default")))
2728

2829
namespace emscripten {
2930

@@ -285,7 +286,7 @@ struct WireTypePack {
285286
static const char name##_symbol[] = #name; \
286287
static const ::emscripten::internal::symbol_registrar<name##_symbol> name##_registrar
287288

288-
class val {
289+
class EMSCRIPTEN_EXPORT val {
289290
public:
290291
// missing operators:
291292
// * ~ - + ++ --

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 EMSCRIPTEN_EXPORT __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 EMSCRIPTEN_EXPORT 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: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7724,6 +7724,40 @@ def test_source_map(self, args):
77247724
else:
77257725
self.assertTrue(seen_lines.issuperset([6, 7, 11, 12]), seen_lines)
77267726

7727+
@needs_dylink
7728+
def test_embind_dylink_visibility_hidden(self):
7729+
# Check that embind is usable from a library built with "-fvisibility=hidden"
7730+
create_file('liba.cpp', r'''
7731+
#include <emscripten/val.h>
7732+
#define EXPORT __attribute__((visibility("default")))
7733+
using namespace emscripten;
7734+
EXPORT void liba_fun() {
7735+
unsigned char buffer[1];
7736+
val view(typed_memory_view(1, buffer));
7737+
}
7738+
''')
7739+
7740+
# side module
7741+
self.build_dlfcn_lib('liba.cpp', outfile='liba.so', emcc_args=['-std=c++11', '-fvisibility=hidden'])
7742+
7743+
# main module
7744+
self.set_setting('MAIN_MODULE', 1)
7745+
self.clear_setting('SIDE_MODULE')
7746+
7747+
self.emcc_args = ['liba.so', '-L.', '--bind']
7748+
create_file('main.cpp', r'''
7749+
#include <stdio.h>
7750+
#include <emscripten/val.h>
7751+
using namespace emscripten;
7752+
void liba_fun();
7753+
int main() {
7754+
liba_fun();
7755+
printf("done\n");
7756+
return 0;
7757+
}
7758+
''')
7759+
self.do_runf('main.cpp', 'done\n')
7760+
77277761
@no_wasm2js('TODO: source maps in wasm2js')
77287762
def test_dwarf(self):
77297763
self.emcc_args.append('-g')

0 commit comments

Comments
 (0)