diff --git a/site/source/docs/porting/connecting_cpp_and_javascript/embind.rst b/site/source/docs/porting/connecting_cpp_and_javascript/embind.rst index b1b6e030cab38..15848f90bd132 100644 --- a/site/source/docs/porting/connecting_cpp_and_javascript/embind.rst +++ b/site/source/docs/porting/connecting_cpp_and_javascript/embind.rst @@ -1214,6 +1214,13 @@ produce `val` types. To give better type information, custom `val` types can be registered using :cpp:func:`EMSCRIPTEN_DECLARE_VAL_TYPE` in combination with :cpp:class:`emscripten::register_type`. An example below: +Two registration forms are supported: + +* Single parameter: ``register_type(definition)`` — the provided string is inlined + everywhere the type appears. +* Two parameters: ``register_type(name, definition)`` — creates a named TypeScript + type alias (``type name = definition;``) and uses ``name`` at call sites. + .. code:: cpp EMSCRIPTEN_DECLARE_VAL_TYPE(CallbackType); @@ -1226,6 +1233,9 @@ registered using :cpp:func:`EMSCRIPTEN_DECLARE_VAL_TYPE` in combination with EMSCRIPTEN_BINDINGS(custom_val) { function("function_with_callback_param", &function_with_callback_param); register_type("(message: string) => void"); + + // Named alias form (emits: type Callback = (message: string) => void;) + // register_type("Callback", "(message: string) => void"); } diff --git a/src/lib/libembind.js b/src/lib/libembind.js index e76f744a525a6..090803012a1ac 100644 --- a/src/lib/libembind.js +++ b/src/lib/libembind.js @@ -568,6 +568,11 @@ var LibraryEmbind = { __embind_register_emval(rawType); }, + _embind_register_user_type_definition__deps: ['_embind_register_emval'], + _embind_register_user_type_definition: (rawType, name, definition) => { + __embind_register_emval(rawType); + }, + _embind_register_optional__deps: ['$registerType', '$EmValOptionalType'], _embind_register_optional: (rawOptionalType, rawType) => { registerType(rawOptionalType, EmValOptionalType); diff --git a/src/lib/libembind_gen.js b/src/lib/libembind_gen.js index dba7bcb992681..28768a1745ebc 100644 --- a/src/lib/libembind_gen.js +++ b/src/lib/libembind_gen.js @@ -36,6 +36,18 @@ var LibraryEmbind = { this.destructorType = 'none'; // Same as emval. } }, + $UserTypeDefinition: class { + constructor(typeId, name, definition) { + this.typeId = typeId; + this.name = name; + this.definition = definition; + this.destructorType = 'none'; // Same as emval. + } + + print(nameMap, out) { + out.push(`type ${this.name} = ${this.definition};\n\n`); + } + }, $OptionalType: class { constructor(type) { this.type = type; @@ -563,6 +575,14 @@ var LibraryEmbind = { name = AsciiToString(name); registerType(rawType, new UserType(rawType, name)); }, + _embind_register_user_type_definition__deps: ['$registerType', '$AsciiToString', '$UserTypeDefinition'], + _embind_register_user_type_definition: (rawType, name, definition) => { + name = AsciiToString(name); + definition = AsciiToString(definition); + const userTypeDef = new UserTypeDefinition(rawType, name, definition); + registerType(rawType, userTypeDef); + moduleDefinitions.push(userTypeDef); + }, _embind_register_optional__deps: ['$OptionalType'], _embind_register_optional: (rawOptionalType, rawType) => { whenDependentTypesAreResolved([rawOptionalType], [rawType], function(type) { diff --git a/src/lib/libsigs.js b/src/lib/libsigs.js index 46c2e1df16f08..739a8b85bd5a2 100644 --- a/src/lib/libsigs.js +++ b/src/lib/libsigs.js @@ -307,6 +307,7 @@ sigs = { _embind_register_std_string__sig: 'vpp', _embind_register_std_wstring__sig: 'vppp', _embind_register_user_type__sig: 'vpp', + _embind_register_user_type_definition__sig: 'vppp', _embind_register_value_array__sig: 'vpppppp', _embind_register_value_array_element__sig: 'vppppppppp', _embind_register_value_object__sig: 'vpppppp', diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h index 9bceabd53481e..c630596f9ce78 100644 --- a/system/include/emscripten/bind.h +++ b/system/include/emscripten/bind.h @@ -262,6 +262,11 @@ void _embind_register_user_type( TYPEID type, const char* typeName); +void _embind_register_user_type_definition( + TYPEID type, + const char* typeName, + const char* typeDefinition); + // Register an InitFunc in the global linked list of init functions. void _embind_register_bindings(struct InitFunc* f); @@ -2223,6 +2228,12 @@ inline void register_type(const char* name) { _embind_register_user_type(TypeID::get(), name); } +template +inline void register_type(const char* name, const char* definition) { + using namespace internal; + _embind_register_user_type_definition(TypeID::get(), name, definition); +} + // EMSCRIPTEN_BINDINGS creates a static struct to initialize the binding which // will get included in the program if the translation unit in which it is // defined gets linked into the program. Using a C++ constructor here ensures it diff --git a/test/other/embind_tsgen.cpp b/test/other/embind_tsgen.cpp index 66bfe440d86ac..2d2d31bb52026 100644 --- a/test/other/embind_tsgen.cpp +++ b/test/other/embind_tsgen.cpp @@ -64,6 +64,9 @@ struct ValObj { ValObj() : callback(val::undefined()) {} }; +EMSCRIPTEN_DECLARE_VAL_TYPE(AliasedVal); + + ValObj getValObj() { ValObj o; return o; @@ -104,6 +107,9 @@ int function_with_callback_param(CallbackType ct) { return 0; } +void function_consuming_aliased_val(AliasedVal) { +} + int global_fn(int, int) { return 0; } std::string string_test(std::string arg) { @@ -240,7 +246,11 @@ EMSCRIPTEN_BINDINGS(Test) { function("function_with_callback_param", &function_with_callback_param); + function("function_consuming_aliased_val", + &function_consuming_aliased_val); + register_type("(message: string) => void"); + register_type("AliasedVal", "number"); class_("BaseClass").function("fn", &BaseClass::fn); diff --git a/test/other/embind_tsgen.d.ts b/test/other/embind_tsgen.d.ts index c161ac92be10f..cfbaeb98eea07 100644 --- a/test/other/embind_tsgen.d.ts +++ b/test/other/embind_tsgen.d.ts @@ -73,6 +73,8 @@ export interface ClassWithSmartPtrConstructor extends ClassHandle { fn(_0: number): number; } +type AliasedVal = number; + export interface BaseClass extends ClassHandle { fn(_0: number): number; } @@ -139,6 +141,7 @@ interface EmbindModule { extend(_0: EmbindString, _1: any): any; }; InterfaceWrapper: {}; + function_consuming_aliased_val(_0: AliasedVal): void; a_bool: boolean; an_int: number; optional_test(_0?: Foo): number | undefined; diff --git a/test/other/embind_tsgen_ignore_1.d.ts b/test/other/embind_tsgen_ignore_1.d.ts index 3dc40a2fcfc85..24a8944ddd687 100644 --- a/test/other/embind_tsgen_ignore_1.d.ts +++ b/test/other/embind_tsgen_ignore_1.d.ts @@ -84,6 +84,8 @@ export interface ClassWithSmartPtrConstructor extends ClassHandle { fn(_0: number): number; } +type AliasedVal = number; + export interface BaseClass extends ClassHandle { fn(_0: number): number; } @@ -150,6 +152,7 @@ interface EmbindModule { extend(_0: EmbindString, _1: any): any; }; InterfaceWrapper: {}; + function_consuming_aliased_val(_0: AliasedVal): void; a_bool: boolean; an_int: number; optional_test(_0?: Foo): number | undefined; diff --git a/test/other/embind_tsgen_ignore_2.d.ts b/test/other/embind_tsgen_ignore_2.d.ts index f66c9ce2fbe71..a421c6d76be74 100644 --- a/test/other/embind_tsgen_ignore_2.d.ts +++ b/test/other/embind_tsgen_ignore_2.d.ts @@ -72,6 +72,8 @@ export interface ClassWithSmartPtrConstructor extends ClassHandle { fn(_0: number): number; } +type AliasedVal = number; + export interface BaseClass extends ClassHandle { fn(_0: number): number; } @@ -138,6 +140,7 @@ interface EmbindModule { extend(_0: EmbindString, _1: any): any; }; InterfaceWrapper: {}; + function_consuming_aliased_val(_0: AliasedVal): void; a_bool: boolean; an_int: number; optional_test(_0?: Foo): number | undefined; diff --git a/test/other/embind_tsgen_ignore_3.d.ts b/test/other/embind_tsgen_ignore_3.d.ts index c161ac92be10f..cfbaeb98eea07 100644 --- a/test/other/embind_tsgen_ignore_3.d.ts +++ b/test/other/embind_tsgen_ignore_3.d.ts @@ -73,6 +73,8 @@ export interface ClassWithSmartPtrConstructor extends ClassHandle { fn(_0: number): number; } +type AliasedVal = number; + export interface BaseClass extends ClassHandle { fn(_0: number): number; } @@ -139,6 +141,7 @@ interface EmbindModule { extend(_0: EmbindString, _1: any): any; }; InterfaceWrapper: {}; + function_consuming_aliased_val(_0: AliasedVal): void; a_bool: boolean; an_int: number; optional_test(_0?: Foo): number | undefined; diff --git a/test/other/embind_tsgen_module.d.ts b/test/other/embind_tsgen_module.d.ts index e7bed1474ac9c..8b54de0698c57 100644 --- a/test/other/embind_tsgen_module.d.ts +++ b/test/other/embind_tsgen_module.d.ts @@ -73,6 +73,8 @@ export interface ClassWithSmartPtrConstructor extends ClassHandle { fn(_0: number): number; } +type AliasedVal = number; + export interface BaseClass extends ClassHandle { fn(_0: number): number; } @@ -139,6 +141,7 @@ interface EmbindModule { extend(_0: EmbindString, _1: any): any; }; InterfaceWrapper: {}; + function_consuming_aliased_val(_0: AliasedVal): void; a_bool: boolean; an_int: number; optional_test(_0?: Foo): number | undefined;