[gjs: 6/26] boxed: Move to C++-style API
- From: Cosimo Cecchi <cosimoc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs: 6/26] boxed: Move to C++-style API
- Date: Sun, 14 Apr 2019 14:03:52 +0000 (UTC)
commit 14f1253c134a4870ad9e6b2317e4072f653326f6
Author: Philip Chimento <philip chimento gmail com>
Date: Sun Jan 20 17:44:45 2019 -0800
boxed: Move to C++-style API
This allows cleaning up the public API in boxed.h a bit, changing some
methods to be private, adding missing error checks in calling code, and
creating a BoxedInstance::new_for_c_struct() method with a
BoxedInstance::NoCopy overload.
The idea is to gradually provide more typesafe, C++-style APIs for all
of the GI wrapper classes, and change calling code to use them rather
than the old C-style APIs.
gi/arg.cpp | 17 ++++++-----------
gi/boxed.cpp | 52 +++++++++++++++++++++++++++++++++++++++++-----------
gi/boxed.h | 40 ++++++++++++++++------------------------
gi/gerror.cpp | 2 +-
gi/repo.cpp | 2 +-
gi/value.cpp | 8 ++++----
gjs/byteArray.cpp | 9 +++++----
7 files changed, 74 insertions(+), 56 deletions(-)
---
diff --git a/gi/arg.cpp b/gi/arg.cpp
index 7f209fbd..c68f9ef5 100644
--- a/gi/arg.cpp
+++ b/gi/arg.cpp
@@ -2907,19 +2907,14 @@ gjs_value_from_g_argument (JSContext *context,
}
JSObject *obj;
- GjsBoxedCreationFlags flags;
- if (copy_structs)
- flags = GJS_BOXED_CREATION_NONE;
- else if (g_type_is_a(gtype, G_TYPE_VARIANT))
- flags = GJS_BOXED_CREATION_NONE;
+ if (copy_structs || g_type_is_a(gtype, G_TYPE_VARIANT))
+ obj = BoxedInstance::new_for_c_struct(
+ context, interface_info, arg->v_pointer);
else
- flags = GJS_BOXED_CREATION_NO_COPY;
-
- obj = gjs_boxed_from_c_struct(context,
- (GIStructInfo *)interface_info,
- arg->v_pointer,
- flags);
+ obj = BoxedInstance::new_for_c_struct(
+ context, interface_info, arg->v_pointer,
+ BoxedInstance::NoCopy());
if (obj)
value = JS::ObjectValue(*obj);
diff --git a/gi/boxed.cpp b/gi/boxed.cpp
index 2a471ba3..b9cc3191 100644
--- a/gi/boxed.cpp
+++ b/gi/boxed.cpp
@@ -25,6 +25,8 @@
#include <string.h>
+#include <utility>
+
#include "gjs/jsapi-wrapper.h"
#include "js/GCHashTable.h"
@@ -948,8 +950,17 @@ bool BoxedPrototype::init(JSContext* context) {
return true;
}
-bool gjs_define_boxed_class(JSContext* context, JS::HandleObject in_object,
- GIStructInfo* info) {
+/*
+ * BoxedPrototype::define_class:
+ * @in_object: Object where the constructor is stored, typically a repo object.
+ * @info: Introspection info for the boxed class.
+ *
+ * Define a boxed class constructor and prototype, including all the necessary
+ * methods and properties.
+ */
+bool BoxedPrototype::define_class(JSContext* context,
+ JS::HandleObject in_object,
+ GIStructInfo* info) {
JS::RootedObject prototype(context), constructor(context);
GType gtype = g_registered_type_info_get_g_type(info);
BoxedPrototype* priv = BoxedPrototype::create_class(
@@ -967,8 +978,13 @@ bool gjs_define_boxed_class(JSContext* context, JS::HandleObject in_object,
return true;
}
-JSObject* gjs_boxed_from_c_struct(JSContext* cx, GIStructInfo* info,
- void* gboxed, GjsBoxedCreationFlags flags) {
+/* Helper function to make the public API more readable. The overloads are
+ * specified explicitly in the public API, but the implementation uses
+ * std::forward in order to avoid duplicating code. */
+template <typename... Args>
+JSObject* BoxedInstance::new_for_c_struct_impl(JSContext* cx,
+ GIStructInfo* info, void* gboxed,
+ Args&&... args) {
if (gboxed == NULL)
return NULL;
@@ -984,13 +1000,8 @@ JSObject* gjs_boxed_from_c_struct(JSContext* cx, GIStructInfo* info,
if (!priv)
return nullptr;
- if ((flags & GJS_BOXED_CREATION_NO_COPY) != 0) {
- if (!priv->init_from_c_struct(cx, gboxed, BoxedInstance::NoCopy()))
- return nullptr;
- } else {
- if (!priv->init_from_c_struct(cx, gboxed))
- return nullptr;
- }
+ if (!priv->init_from_c_struct(cx, gboxed, std::forward<Args>(args)...))
+ return nullptr;
if (priv->gtype() == G_TYPE_ERROR && !gjs_define_error_properties(cx, obj))
return nullptr;
@@ -998,6 +1009,25 @@ JSObject* gjs_boxed_from_c_struct(JSContext* cx, GIStructInfo* info,
return obj;
}
+/*
+ * BoxedInstance::new_for_c_struct:
+ *
+ * Creates a new BoxedInstance JS object from a C boxed struct pointer.
+ *
+ * There are two overloads of this method; the NoCopy overload will simply take
+ * the passed-in pointer but not own it, while the normal method will take a
+ * reference, or if the boxed type can be directly allocated, copy the memory.
+ */
+JSObject* BoxedInstance::new_for_c_struct(JSContext* cx, GIStructInfo* info,
+ void* gboxed) {
+ return new_for_c_struct_impl(cx, info, gboxed);
+}
+
+JSObject* BoxedInstance::new_for_c_struct(JSContext* cx, GIStructInfo* info,
+ void* gboxed, NoCopy no_copy) {
+ return new_for_c_struct_impl(cx, info, gboxed, no_copy);
+}
+
/*
* BoxedInstance::init_from_c_struct:
*
diff --git a/gi/boxed.h b/gi/boxed.h
index 5c134c5a..f2f004a9 100644
--- a/gi/boxed.h
+++ b/gi/boxed.h
@@ -35,15 +35,6 @@
#include "js/GCHashTable.h"
-G_BEGIN_DECLS
-
-typedef enum {
- GJS_BOXED_CREATION_NONE = 0,
- GJS_BOXED_CREATION_NO_COPY = (1 << 0)
-} GjsBoxedCreationFlags;
-
-G_END_DECLS
-
class BoxedPrototype;
class BoxedInstance;
@@ -146,10 +137,13 @@ class BoxedPrototype : public GIWrapperPrototype<BoxedBase, BoxedPrototype,
static FieldMap* create_field_map(JSContext* cx, GIStructInfo* struct_info);
GJS_JSAPI_RETURN_CONVENTION
bool ensure_field_map(JSContext* cx);
+ GJS_JSAPI_RETURN_CONVENTION
+ bool define_boxed_class_fields(JSContext* cx, JS::HandleObject proto);
public:
GJS_JSAPI_RETURN_CONVENTION
- bool define_boxed_class_fields(JSContext* cx, JS::HandleObject proto);
+ static bool define_class(JSContext* cx, JS::HandleObject in_object,
+ GIStructInfo* info);
GJS_JSAPI_RETURN_CONVENTION
GIFieldInfo* lookup_field(JSContext* cx, JSString* prop_name);
};
@@ -213,24 +207,22 @@ class BoxedInstance
public:
struct NoCopy {};
+ private:
GJS_JSAPI_RETURN_CONVENTION
bool init_from_c_struct(JSContext* cx, void* gboxed);
GJS_JSAPI_RETURN_CONVENTION
bool init_from_c_struct(JSContext* cx, void* gboxed, NoCopy);
-};
+ template <typename... Args>
+ GJS_JSAPI_RETURN_CONVENTION static JSObject* new_for_c_struct_impl(
+ JSContext* cx, GIStructInfo* info, void* gboxed, Args&&... args);
-G_BEGIN_DECLS
-
-GJS_JSAPI_RETURN_CONVENTION
-bool gjs_define_boxed_class(JSContext* cx, JS::HandleObject in_object,
- GIStructInfo* info);
-
-GJS_JSAPI_RETURN_CONVENTION
-JSObject* gjs_boxed_from_c_struct (JSContext *context,
- GIStructInfo *info,
- void *gboxed,
- GjsBoxedCreationFlags flags);
-
-G_END_DECLS
+ public:
+ GJS_JSAPI_RETURN_CONVENTION
+ static JSObject* new_for_c_struct(JSContext* cx, GIStructInfo* info,
+ void* gboxed);
+ GJS_JSAPI_RETURN_CONVENTION
+ static JSObject* new_for_c_struct(JSContext* cx, GIStructInfo* info,
+ void* gboxed, NoCopy);
+};
#endif /* __GJS_BOXED_H__ */
diff --git a/gi/gerror.cpp b/gi/gerror.cpp
index 9d3c656a..056ca7e0 100644
--- a/gi/gerror.cpp
+++ b/gi/gerror.cpp
@@ -374,7 +374,7 @@ gjs_error_from_gerror(JSContext *context,
JSObject *retval;
glib_boxed = g_irepository_find_by_name(NULL, "GLib", "Error");
- retval = gjs_boxed_from_c_struct(context, glib_boxed, gerror, (GjsBoxedCreationFlags) 0);
+ retval = BoxedInstance::new_for_c_struct(context, glib_boxed, gerror);
g_base_info_unref(glib_boxed);
return retval;
diff --git a/gi/repo.cpp b/gi/repo.cpp
index 9ce7aa41..9dc6eec1 100644
--- a/gi/repo.cpp
+++ b/gi/repo.cpp
@@ -466,7 +466,7 @@ gjs_define_info(JSContext *context,
/* Fall through */
case GI_INFO_TYPE_BOXED:
- if (!gjs_define_boxed_class(context, in_object, info))
+ if (!BoxedPrototype::define_class(context, in_object, info))
return false;
break;
case GI_INFO_TYPE_UNION:
diff --git a/gi/value.cpp b/gi/value.cpp
index 241c35ad..c9309aac 100644
--- a/gi/value.cpp
+++ b/gi/value.cpp
@@ -829,7 +829,6 @@ gjs_value_from_g_value_internal(JSContext *context,
return false;
} else if (g_type_is_a(gtype, G_TYPE_BOXED) ||
g_type_is_a(gtype, G_TYPE_VARIANT)) {
- GjsBoxedCreationFlags boxed_flags;
void *gboxed;
JSObject *obj;
@@ -837,7 +836,6 @@ gjs_value_from_g_value_internal(JSContext *context,
gboxed = g_value_get_boxed(gvalue);
else
gboxed = g_value_get_variant(gvalue);
- boxed_flags = GJS_BOXED_CREATION_NONE;
/* special case GError */
if (g_type_is_a(gtype, G_TYPE_ERROR)) {
@@ -874,8 +872,10 @@ gjs_value_from_g_value_internal(JSContext *context,
GIInfoType type = info.type();
if (type == GI_INFO_TYPE_BOXED || type == GI_INFO_TYPE_STRUCT) {
if (no_copy)
- boxed_flags = (GjsBoxedCreationFlags) (boxed_flags | GJS_BOXED_CREATION_NO_COPY);
- obj = gjs_boxed_from_c_struct(context, info, gboxed, boxed_flags);
+ obj = BoxedInstance::new_for_c_struct(context, info, gboxed,
+ BoxedInstance::NoCopy());
+ else
+ obj = BoxedInstance::new_for_c_struct(context, info, gboxed);
} else if (type == GI_INFO_TYPE_UNION) {
obj = gjs_union_from_c_union(context, info, gboxed);
} else {
diff --git a/gjs/byteArray.cpp b/gjs/byteArray.cpp
index 49d279a2..01b39a2e 100644
--- a/gjs/byteArray.cpp
+++ b/gjs/byteArray.cpp
@@ -164,7 +164,6 @@ to_gbytes_func(JSContext *context,
JS::Value *vp)
{
JS::CallArgs rec = JS::CallArgsFromVp(argc, vp);
- JSObject *ret_bytes_obj;
GIBaseInfo *gbytes_info;
JS::RootedObject byte_array(context);
@@ -183,11 +182,13 @@ to_gbytes_func(JSContext *context,
g_irepository_require(nullptr, "GLib", "2.0", GIRepositoryLoadFlags(0),
nullptr);
gbytes_info = g_irepository_find_by_gtype(NULL, G_TYPE_BYTES);
- ret_bytes_obj = gjs_boxed_from_c_struct(context, (GIStructInfo*)gbytes_info,
- bytes, GJS_BOXED_CREATION_NONE);
+ JSObject* ret_bytes_obj =
+ BoxedInstance::new_for_c_struct(context, gbytes_info, bytes);
g_bytes_unref(bytes);
+ if (!ret_bytes_obj)
+ return false;
- rec.rval().setObjectOrNull(ret_bytes_obj);
+ rec.rval().setObject(*ret_bytes_obj);
return true;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]