]> git.eshelyaron.com Git - emacs.git/commitdiff
Support dynamic loading of libjansson on MS-Windows
authorEli Zaretskii <eliz@gnu.org>
Sun, 10 Dec 2017 16:36:37 +0000 (18:36 +0200)
committerEli Zaretskii <eliz@gnu.org>
Sun, 10 Dec 2017 16:36:37 +0000 (18:36 +0200)
* src/json.c [WINDOWSNT]: Define fn_* function pointers to jansson
functions.
(json_delete) [WINDOWSNT]: A wrapper around fn_json_delete, needed
by json_decref.
(init_json_functions) [WINDOWSNT]: New function.
(Fjson_serialize, Fjson_insert, Fjson_parse_string)
(Fjson_parse_buffer) [WINDOWSNT]: Call init_json_functions if
needed, and record JSON in Vlibrary_cache.
* src/emacs.c (main): Don't call init_json on WINDOWSNT.
* src/w32fns.c (syms_of_w32fns): DEFSYM "json".

* lisp/term/w32-win.el (dynamic-library-alist): Add JSON DLL to
the list.

* configure.ac (HAVE_JSON): Empty JSON_LIBS for MinGW.

* nt/INSTALL.W64:
* nt/INSTALL: Add information about libjansson.

configure.ac
lisp/term/w32-win.el
nt/INSTALL
nt/INSTALL.W64
src/emacs.c
src/json.c
src/w32fns.c

index caee0159548dcbdc1411efa77e32d6fc463150c7..562b19afe646de8081922ac858aa573816e957bf 100644 (file)
@@ -2881,6 +2881,11 @@ if test "${with_json}" = yes; then
     AC_DEFINE(HAVE_JSON, 1, [Define if using Jansson.])
     JSON_OBJ=json.o
   fi
+
+  # Windows loads libjansson dynamically
+  if test "${opsys}" = "mingw32"; then
+    JSON_LIBS=
+  fi
 fi
 
 AC_SUBST(JSON_LIBS)
index 4e0e54ae17937f3d3d66ca89161b6c51a7c4dd93..1db90aec984b3e47547dbf08b61799549a9a56e4 100644 (file)
@@ -276,7 +276,8 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.")
         '(gnutls "libgnutls-28.dll" "libgnutls-26.dll"))
        '(libxml2 "libxml2-2.dll" "libxml2.dll")
        '(zlib "zlib1.dll" "libz-1.dll")
-       '(lcms2 "liblcms2-2.dll")))
+       '(lcms2 "liblcms2-2.dll")
+       '(json "libjansson-4.dll")))
 
 ;;; multi-tty support
 (defvar w32-initialized nil
index 30e14293f5c5a295c49afc609d2eb7755a4c5fc4..361d607ff68030e1894c59387ac5b7917cf4dd77 100644 (file)
@@ -806,6 +806,13 @@ build will run on Windows 9X and newer systems).
   Prebuilt binaries of lcms2 DLL (for 32-bit builds of Emacs) are
   available from the ezwinports site and from the MSYS2 project.
 
+* Optional support for JSON
+
+  Emacs can provide built-in support for JSON parsing and
+  serialization using the libjansson library.  Prebuilt binaries of
+  the libjansson DLL (for 32-bit builds of Emacs) are available from
+  the ezwinports site and from the MSYS2 project.
+
 \f
 This file is part of GNU Emacs.
 
index e08b72f2ca03d73ce6bd14b132f1743e556595f0..41d57bd36891abc0fc0110623fc855f1b4052767 100644 (file)
@@ -52,6 +52,7 @@ packages (you can copy and paste it into the shell with Shift + Insert):
   mingw-w64-x86_64-libjpeg-turbo \
   mingw-w64-x86_64-librsvg \
   mingw-w64-x86_64-lcms2 \
+  mingw-w64-x86_64-jansson \
   mingw-w64-x86_64-libxml2 \
   mingw-w64-x86_64-gnutls \
   mingw-w64-x86_64-zlib
index 7c1ae1f2c5b672bb3bd3165cc9c1af87a4a9fbbb..5a6b896ef473eeac62967a6d37863fe39a1173ca 100644 (file)
@@ -1262,7 +1262,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
   running_asynch_code = 0;
   init_random ();
 
-#ifdef HAVE_JSON
+#if defined HAVE_JSON && !defined WINDOWSNT
   init_json ();
 #endif
 
index dc449e43e119c4a062a80ef80e23995632c9527b..7025ae165cdeebb5c9beaa19757b1c2785d7c948 100644 (file)
@@ -30,6 +30,126 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 #include "buffer.h"
 #include "coding.h"
 
