[gjs] add support for (out caller-allocates)
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs] add support for (out caller-allocates)
- Date: Fri, 19 Nov 2010 21:14:43 +0000 (UTC)
commit fd1b655863610832f65077bcf08a0c560b14d83b
Author: Maxim Ermilov <zaspire rambler ru>
Date: Thu Aug 12 02:17:01 2010 +0400
add support for (out caller-allocates)
Modified to clean up memory leaks and add comments
by Colin Walters <walters verbum org>.
https://bugzilla.gnome.org/show_bug.cgi?id=624811
gi/function.c | 76 ++++++++++++++++++++++++++++++++-
test/js/testEverythingEncapsulated.js | 14 ++++++
2 files changed, 88 insertions(+), 2 deletions(-)
---
diff --git a/gi/function.c b/gi/function.c
index 0404bdf..e83aa69 100644
--- a/gi/function.c
+++ b/gi/function.c
@@ -497,8 +497,49 @@ gjs_invoke_c_function(JSContext *context,
g_assert_cmpuint(out_args_pos, <, out_args_len);
g_assert_cmpuint(in_args_pos, <, in_args_len);
- out_arg_cvalues[out_args_pos].v_pointer = NULL;
- in_arg_cvalues[in_args_pos].v_pointer = &out_arg_cvalues[out_args_pos];
+ if (g_arg_info_is_caller_allocates(&arg_info)) {
+ GITypeTag type_tag;
+ GITypeInfo ainfo;
+
+ g_arg_info_load_type(&arg_info, &ainfo);
+ type_tag = g_type_info_get_tag(&ainfo);
+
+ switch (type_tag) {
+ case GI_TYPE_TAG_INTERFACE:
+ {
+ GIBaseInfo* interface_info;
+ GIInfoType interface_type;
+ gsize size;
+
+ interface_info = g_type_info_get_interface(&ainfo);
+ g_assert(interface_info != NULL);
+
+ interface_type = g_base_info_get_type(interface_info);
+ g_base_info_unref((GIBaseInfo*)interface_info);
+
+ if (interface_type == GI_INFO_TYPE_STRUCT) {
+ size = g_struct_info_get_size((GIStructInfo*)interface_info);
+ } else if (interface_type == GI_INFO_TYPE_UNION) {
+ size = g_union_info_get_size((GIUnionInfo*)interface_info);
+ } else {
+ failed = TRUE;
+ }
+
+ if (!failed) {
+ in_arg_cvalues[in_args_pos].v_pointer = g_slice_alloc0(size);
+ out_arg_cvalues[out_args_pos].v_pointer = in_arg_cvalues[in_args_pos].v_pointer;
+ }
+ break;
+ }
+ default:
+ failed = TRUE;
+ }
+ if (failed)
+ gjs_throw(context, "Unsupported type %s for (out caller-allocates)", g_type_tag_to_string(type_tag));
+ } else {
+ out_arg_cvalues[out_args_pos].v_pointer = NULL;
+ in_arg_cvalues[in_args_pos].v_pointer = &out_arg_cvalues[out_args_pos];
+ }
out_args_pos++;
} else {
GArgument *in_value;
@@ -696,6 +737,37 @@ release:
postinvoke_release_failed = TRUE;
}
+ /* For caller-allocates, what happens here is we allocate
+ * a structure above, then gjs_value_from_g_argument calls
+ * g_boxed_copy on it, and takes ownership of that. So
+ * here we release the memory allocated above. It would be
+ * better to special case this and directly hand JS the boxed
+ * object and tell gjs_boxed it owns the memory, but for now
+ * this works OK. We could also alloca() the structure instead
+ * of slice allocating.
+ */
+ if (g_arg_info_is_caller_allocates(&arg_info)) {
+ GITypeTag type_tag;
+ GIBaseInfo* interface_info;
+ GIInfoType interface_type;
+ gsize size;
+
+ type_tag = g_type_info_get_tag(&arg_type_info);
+ g_assert(type_tag == GI_TYPE_TAG_INTERFACE);
+ interface_info = g_type_info_get_interface(&arg_type_info);
+ interface_type = g_base_info_get_type(interface_info);
+ if (interface_type == GI_INFO_TYPE_STRUCT) {
+ size = g_struct_info_get_size((GIStructInfo*)interface_info);
+ } else if (interface_type == GI_INFO_TYPE_UNION) {
+ size = g_union_info_get_size((GIUnionInfo*)interface_info);
+ } else {
+ g_assert_not_reached();
+ }
+
+ g_slice_free1(size, out_arg_cvalues[out_args_pos].v_pointer);
+ g_base_info_unref((GIBaseInfo*)interface_info);
+ }
+
/* Free GArgument, the jsval should have ref'd or copied it */
if (!arg_failed)
gjs_g_argument_release(context,
diff --git a/test/js/testEverythingEncapsulated.js b/test/js/testEverythingEncapsulated.js
index 8dd82c2..2e4a1b3 100644
--- a/test/js/testEverythingEncapsulated.js
+++ b/test/js/testEverythingEncapsulated.js
@@ -15,6 +15,20 @@ function testStruct() {
assertEquals(43, struct.some_int8);
assertEquals(42.5, struct.some_double);
assertEquals(Everything.TestEnum.VALUE3, struct.some_enum);
+ let b = struct.clone();
+ assertEquals(42, b.some_int);
+ assertEquals(43, b.some_int8);
+ assertEquals(42.5, b.some_double);
+ assertEquals(Everything.TestEnum.VALUE3, b.some_enum);
+
+ struct = new Everything.TestStructB();
+ struct.some_int8 = 43;
+ struct.nested_a.some_int8 = 66;
+ assertEquals(43, struct.some_int8);
+ assertEquals(66, struct.nested_a.some_int8);
+ b = struct.clone();
+ assertEquals(43, b.some_int8);
+ assertEquals(66, struct.nested_a.some_int8);
}
function testStructConstructor()
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]