From 04a4c6861a471b26b6fffda00b48289aeb5d666b Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Sat, 5 Dec 2020 03:09:54 -0600 Subject: [PATCH 1/2] Fix constructor embind Adds the removed method from https://github.com/emscripten-core/emscripten/commit/ecb7bb3dcf8cc9f188cdbbc62877c2f4ad87a386#diff-b89415f247dd9bc4a13f065288c5e651 --- system/include/emscripten/bind.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h index 8f66466abad0e..f4706dff1c710 100644 --- a/system/include/emscripten/bind.h +++ b/system/include/emscripten/bind.h @@ -1475,6 +1475,24 @@ namespace emscripten { return *this; } + template + EMSCRIPTEN_ALWAYS_INLINE const class_& constructor(ReturnType (*factory)(Args...), Policies...) const { + using namespace internal; + + // TODO: allows all raw pointers... policies need a rethink + typename WithPolicies::template ArgTypeList args; + auto invoke = &Invoker::invoke; + _embind_register_class_constructor( + TypeID::get(), + args.getCount(), + args.getTypes(), + getSignature(invoke), + reinterpret_cast(invoke), + reinterpret_cast(factory)); + + return *this; + } + template EMSCRIPTEN_ALWAYS_INLINE const class_& smart_ptr_constructor(const char* smartPtrName, SmartPtr (*factory)(Args...), Policies...) const { using namespace internal; From 08abc35d4b428fe5c777191de6afe58e1b047a82 Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Mon, 18 Jan 2021 05:36:53 -0600 Subject: [PATCH 2/2] Add tests --- tests/embind/embind.test.js | 11 ++++++++ tests/embind/embind_test.cpp | 52 +++++++++++++++++++++++------------- 2 files changed, 44 insertions(+), 19 deletions(-) diff --git a/tests/embind/embind.test.js b/tests/embind/embind.test.js index 0b94824bf2b02..7ee0f5107fae0 100644 --- a/tests/embind/embind.test.js +++ b/tests/embind/embind.test.js @@ -1277,6 +1277,17 @@ module({ b.delete(); }); + test("functions as class constructors", function() { + var a = new cm.ConstructFromFunction({optionA: true}); + assert.equal(true, a.optionA); + + var b = new cm.ConstructFromFunction(); + assert.equal(false, b.optionA); + + a.delete(); + b.delete(); + }); + test("function objects as class methods", function() { var b = cm.ValHolder.makeValHolder("foo"); diff --git a/tests/embind/embind_test.cpp b/tests/embind/embind_test.cpp index e857d38fb87ba..916596181735a 100644 --- a/tests/embind/embind_test.cpp +++ b/tests/embind/embind_test.cpp @@ -341,7 +341,7 @@ class SharedPtrHolder { std::shared_ptr get() const { return ptr_; } - + void set(std::shared_ptr p) { ptr_ = p; } @@ -988,11 +988,11 @@ class UniquePtrToConstructor { UniquePtrToConstructor(std::unique_ptr p) : value(*p) {} - + int getValue() const { return value; } - + private: int value; }; @@ -1412,7 +1412,7 @@ EMSCRIPTEN_BINDINGS(interface_tests) { self.AbstractClass::passVal(v); })) ; - + function("getAbstractClass", &getAbstractClass); function("callAbstractMethod", &callAbstractMethod); function("callOptionalMethod", &callOptionalMethod); @@ -1500,7 +1500,7 @@ class CustomSmartPtr { ~CustomSmartPtr() { verify(); std::fill(d_, d_ + N_, Deleted); - + if (ptr_ && --ptr_->refcount == 0) { delete ptr_; } @@ -1751,6 +1751,16 @@ ConstructFromFunctor construct_from_functor_mixin(const val& v, int i) return {v, i}; } +struct ConstructFromFunction { + bool optionA; + ConstructFromFunction(bool optionA_): optionA{optionA_} {}; +}; + +ConstructFromFunction* ConstructFromFunctionConstructor(emscripten::val value) { + bool optionA = (value.as() && value["optionA"].as()); + return new ConstructFromFunction(optionA); +} + EMSCRIPTEN_BINDINGS(tests) { register_vector("IntegerVector"); register_vector("CharVector"); @@ -1873,6 +1883,10 @@ EMSCRIPTEN_BINDINGS(tests) { .function("getA", &ConstructFromFunctor<2>::getA) ; + class_("ConstructFromFunction") + .constructor(&ConstructFromFunctionConstructor) + ; + class_("ValHolder") .smart_ptr>("std::shared_ptr") .constructor() @@ -1929,7 +1943,7 @@ EMSCRIPTEN_BINDINGS(tests) { .function("get", &StringHolder::get) .function("get_const_ref", &StringHolder::get_const_ref) ; - + class_("SharedPtrHolder") .constructor<>() .function("get", &SharedPtrHolder::get) @@ -2002,7 +2016,7 @@ EMSCRIPTEN_BINDINGS(tests) { .property("member", &SecondBase::member) .property("secondBaseMember", &SecondBase::secondBaseMember) ; - + class_("DerivedHolder") .constructor<>() @@ -2017,7 +2031,7 @@ EMSCRIPTEN_BINDINGS(tests) { .constructor<>() .function("getClassName", &SiblingDerived::getClassName) ; - + class_>("MultiplyDerived") .smart_ptr>("shared_ptr") .constructor<>() @@ -2094,7 +2108,7 @@ EMSCRIPTEN_BINDINGS(tests) { .constructor<>() .function("getClassName", &PolyDiamondBase::getClassName) ; - + class_("PolyDiamondDerived") .smart_ptr>("shared_ptr") .constructor<>() @@ -2339,10 +2353,10 @@ class MultipleSmartCtors { class MultipleOverloads { public: MultipleOverloads() {} - + int value; static int staticValue; - + int Func(int i) { assert(i == 10); value = 1; @@ -2358,7 +2372,7 @@ class MultipleOverloads { int WhichFuncCalled() const { return value; } - + static int StaticFunc(int i) { assert(i == 10); staticValue = 1; @@ -2381,7 +2395,7 @@ int MultipleOverloads::staticValue = 0; class MultipleOverloadsDerived : public MultipleOverloads { public: MultipleOverloadsDerived() {} - + int Func(int i, int j, int k) { assert(i == 30); assert(j == 30); @@ -2397,7 +2411,7 @@ class MultipleOverloadsDerived : public MultipleOverloads { value = 4; return 4; } - + static int StaticFunc(int i, int j, int k) { assert(i == 30); assert(j == 30); @@ -2476,14 +2490,14 @@ EMSCRIPTEN_BINDINGS(overloads) { .constructor() .function("WhichCtorCalled", &MultipleCtors::WhichCtorCalled) ; - + class_("MultipleSmartCtors") .smart_ptr>("shared_ptr") .constructor(&std::make_shared) .constructor(&std::make_shared) .function("WhichCtorCalled", &MultipleSmartCtors::WhichCtorCalled) ; - + class_("MultipleOverloads") .constructor<>() .function("Func", select_overload(&MultipleOverloads::Func)) @@ -2560,7 +2574,7 @@ EMSCRIPTEN_BINDINGS(order) { .field("first", &OrderedStruct::first) .field("second", &OrderedStruct::second) ; - + class_("SecondElement") ; @@ -2644,7 +2658,7 @@ EMSCRIPTEN_BINDINGS(incomplete) { class Noncopyable { Noncopyable(const Noncopyable&) = delete; Noncopyable& operator=(const Noncopyable&) = delete; - + public: Noncopyable() {} Noncopyable(Noncopyable&& other) { @@ -2709,7 +2723,7 @@ EMSCRIPTEN_BINDINGS(constants) { constant("VALUE_OBJECT_CONSTANT", sv); } -class DerivedWithOffset : public DummyDataToTestPointerAdjustment, public Base { +class DerivedWithOffset : public DummyDataToTestPointerAdjustment, public Base { }; std::shared_ptr return_Base_from_DerivedWithOffset(std::shared_ptr ptr) {