+#ifdef WINDOWSNT
+# include <windows.h>
+# include "w32.h"
+
+DEF_DLL_FN (void, json_set_alloc_funcs,
+           (json_malloc_t malloc_fn, json_free_t free_fn));
+DEF_DLL_FN (void, json_delete, (json_t *json));
+DEF_DLL_FN (json_t *, json_array, (void));
+DEF_DLL_FN (int, json_array_append_new, (json_t *array, json_t *value));
+DEF_DLL_FN (size_t, json_array_size, (const json_t *array));
+DEF_DLL_FN (json_t *, json_object, (void));
+DEF_DLL_FN (int, json_object_set_new,
+           (json_t *object, const char *key, json_t *value));
+DEF_DLL_FN (json_t *, json_null, (void));
+DEF_DLL_FN (json_t *, json_true, (void));
+DEF_DLL_FN (json_t *, json_false, (void));
+DEF_DLL_FN (json_t *, json_integer, (json_int_t value));
+DEF_DLL_FN (json_t *, json_real, (double value));
+DEF_DLL_FN (json_t *, json_stringn, (const char *value, size_t len));
+DEF_DLL_FN (char *, json_dumps, (const json_t *json, size_t flags));
+DEF_DLL_FN (int, json_dump_callback,
+           (const json_t *json, json_dump_callback_t callback, void *data,
+            size_t flags));
+DEF_DLL_FN (json_int_t, json_integer_value, (const json_t *integer));
+DEF_DLL_FN (double, json_real_value, (const json_t *real));
+DEF_DLL_FN (const char *, json_string_value, (const json_t *string));
+DEF_DLL_FN (size_t, json_string_length, (const json_t *string));
+DEF_DLL_FN (json_t *, json_array_get, (const json_t *array, size_t index));
+DEF_DLL_FN (size_t, json_object_size, (const json_t *object));
+DEF_DLL_FN (const char *, json_object_iter_key, (void *iter));
+DEF_DLL_FN (void *, json_object_iter, (json_t *object));
+DEF_DLL_FN (json_t *, json_object_iter_value, (void *iter));
+DEF_DLL_FN (void *, json_object_key_to_iter, (const char *key));
+DEF_DLL_FN (void *, json_object_iter_next, (json_t *object, void *iter));
+DEF_DLL_FN (json_t *, json_loads,
+           (const char *input, size_t flags, json_error_t *error));
+DEF_DLL_FN (json_t *, json_load_callback,
+           (json_load_callback_t callback, void *data, size_t flags,
+            json_error_t *error));
+
+/* This is called by json_decref, which is an inline function.  */
+void json_delete(json_t *json)
+{
+  fn_json_delete (json);
+}
+
+static bool json_initialized;
+
+static bool
+init_json_functions (void)
+{
+  HMODULE library = w32_delayed_load (Qjson);
+
+  if (!library)
+    return false;
+
+  LOAD_DLL_FN (library, json_set_alloc_funcs);
+  LOAD_DLL_FN (library, json_delete);
+  LOAD_DLL_FN (library, json_array);
+  LOAD_DLL_FN (library, json_array_append_new);
+  LOAD_DLL_FN (library, json_array_size);
+  LOAD_DLL_FN (library, json_object);
+  LOAD_DLL_FN (library, json_object_set_new);
+  LOAD_DLL_FN (library, json_null);
+  LOAD_DLL_FN (library, json_true);
+  LOAD_DLL_FN (library, json_false);
+  LOAD_DLL_FN (library, json_integer);
+  LOAD_DLL_FN (library, json_real);
+  LOAD_DLL_FN (library, json_stringn);
+  LOAD_DLL_FN (library, json_dumps);
+  LOAD_DLL_FN (library, json_dump_callback);
+  LOAD_DLL_FN (library, json_integer_value);
+  LOAD_DLL_FN (library, json_real_value);
+  LOAD_DLL_FN (library, json_string_value);
+  LOAD_DLL_FN (library, json_string_length);
+  LOAD_DLL_FN (library, json_array_get);
+  LOAD_DLL_FN (library, json_object_size);
+  LOAD_DLL_FN (library, json_object_iter_key);
+  LOAD_DLL_FN (library, json_object_iter);
+  LOAD_DLL_FN (library, json_object_iter_value);
+  LOAD_DLL_FN (library, json_object_key_to_iter);
+  LOAD_DLL_FN (library, json_object_iter_next);
+  LOAD_DLL_FN (library, json_loads);
+  LOAD_DLL_FN (library, json_load_callback);
+
+  init_json ();
+
+  return true;
+}
+
+#define json_set_alloc_funcs fn_json_set_alloc_funcs
+#define json_array fn_json_array
+#define json_array_append_new fn_json_array_append_new
+#define json_array_size fn_json_array_size
+#define json_object fn_json_object
+#define json_object_set_new fn_json_object_set_new
+#define json_null fn_json_null
+#define json_true fn_json_true
+#define json_false fn_json_false
+#define json_integer fn_json_integer
+#define json_real fn_json_real
+#define json_stringn fn_json_stringn
+#define json_dumps fn_json_dumps
+#define json_dump_callback fn_json_dump_callback
+#define json_integer_value fn_json_integer_value
+#define json_real_value fn_json_real_value
+#define json_string_value fn_json_string_value
+#define json_string_length fn_json_string_length
+#define json_array_get fn_json_array_get
+#define json_object_size fn_json_object_size
+#define json_object_iter_key fn_json_object_iter_key
+#define json_object_iter fn_json_object_iter
+#define json_object_iter_value fn_json_object_iter_value
+#define json_object_key_to_iter fn_json_object_key_to_iter
+#define json_object_iter_next fn_json_object_iter_next
+#define json_loads fn_json_loads
+#define json_load_callback fn_json_load_callback
+
+#endif /* WINDOWSNT */
+
 /* We install a custom allocator so that we can avoid objects larger
    than PTRDIFF_MAX.  Such objects wouldn’t play well with the rest of
    Emacs’s codebase, which generally uses ptrdiff_t for sizes and
@@ -277,6 +397,21 @@ each object.  */)
 {
   ptrdiff_t count = SPECPDL_INDEX ();
 
+#ifdef WINDOWSNT
+  if (!json_initialized)
+    {
+      Lisp_Object status;
+      json_initialized = init_json_functions ();
+      status = json_initialized ? Qt : Qnil;
+      Vlibrary_cache = Fcons (Fcons (Qjson, status), Vlibrary_cache);
+    }
+  if (!json_initialized)
+    {
+      message1 ("jansson library not found");
+      return Qnil;
+    }
+#endif
+
   json_t *json = lisp_to_json_toplevel (object);
   record_unwind_protect_ptr (json_release_object, json);
 
@@ -340,6 +475,21 @@ OBJECT.  */)
 {
   ptrdiff_t count = SPECPDL_INDEX ();
 
+#ifdef WINDOWSNT
+  if (!json_initialized)
+    {
+      Lisp_Object status;
+      json_initialized = init_json_functions ();
+      status = json_initialized ? Qt : Qnil;
+      Vlibrary_cache = Fcons (Fcons (Qjson, status), Vlibrary_cache);
+    }
+  if (!json_initialized)
+    {
+      message1 ("jansson library not found");
+      return Qnil;
+    }
+#endif
+
   json_t *json = lisp_to_json (object);
   record_unwind_protect_ptr (json_release_object, json);
 
@@ -439,6 +589,22 @@ an error of type `json-parse-error' is signaled.  */)
   (Lisp_Object string)
 {
   ptrdiff_t count = SPECPDL_INDEX ();
+
+#ifdef WINDOWSNT
+  if (!json_initialized)
+    {
+      Lisp_Object status;
+      json_initialized = init_json_functions ();
+      status = json_initialized ? Qt : Qnil;
+      Vlibrary_cache = Fcons (Fcons (Qjson, status), Vlibrary_cache);
+    }
+  if (!json_initialized)
+    {
+      message1 ("jansson library not found");
+      return Qnil;
+    }
+#endif
+
   Lisp_Object encoded = json_encode (string);
   check_string_without_embedded_nulls (encoded);
 
@@ -493,6 +659,21 @@ not moved.  */)
 {
   ptrdiff_t count = SPECPDL_INDEX ();
 
+#ifdef WINDOWSNT
+  if (!json_initialized)
+    {
+      Lisp_Object status;
+      json_initialized = init_json_functions ();
+      status = json_initialized ? Qt : Qnil;
+      Vlibrary_cache = Fcons (Fcons (Qjson, status), Vlibrary_cache);
+    }
+  if (!json_initialized)
+    {
+      message1 ("jansson library not found");
+      return Qnil;
+    }
+#endif
+
   ptrdiff_t point = PT_BYTE;
   struct json_read_buffer_data data = {.point = point};
   json_error_t error;
index d2d4b2c73558e38d28691df0de01a464a98300cf..90d09542c45736eadb2e89dbb0dcde155ce318bb 100644 (file)
@@ -10418,6 +10418,7 @@ syms_of_w32fns (void)
   DEFSYM (Qserif, "serif");
   DEFSYM (Qzlib, "zlib");
   DEFSYM (Qlcms2, "lcms2");
+  DEFSYM (Qjson, "json");
 
   Fput (Qundefined_color, Qerror_conditions,
        listn (CONSTYPE_PURE, 2, Qundefined_color, Qerror));