Skip to content

Commit 75f1731

Browse files
authored
Fix binding of dynamically initialized globals. (#17182)
Embind bindings were being initialized before dynamically initialized static globals, making it impossible to bind them. This moves the initialization back into a static struct so the bindings work as expected. Fixes #16275
1 parent 43d1f80 commit 75f1731

File tree

4 files changed

+39
-3
lines changed

4 files changed

+39
-3
lines changed

system/include/emscripten/bind.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1885,9 +1885,19 @@ void constant(const char* name, const ConstantType& v) {
18851885
static_cast<double>(asGenericValue(BT::toWireType(v))));
18861886
}
18871887

1888-
// EMSCRIPTEN_BINDINGS simple creates a static constructor function which
1888+
1889+
1890+
1891+
// EMSCRIPTEN_BINDINGS creates a static struct to initialize the binding which
18891892
// will get included in the program if the translation unit in which it is
1890-
// define gets linked into the program.
1891-
#define EMSCRIPTEN_BINDINGS(name) __attribute__((constructor)) static void __embind_init_##name(void)
1893+
// defined gets linked into the program. Using a C++ constructor here ensures it
1894+
// occurs after any other C++ constructors in this file, which is not true for
1895+
// __attribute__((constructor)) (they run before C++ constructors in the same
1896+
// file).
1897+
#define EMSCRIPTEN_BINDINGS(name) \
1898+
static struct EmBindInit_##name { \
1899+
EmBindInit_##name(); \
1900+
} EmBindInit_##name##_instance; \
1901+
EmBindInit_##name::EmBindInit_##name()
18921902

18931903
} // end namespace emscripten
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2018 The Emscripten Authors. All rights reserved.
2+
// Emscripten is available under two separate licenses, the MIT license and the
3+
// University of Illinois/NCSA Open Source License. Both these licenses can be
4+
// found in the LICENSE file.
5+
6+
#include <string>
7+
#include <emscripten/bind.h>
8+
#include <emscripten/emscripten.h>
9+
10+
const std::string global_string = "global string";
11+
12+
EMSCRIPTEN_BINDINGS(constants) {
13+
emscripten::constant("global_string", global_string);
14+
}
15+
16+
int main() {
17+
EM_ASM(
18+
console.log("global_string = " + Module['global_string']);
19+
);
20+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
global_string = global string

tests/test_core.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7484,6 +7484,11 @@ def test_embind_val_assignment(self):
74847484
err = self.expect_fail([EMCC, test_file('embind/test_val_assignment.cpp'), '-lembind', '-c'])
74857485
self.assertContained('candidate function not viable: expects an lvalue for object argument', err)
74867486

7487+
@no_wasm64('embind does not yet support MEMORY64')
7488+
def test_embind_dynamic_initialization(self):
7489+
self.emcc_args += ['-lembind']
7490+
self.do_run_in_out_file_test('embind/test_dynamic_initialization.cpp')
7491+
74877492
@no_wasm2js('wasm_bigint')
74887493
@no_wasm64('embind does not yet support MEMORY64')
74897494
def test_embind_i64_val(self):

0 commit comments

Comments
 (0)