Skip to content

Commit d1c731c

Browse files
authored
embind: Better support memory64 for TS generation (#20568)
* fix: enable flags needed to run tsgen js based on settings * fix: add missing mappings for longs & unsigned longs * style: use shared helper to get nodejs memory64 flags * fix: map longs to bigints if memory64 is enabled * test: update normal test case w/ long values * test: add test case for memory64 longs ts bindings * chore: disable wasm exceptions when generating ts typings * docs: explain new behavior in docs * docs: add missing or
1 parent c46987e commit d1c731c

File tree

8 files changed

+42
-6
lines changed

8 files changed

+42
-6
lines changed

site/source/docs/porting/connecting_cpp_and_javascript/embind.rst

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -909,17 +909,17 @@ Out of the box, *embind* provides converters for many standard C++ types:
909909
+---------------------+--------------------------------------------------------------------+
910910
| ``unsigned int`` | Number |
911911
+---------------------+--------------------------------------------------------------------+
912-
| ``long`` | Number |
912+
| ``long`` | Number, or BigInt* |
913913
+---------------------+--------------------------------------------------------------------+
914-
| ``unsigned long`` | Number |
914+
| ``unsigned long`` | Number, or BigInt* |
915915
+---------------------+--------------------------------------------------------------------+
916916
| ``float`` | Number |
917917
+---------------------+--------------------------------------------------------------------+
918918
| ``double`` | Number |
919919
+---------------------+--------------------------------------------------------------------+
920-
| ``int64_t`` | BigInt* |
920+
| ``int64_t`` | BigInt** |
921921
+---------------------+--------------------------------------------------------------------+
922-
| ``uint64_t`` | BigInt* |
922+
| ``uint64_t`` | BigInt** |
923923
+---------------------+--------------------------------------------------------------------+
924924
| ``std::string`` | ArrayBuffer, Uint8Array, Uint8ClampedArray, Int8Array, or String |
925925
+---------------------+--------------------------------------------------------------------+
@@ -928,7 +928,9 @@ Out of the box, *embind* provides converters for many standard C++ types:
928928
| ``emscripten::val`` | anything |
929929
+---------------------+--------------------------------------------------------------------+
930930

931-
\*Requires BigInt support to be enabled with the `-sWASM_BIGINT` flag.
931+
\*BigInt when MEMORY64 is used, Number otherwise.
932+
933+
\*\*Requires BigInt support to be enabled with the `-sWASM_BIGINT` flag.
932934

933935
For convenience, *embind* provides factory functions to register
934936
``std::vector<T>`` (:cpp:func:`register_vector`) and ``std::map<K, V>``

src/embind/embind_ts.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,10 @@ var LibraryEmbind = {
210210
['bool', 'boolean'],
211211
['float', 'number'],
212212
['double', 'number'],
213+
#if MEMORY64
214+
['long', 'bigint'],
215+
['unsigned long', 'bigint'],
216+
#endif
213217
#if WASM_BIGINT
214218
['int64_t', 'bigint'],
215219
['uint64_t', 'bigint'],

test/other/embind_tsgen.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ class Test {
1212
int function_three(const std::string&) { return 1; }
1313
int function_four(bool x) { return 2; }
1414

15+
long long_fn(unsigned long a) { return 3; }
16+
1517
int const_fn() const { return 0; }
1618

1719
int getX() const { return x; }
@@ -101,6 +103,7 @@ EMSCRIPTEN_BINDINGS(Test) {
101103
.function("functionFour", &Test::function_four)
102104
.function("functionFive(x, y)", &Test::function_one)
103105
.function("functionSix(str)", &Test::function_three)
106+
.function("longFn", &Test::long_fn)
104107
.function("constFn", &Test::const_fn)
105108
.property("x", &Test::getX, &Test::setX)
106109
.property("y", &Test::getY)

test/other/embind_tsgen.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export interface Test {
66
functionFour(_0: boolean): number;
77
functionFive(x: number, y: number): number;
88
constFn(): number;
9+
longFn(_0: number): number;
910
functionThree(_0: ArrayBuffer|Uint8Array|Uint8ClampedArray|Int8Array|string): number;
1011
functionSix(str: ArrayBuffer|Uint8Array|Uint8ClampedArray|Int8Array|string): number;
1112
delete(): void;

test/other/embind_tsgen_memory64.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#include <emscripten/bind.h>
2+
#include <emscripten/val.h>
3+
4+
using namespace emscripten;
5+
6+
long long_fn(unsigned long) { return 0; }
7+
8+
EMSCRIPTEN_BINDINGS(Test) {
9+
function("longFn", &long_fn);
10+
}

test/other/embind_tsgen_memory64.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export interface MainModule {
2+
longFn(_0: bigint): bigint;
3+
}

test/test_other.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3047,6 +3047,12 @@ def test_embind_tsgen_bigint(self):
30473047
self.run_process(args + ['-sWASM_BIGINT'])
30483048
self.assertFileContents(test_file('other/embind_tsgen_bigint.d.ts'), read_file('embind_tsgen_bigint.d.ts'))
30493049

3050+
def test_embind_tsgen_memory64(self):
3051+
# Check that when memory64 is enabled longs & unsigned longs are mapped to bigint in the generated TS bindings
3052+
self.run_process([EMCC, test_file('other/embind_tsgen_memory64.cpp'),
3053+
'-lembind', '--embind-emit-tsd', 'embind_tsgen_memory64.d.ts', '-sMEMORY64'])
3054+
self.assertFileContents(test_file('other/embind_tsgen_memory64.d.ts'), read_file('embind_tsgen_memory64.d.ts'))
3055+
30503056
def test_emconfig(self):
30513057
output = self.run_process([emconfig, 'LLVM_ROOT'], stdout=PIPE).stdout.strip()
30523058
self.assertEqual(output, config.LLVM_ROOT)

tools/link.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1938,6 +1938,8 @@ def phase_embind_emit_tsd(options, wasm_target, js_syms):
19381938
setup_environment_settings()
19391939
# Use a separate Wasm file so the JS does not need to be modified after emscripten.run.
19401940
settings.SINGLE_FILE = False
1941+
# Disable support for wasm exceptions
1942+
settings.WASM_EXCEPTIONS = False
19411943
# Embind may be included multiple times, de-duplicate the list first.
19421944
settings.JS_LIBRARIES = dedup_list(settings.JS_LIBRARIES)
19431945
# Replace embind with the TypeScript generation version.
@@ -1947,7 +1949,12 @@ def phase_embind_emit_tsd(options, wasm_target, js_syms):
19471949
# The Wasm outfile may be modified by emscripten.run, so use a temporary file.
19481950
outfile_wasm = in_temp('tsgen_a.out.wasm')
19491951
emscripten.run(wasm_target, outfile_wasm, outfile_js, js_syms, False)
1950-
out = shared.run_js_tool(outfile_js, [], stdout=PIPE)
1952+
# Build the flags needed by Node.js to properly run the output file.
1953+
node_args = []
1954+
if settings.MEMORY64:
1955+
node_args += shared.node_memory64_flags()
1956+
# Run the generated JS file with the proper flags to generate the TypeScript bindings.
1957+
out = shared.run_js_tool(outfile_js, [], node_args, stdout=PIPE)
19511958
write_file(
19521959
os.path.join(os.path.dirname(wasm_target), options.embind_emit_tsd), out)
19531960
settings.restore(original_settings)

0 commit comments

Comments
 (0)