aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChad Austin <chad@imvu.com>2013-04-03 19:50:50 -0700
committerJukka Jylänki <jujjyl@gmail.com>2013-04-12 14:27:19 +0300
commitf508d6306ff0be4966d3f26b99a26c46f7c2c1ef (patch)
tree352dd1ce42319b225794db40ee510dc86743e36b
parentd4bf6fbe297ea7e5720b49bfa6fc58b696540144 (diff)
Allow value_tuple and value_struct to be registered as global constants. This involved reworking how value_struct and value_tuple are registered.
-rwxr-xr-xsrc/embind/embind.js248
-rwxr-xr-xsystem/include/emscripten/bind.h26
-rwxr-xr-xtests/embind/embind.test.js3
-rw-r--r--tests/embind/embind_test.cpp7
4 files changed, 173 insertions, 111 deletions
diff --git a/src/embind/embind.js b/src/embind/embind.js
index 46fdeee4..37439912 100755
--- a/src/embind/embind.js
+++ b/src/embind/embind.js
@@ -407,37 +407,15 @@ function __embind_register_function(name, argCount, rawArgTypesAddr, rawInvoker,
});
}
+var tupleRegistrations = {};
+
function __embind_register_tuple(rawType, name, rawConstructor, rawDestructor) {
- name = Pointer_stringify(name);
- rawConstructor = FUNCTION_TABLE[rawConstructor];
- rawDestructor = FUNCTION_TABLE[rawDestructor];
- registerType(rawType, {
- name: name,
- rawConstructor: rawConstructor,
- rawDestructor: rawDestructor,
+ tupleRegistrations[rawType] = {
+ name: Pointer_stringify(name),
+ rawConstructor: FUNCTION_TABLE[rawConstructor],
+ rawDestructor: FUNCTION_TABLE[rawDestructor],
elements: [],
- fromWireType: function(ptr) {
- var len = this.elements.length;
- var rv = new Array(len);
- for (var i = 0; i < len; ++i) {
- rv[i] = this.elements[i].read(ptr);
- }
- this.rawDestructor(ptr);
- return rv;
- },
- toWireType: function(destructors, o) {
- var len = this.elements.length;
- if (len !== o.length) {
- throw new TypeError("Incorrect number of tuple elements");
- }
- var ptr = this.rawConstructor();
- for (var i = 0; i < len; ++i) {
- this.elements[i].write(ptr, o[i]);
- }
- destructors.push(rawDestructor, ptr);
- return ptr;
- },
- });
+ };
}
function __embind_register_tuple_element(
@@ -449,78 +427,84 @@ function __embind_register_tuple_element(
setter,
setterContext
) {
- var tupleType = requireRegisteredType(rawTupleType, 'tuple');
- getter = FUNCTION_TABLE[getter];
- setter = FUNCTION_TABLE[setter];
+ tupleRegistrations[rawTupleType].elements.push({
+ getterReturnType: getterReturnType,
+ getter: FUNCTION_TABLE[getter],
+ getterContext: getterContext,
+ setterArgumentType: setterArgumentType,
+ setter: FUNCTION_TABLE[setter],
+ setterContext: setterContext,
+ });
+}
- var index = tupleType.elements.length;
- tupleType.elements.push(undefined);
-
- // TODO: test incomplete registration of value tuples
- whenDependentTypesAreResolved([], [getterReturnType, setterArgumentType], function(types) {
- var getterReturnType = types[0];
- var setterArgumentType = types[1];
- tupleType.elements[index] = {
- read: function(ptr) {
- return getterReturnType.fromWireType(
- getter(
- getterContext,
- ptr));
- },
- write: function(ptr, o) {
+function __embind_finalize_tuple(rawTupleType) {
+ var reg = tupleRegistrations[rawTupleType];
+ delete tupleRegistrations[rawTupleType];
+ var elements = reg.elements;
+ var elementsLength = elements.length;
+ var elementTypes = elements.map(function(elt) { return elt.getterReturnType; }).
+ concat(elements.map(function(elt) { return elt.setterArgumentType; }));
+
+ var rawConstructor = reg.rawConstructor;
+ var rawDestructor = reg.rawDestructor;
+
+ whenDependentTypesAreResolved([rawTupleType], elementTypes, function(elementTypes) {
+ elements.forEach(function(elt, i) {
+ var getterReturnType = elementTypes[i];
+ var getter = elt.getter;
+ var getterContext = elt.getterContext;
+ var setterArgumentType = elementTypes[i + elementsLength];
+ var setter = elt.setter;
+ var setterContext = elt.setterContext;
+ elt.read = function(ptr) {
+ return getterReturnType.fromWireType(getter(getterContext, ptr));
+ };
+ elt.write = function(ptr, o) {
var destructors = [];
- setter(
- setterContext,
- ptr,
- setterArgumentType.toWireType(destructors, o));
+ setter(setterContext, ptr, setterArgumentType.toWireType(destructors, o));
runDestructors(destructors);
- }
- };
- return [];
+ };
+ });
+
+ return [{
+ name: reg.name,
+ fromWireType: function(ptr) {
+ var rv = new Array(elementsLength);
+ for (var i = 0; i < elementsLength; ++i) {
+ rv[i] = elements[i].read(ptr);
+ }
+ rawDestructor(ptr);
+ return rv;
+ },
+ toWireType: function(destructors, o) {
+ if (elementsLength !== o.length) {
+ throw new TypeError("Incorrect number of tuple elements");
+ }
+ var ptr = rawConstructor();
+ for (var i = 0; i < elementsLength; ++i) {
+ elements[i].write(ptr, o[i]);
+ }
+ destructors.push(rawDestructor, ptr);
+ return ptr;
+ },
+ }];
});
}
+var structRegistrations = {};
+
function __embind_register_struct(
rawType,
name,
rawConstructor,
rawDestructor
) {
- name = Pointer_stringify(name);
- rawConstructor = FUNCTION_TABLE[rawConstructor];
- rawDestructor = FUNCTION_TABLE[rawDestructor];
-
- registerType(rawType, {
- name: name,
- rawConstructor: rawConstructor,
- rawDestructor: rawDestructor,
- fields: {},
- fromWireType: function(ptr) {
- var fields = this.fields;
- var rv = {};
- for (var i in fields) {
- rv[i] = fields[i].read(ptr);
- }
- this.rawDestructor(ptr);
- return rv;
- },
- toWireType: function(destructors, o) {
- var fields = this.fields;
- // todo: Here we have an opportunity for -O3 level "unsafe" optimizations:
- // assume all fields are present without checking.
- for (var fieldName in fields) {
- if (!(fieldName in o)) {
- throw new TypeError('Missing field');
- }
- }
- var ptr = this.rawConstructor();
- for (fieldName in fields) {
- fields[fieldName].write(ptr, o[fieldName]);
- }
- destructors.push(rawDestructor, ptr);
- return ptr;
- },
- });
+ structRegistrations[rawType] = {
+ name: Pointer_stringify(name),
+ rawConstructor: FUNCTION_TABLE[rawConstructor],
+ rawDestructor: FUNCTION_TABLE[rawDestructor],
+ fields: [],
+ };
}
function __embind_register_struct_field(
@@ -533,27 +517,75 @@ function __embind_register_struct_field(
setter,
setterContext
) {
- structType = requireRegisteredType(structType, 'struct');
- fieldName = Pointer_stringify(fieldName);
- getter = FUNCTION_TABLE[getter];
- setter = FUNCTION_TABLE[setter];
+ structRegistrations[structType].fields.push({
+ fieldName: Pointer_stringify(fieldName),
+ getterReturnType: getterReturnType,
+ getter: FUNCTION_TABLE[getter],
+ getterContext: getterContext,
+ setterArgumentType: setterArgumentType,
+ setter: FUNCTION_TABLE[setter],
+ setterContext: setterContext,
+ });
+}
+
+function __embind_finalize_struct(structType) {
+ var reg = structRegistrations[structType];
+ delete structRegistrations[structType];
+
+ var rawConstructor = reg.rawConstructor;
+ var rawDestructor = reg.rawDestructor;
+ var fieldRecords = reg.fields;
+ var fieldTypes = fieldRecords.map(function(field) { return field.getterReturnType; }).
+ concat(fieldRecords.map(function(field) { return field.setterArgumentType; }));
+ whenDependentTypesAreResolved([structType], fieldTypes, function(fieldTypes) {
+ var fields = {};
+ fieldRecords.forEach(function(field, i) {
+ var fieldName = field.fieldName;
+ var getterReturnType = fieldTypes[i];
+ var getter = field.getter;
+ var getterContext = field.getterContext;
+ var setterArgumentType = fieldTypes[i + fieldRecords.length];
+ var setter = field.setter;
+ var setterContext = field.setterContext;
+ fields[fieldName] = {
+ read: function(ptr) {
+ return getterReturnType.fromWireType(
+ getter(getterContext, ptr));
+ },
+ write: function(ptr, o) {
+ var destructors = [];
+ setter(setterContext, ptr, setterArgumentType.toWireType(destructors, o));
+ runDestructors(destructors);
+ }
+ };
+ });
- // TODO: test incomplete registration of value structs
- whenDependentTypesAreResolved([], [getterReturnType, setterArgumentType], function(types) {
- var getterReturnType = types[0];
- var setterArgumentType = types[1];
- structType.fields[fieldName] = {
- read: function(ptr) {
- return getterReturnType.fromWireType(
- getter(getterContext, ptr));
+ return [{
+ name: reg.name,
+ fromWireType: function(ptr) {
+ var rv = {};
+ for (var i in fields) {
+ rv[i] = fields[i].read(ptr);
+ }
+ rawDestructor(ptr);
+ return rv;
},
- write: function(ptr, o) {
- var destructors = [];
- setter(setterContext, ptr, setterArgumentType.toWireType(destructors, o));
- runDestructors(destructors);
- }
- };
- return [];
+ toWireType: function(destructors, o) {
+ // todo: Here we have an opportunity for -O3 level "unsafe" optimizations:
+ // assume all fields are present without checking.
+ for (var fieldName in fields) {
+ if (!(fieldName in o)) {
+ throw new TypeError('Missing field');
+ }
+ }
+ var ptr = rawConstructor();
+ for (fieldName in fields) {
+ fields[fieldName].write(ptr, o[fieldName]);
+ }
+ destructors.push(rawDestructor, ptr);
+ return ptr;
+ },
+ }];
});
}
diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h
index e767afaa..bd170dea 100755
--- a/system/include/emscripten/bind.h
+++ b/system/include/emscripten/bind.h
@@ -77,6 +77,8 @@ namespace emscripten {
GenericFunction setter,
void* setterContext);
+ void _embind_finalize_tuple(TYPEID tupleType);
+
void _embind_register_struct(
TYPEID structType,
const char* fieldName,
@@ -93,6 +95,8 @@ namespace emscripten {
GenericFunction setter,
void* setterContext);
+ void _embind_finalize_struct(TYPEID structType);
+
void _embind_register_smart_ptr(
TYPEID pointerType,
TYPEID pointeeType,
@@ -458,6 +462,15 @@ namespace emscripten {
return internal::getContext(context);
}
};
+
+ class noncopyable {
+ protected:
+ noncopyable() {}
+ ~noncopyable() {}
+ private:
+ noncopyable(const noncopyable&) = delete;
+ const noncopyable& operator=(const noncopyable&) = delete;
+ };
}
////////////////////////////////////////////////////////////////////////////////
@@ -465,7 +478,7 @@ namespace emscripten {
////////////////////////////////////////////////////////////////////////////////
template<typename ClassType>
- class value_tuple {
+ class value_tuple : public internal::noncopyable {
public:
value_tuple(const char* name) {
using namespace internal;
@@ -476,6 +489,11 @@ namespace emscripten {
reinterpret_cast<GenericFunction>(&raw_destructor<ClassType>));
}
+ ~value_tuple() {
+ using namespace internal;
+ _embind_finalize_tuple(TypeID<ClassType>::get());
+ }
+
template<typename InstanceType, typename ElementType>
value_tuple& element(ElementType InstanceType::*field) {
using namespace internal;
@@ -516,7 +534,7 @@ namespace emscripten {
////////////////////////////////////////////////////////////////////////////////
template<typename ClassType>
- class value_struct {
+ class value_struct : public internal::noncopyable {
public:
value_struct(const char* name) {
using namespace internal;
@@ -527,6 +545,10 @@ namespace emscripten {
reinterpret_cast<GenericFunction>(&raw_destructor<ClassType>));
}
+ ~value_struct() {
+ _embind_finalize_struct(internal::TypeID<ClassType>::get());
+ }
+
template<typename InstanceType, typename FieldType>
value_struct& field(const char* fieldName, FieldType InstanceType::*field) {
using namespace internal;
diff --git a/tests/embind/embind.test.js b/tests/embind/embind.test.js
index 7bb3985f..11746214 100755
--- a/tests/embind/embind.test.js
+++ b/tests/embind/embind.test.js
@@ -1519,7 +1519,8 @@ module({
BaseFixture.extend("constants", function() {
assert.equal(10, cm.INT_CONSTANT);
assert.equal("some string", cm.STRING_CONSTANT);
- //assert.deepEqual([1, 2, 3], cm.VALUE_TUPLE_CONSTANT);
+ assert.deepEqual([1, 2, 3], cm.VALUE_TUPLE_CONSTANT);
+ assert.deepEqual({x:1,y:2,z:3}, cm.VALUE_STRUCT_CONSTANT);
});
});
diff --git a/tests/embind/embind_test.cpp b/tests/embind/embind_test.cpp
index 4d1b376b..be089f9f 100644
--- a/tests/embind/embind_test.cpp
+++ b/tests/embind/embind_test.cpp
@@ -1355,11 +1355,18 @@ int overloaded_function(int i, int j)
EMSCRIPTEN_BINDINGS(constants) {
constant("INT_CONSTANT", 10);
constant("STRING_CONSTANT", std::string("some string"));
+
TupleVector tv;
tv.x = 1;
tv.y = 2;
tv.z = 3;
constant("VALUE_TUPLE_CONSTANT", tv);
+
+ StructVector sv;
+ sv.x = 1;
+ sv.y = 2;
+ sv.z = 3;
+ constant("VALUE_STRUCT_CONSTANT", sv);
}
EMSCRIPTEN_BINDINGS(tests) {