diff options
Diffstat (limited to 'system')
-rw-r--r--[-rwxr-xr-x] | system/include/emscripten/bind.h | 62 | ||||
-rw-r--r-- | system/include/emscripten/val.h | 116 | ||||
-rw-r--r--[-rwxr-xr-x] | system/include/emscripten/wire.h | 81 | ||||
-rw-r--r-- | system/include/netdb.h | 2 | ||||
-rw-r--r-- | system/lib/embind/bind.cpp | 1 | ||||
-rw-r--r-- | system/lib/sdl.cpp | 13 | ||||
-rw-r--r-- | system/lib/sdl.symbols | 1 |
7 files changed, 170 insertions, 106 deletions
diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h index 7aa2a55e..cd465e45 100755..100644 --- a/system/include/emscripten/bind.h +++ b/system/include/emscripten/bind.h @@ -18,7 +18,6 @@ namespace emscripten { }; namespace internal { - typedef void (*GenericFunction)(); typedef long GenericEnumValue; // Implemented in JavaScript. Don't call these directly. @@ -60,6 +59,10 @@ namespace emscripten { TYPEID emvalType, const char* name); + void _embind_register_memory_view( + TYPEID memoryViewType, + const char* name); + void _embind_register_function( const char* name, unsigned argCount, @@ -414,11 +417,10 @@ namespace emscripten { // TODO: This could do a reinterpret-cast if sizeof(T) === sizeof(void*) template<typename T> - inline void* getContext(const T& t) { + inline T* getContext(const T& t) { // not a leak because this is called once per binding - void* p = malloc(sizeof(T)); - assert(p); - memcpy(p, &t, sizeof(T)); + T* p = reinterpret_cast<T*>(malloc(sizeof(T))); + new(p) T(t); return p; } @@ -749,38 +751,19 @@ namespace emscripten { template<typename ReturnType, typename... Args> ReturnType call(const char* name, Args&&... args) const { - return Caller<ReturnType, Args...>::call(wrapped, name, std::forward<Args>(args)...); + return wrapped.call<ReturnType>(name, std::forward<Args>(args)...); } template<typename ReturnType, typename... Args, typename Default> ReturnType optional_call(const char* name, Default def, Args&&... args) const { - if (has_function(name)) { - return Caller<ReturnType, Args...>::call(wrapped, name, std::forward<Args>(args)...); + if (wrapped.has_function(name)) { + return call<ReturnType>(name, std::forward<Args>(args)...); } else { return def(); } } private: - bool has_function(const char* name) const { - return wrapped.has_function(name); - } - - // this class only exists because you can't partially specialize function templates - template<typename ReturnType, typename... Args> - struct Caller { - static ReturnType call(const val& v, const char* name, Args&&... args) { - return v.call(name, std::forward<Args>(args)...).template as<ReturnType>(); - } - }; - - template<typename... Args> - struct Caller<void, Args...> { - static void call(const val& v, const char* name, Args&&... args) { - v.call_void(name, std::forward<Args>(args)...); - } - }; - val wrapped; }; @@ -844,23 +827,8 @@ namespace emscripten { } }; - template<typename PointerType> - struct ptr { - typedef PointerType pointer_type; - }; - namespace internal { template<typename T> - struct is_ptr { - enum { value = false }; - }; - - template<typename T> - struct is_ptr<ptr<T>> { - enum { value = true }; - }; - - template<typename T> struct SmartPtrIfNeeded { template<typename U> SmartPtrIfNeeded(U& cls) { @@ -881,7 +849,6 @@ namespace emscripten { public: class_() = delete; - template<typename = typename std::enable_if<!internal::is_ptr<ClassType>::value>::type> explicit class_(const char* name) { using namespace internal; @@ -927,16 +894,17 @@ namespace emscripten { policies...); } - template<typename... Args, typename... Policies> - class_& constructor(ClassType* (*factory)(Args...), Policies...) { + template<typename... Args, typename ReturnType, typename... Policies> + class_& constructor(ReturnType (*factory)(Args...), Policies...) { using namespace internal; - typename WithPolicies<Policies...>::template ArgTypeList<AllowedRawPointer<ClassType>, Args...> args; + // TODO: allows all raw pointers... policies need a rethink + typename WithPolicies<allow_raw_pointers, Policies...>::template ArgTypeList<ReturnType, Args...> args; _embind_register_class_constructor( TypeID<ClassType>::get(), args.count, args.types, - reinterpret_cast<GenericFunction>(&Invoker<ClassType*, Args...>::invoke), + reinterpret_cast<GenericFunction>(&Invoker<ReturnType, Args...>::invoke), reinterpret_cast<GenericFunction>(factory)); return *this; } diff --git a/system/include/emscripten/val.h b/system/include/emscripten/val.h index edd070e3..b712d164 100644 --- a/system/include/emscripten/val.h +++ b/system/include/emscripten/val.h @@ -10,7 +10,6 @@ namespace emscripten { extern "C" { void _emval_register_symbol(const char*); - typedef struct _EM_SIG* EM_SIG; typedef struct _EM_VAL* EM_VAL; void _emval_incref(EM_VAL value); @@ -39,34 +38,67 @@ namespace emscripten { unsigned argCount, internal::TYPEID argTypes[] /*, ... */); - EM_VAL _emval_call_method( - EM_VAL value, - const char* methodName, - unsigned argCount, - internal::TYPEID argTypes[] - /*, ... */); - void _emval_call_void_method( - EM_VAL value, - const char* methodName, - unsigned argCount, - internal::TYPEID argTypes[] - /*, ...*/); + + // DO NOT call this more than once per signature. It will leak function pointer offsets! + GenericFunction _emval_get_method_caller( + unsigned argCount, // including return value + internal::TYPEID argTypes[]); bool _emval_has_function( EM_VAL value, const char* methodName); } - } - template<const char* address> - struct symbol_registrar { - symbol_registrar() { - internal::_emval_register_symbol(address); - } - }; + template<const char* address> + struct symbol_registrar { + symbol_registrar() { + internal::_emval_register_symbol(address); + } + }; + + template<typename ReturnType, typename... Args> + struct Signature { + typedef typename BindingType<ReturnType>::WireType (*MethodCaller)(EM_VAL value, const char* methodName, typename BindingType<Args>::WireType...); + + static MethodCaller get_method_caller() { + static MethodCaller fp = reinterpret_cast<MethodCaller>(init_method_caller()); + return fp; + } + + private: + static GenericFunction init_method_caller() { + WithPolicies<>::ArgTypeList<ReturnType, Args...> args; + return _emval_get_method_caller(args.count, args.types); + } + }; + + template<typename ReturnType, typename... Args> + struct MethodCaller { + static ReturnType call(EM_VAL handle, const char* methodName, Args&&... args) { + auto caller = Signature<ReturnType, Args...>::get_method_caller(); + auto wireType = caller( + handle, + methodName, + toWireType(std::forward<Args>(args))...); + WireDeleter<ReturnType> deleter(wireType); + return BindingType<ReturnType>::fromWireType(wireType); + } + }; + + template<typename... Args> + struct MethodCaller<void, Args...> { + static void call(EM_VAL handle, const char* methodName, Args&&... args) { + auto caller = Signature<void, Args...>::get_method_caller(); + return caller( + handle, + methodName, + toWireType(std::forward<Args>(args))...); + } + }; + } #define EMSCRIPTEN_SYMBOL(name) \ static const char name##_symbol[] = #name; \ - static const symbol_registrar<name##_symbol> name##_registrar + static const ::emscripten::internal::symbol_registrar<name##_symbol> name##_registrar class val { public: @@ -158,7 +190,7 @@ namespace emscripten { } bool hasOwnProperty(const char* key) const { - return val::global("Object")["prototype"]["hasOwnProperty"].call("call", *this, val(key)).as<bool>(); + return val::global("Object")["prototype"]["hasOwnProperty"].call<bool>("call", *this, val(key)); } template<typename... Args> @@ -211,45 +243,11 @@ namespace emscripten { toWireType(std::forward<Args>(args))...)); } - template<typename ...Args> - val call(const char* name, Args&&... args) const { + template<typename ReturnValue, typename... Args> + ReturnValue call(const char* name, Args&&... args) const { using namespace internal; - WithPolicies<>::ArgTypeList<Args...> argList; - typedef EM_VAL (*TypedCall)( - EM_VAL, - const char* name, - unsigned, - TYPEID argTypes[], - typename BindingType<Args>::WireType...); - TypedCall typedCall = reinterpret_cast<TypedCall>(&_emval_call_method); - return val( - typedCall( - handle, - name, - argList.count, - argList.types, - toWireType(std::forward<Args>(args))...)); - } - - template<typename ...Args> - void call_void(const char* name, Args&&... args) const { - using namespace internal; - - WithPolicies<>::ArgTypeList<Args...> argList; - typedef void (*TypedCall)( - EM_VAL, - const char* name, - unsigned, - TYPEID argTypes[], - typename BindingType<Args>::WireType...); - TypedCall typedCall = reinterpret_cast<TypedCall>(&_emval_call_void_method); - return typedCall( - handle, - name, - argList.count, - argList.types, - toWireType(std::forward<Args>(args))...); + return MethodCaller<ReturnValue, Args...>::call(handle, name, std::forward<Args>(args)...); } bool has_function(const char* name) const { diff --git a/system/include/emscripten/wire.h b/system/include/emscripten/wire.h index 6fb15fc7..a5892216 100755..100644 --- a/system/include/emscripten/wire.h +++ b/system/include/emscripten/wire.h @@ -13,6 +13,8 @@ namespace emscripten { namespace internal { + typedef void (*GenericFunction)(); + typedef const struct _TYPEID* TYPEID; // This implementation is technically not legal, as it's not @@ -146,6 +148,7 @@ namespace emscripten { template<> struct BindingType<void> { + typedef void WireType; }; template<> @@ -309,4 +312,82 @@ namespace emscripten { WireType wt; }; } + + struct memory_view { + enum class Type { + Int8Array, + Uint8Array, + Int16Array, + Uint16Array, + Int32Array, + Uint32Array, + Float32Array, + Float64Array, + }; + + memory_view() = delete; + explicit memory_view(size_t size, const void* data) + : type(Type::Uint8Array) + , size(size) + , data(data) + {} + explicit memory_view(Type type, size_t size, const void* data) + : type(type) + , size(size) + , data(data) + {} + + const Type type; + const size_t size; // in elements, not bytes + const void* const data; + }; + + inline memory_view typed_memory_view(size_t size, const int8_t* data) { + return memory_view(memory_view::Type::Int8Array, size, data); + } + + inline memory_view typed_memory_view(size_t size, const uint8_t* data) { + return memory_view(memory_view::Type::Uint8Array, size, data); + } + + inline memory_view typed_memory_view(size_t size, const int16_t* data) { + return memory_view(memory_view::Type::Int16Array, size, data); + } + + inline memory_view typed_memory_view(size_t size, const uint16_t* data) { + return memory_view(memory_view::Type::Uint16Array, size, data); + } + + inline memory_view typed_memory_view(size_t size, const int32_t* data) { + return memory_view(memory_view::Type::Int32Array, size, data); + } + + inline memory_view typed_memory_view(size_t size, const uint32_t* data) { + return memory_view(memory_view::Type::Uint32Array, size, data); + } + + inline memory_view typed_memory_view(size_t size, const float* data) { + return memory_view(memory_view::Type::Float32Array, size, data); + } + + inline memory_view typed_memory_view(size_t size, const double* data) { + return memory_view(memory_view::Type::Float64Array, size, data); + } + + namespace internal { + template<> + struct BindingType<memory_view> { + // This non-word-sized WireType only works because I + // happen to know that clang will pass aggregates as + // pointers to stack elements and we never support + // converting JavaScript typed arrays back into + // memory_view. (That is, fromWireType is not implemented + // on the C++ side, nor is toWireType implemented in + // JavaScript.) + typedef memory_view WireType; + static WireType toWireType(const memory_view& mv) { + return mv; + } + }; + } } diff --git a/system/include/netdb.h b/system/include/netdb.h index 147cdff4..48acdcc4 100644 --- a/system/include/netdb.h +++ b/system/include/netdb.h @@ -85,6 +85,8 @@ const char* hstrerror(int err); extern int h_errno; +#include <netinet/in.h> + #ifdef __cplusplus } #endif diff --git a/system/lib/embind/bind.cpp b/system/lib/embind/bind.cpp index ec1648a9..12264dfd 100644 --- a/system/lib/embind/bind.cpp +++ b/system/lib/embind/bind.cpp @@ -59,4 +59,5 @@ EMSCRIPTEN_BINDINGS(native_and_builtin_types) { _embind_register_std_string(TypeID<std::string>::get(), "std::string");
_embind_register_std_wstring(TypeID<std::wstring>::get(), sizeof(wchar_t), "std::wstring");
_embind_register_emval(TypeID<val>::get(), "emscripten::val");
+ _embind_register_memory_view(TypeID<memory_view>::get(), "emscripten::memory_view");
}
diff --git a/system/lib/sdl.cpp b/system/lib/sdl.cpp new file mode 100644 index 00000000..7038cdb1 --- /dev/null +++ b/system/lib/sdl.cpp @@ -0,0 +1,13 @@ + +#include <stdlib.h> + +// force malloc&free to be included in from libc +struct Force { + Force() { + void *x = malloc(10); + free(x); + } +}; + +static Force f; + diff --git a/system/lib/sdl.symbols b/system/lib/sdl.symbols new file mode 100644 index 00000000..c2c0af42 --- /dev/null +++ b/system/lib/sdl.symbols @@ -0,0 +1 @@ + W SDL_Init |