From 8625802d854ec0152177a6ff0ac092e0e3ff98a5 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Fri, 24 Jun 2022 12:40:43 +0200 Subject: [PATCH] gh-84461: Fix ctypes and test_ctypes on Emscripten (#94142) - c_longlong and c_longdouble need experimental WASM bigint. - Skip tests that need threading - Define ``CTYPES_MAX_ARGCOUNT`` for Emscripten. libffi-emscripten 2022-06-23 supports up to 1000 args. --- Lib/test/test_code.py | 2 ++ Lib/test/test_ctypes/test_as_parameter.py | 1 + Lib/test/test_ctypes/test_callbacks.py | 3 +++ Lib/test/test_ctypes/test_cfuncs.py | 6 ++++++ Lib/test/test_ctypes/test_functions.py | 1 + Modules/_ctypes/ctypes.h | 6 +++++- Tools/wasm/README.md | 2 ++ configure | 8 +++----- configure.ac | 6 +++--- 9 files changed, 26 insertions(+), 9 deletions(-) diff --git a/Lib/test/test_code.py b/Lib/test/test_code.py index a6857dc4f84..308141aaf10 100644 --- a/Lib/test/test_code.py +++ b/Lib/test/test_code.py @@ -141,6 +141,7 @@ check_impl_detail, requires_debug_ranges, gc_collect) from test.support.script_helper import assert_python_ok +from test.support import threading_helper from opcode import opmap COPY_FREE_VARS = opmap['COPY_FREE_VARS'] @@ -723,6 +724,7 @@ def test_get_set(self): self.assertEqual(extra.value, 300) del f + @threading_helper.requires_working_threading() def test_free_different_thread(self): # Freeing a code object on a different thread then # where the co_extra was set should be safe. diff --git a/Lib/test/test_ctypes/test_as_parameter.py b/Lib/test/test_ctypes/test_as_parameter.py index b35defb1585..e9ec9ad847b 100644 --- a/Lib/test/test_ctypes/test_as_parameter.py +++ b/Lib/test/test_ctypes/test_as_parameter.py @@ -122,6 +122,7 @@ def callback(value): result = f(self.wrap(-10), self.wrap(cb)) self.assertEqual(result, -18) + @need_symbol('c_longlong') def test_longlong_callbacks(self): f = dll._testfunc_callback_q_qf diff --git a/Lib/test/test_ctypes/test_callbacks.py b/Lib/test/test_ctypes/test_callbacks.py index 2758720d4a9..b5bef04e14d 100644 --- a/Lib/test/test_ctypes/test_callbacks.py +++ b/Lib/test/test_ctypes/test_callbacks.py @@ -65,10 +65,12 @@ def test_long(self): def test_ulong(self): self.check_type(c_ulong, 42) + @need_symbol('c_longlong') def test_longlong(self): self.check_type(c_longlong, 42) self.check_type(c_longlong, -42) + @need_symbol('c_ulonglong') def test_ulonglong(self): self.check_type(c_ulonglong, 42) @@ -82,6 +84,7 @@ def test_double(self): self.check_type(c_double, 3.14) self.check_type(c_double, -3.14) + @need_symbol('c_longdouble') def test_longdouble(self): self.check_type(c_longdouble, 3.14) self.check_type(c_longdouble, -3.14) diff --git a/Lib/test/test_ctypes/test_cfuncs.py b/Lib/test/test_ctypes/test_cfuncs.py index 0a9394bf313..7cba4b0e527 100644 --- a/Lib/test/test_ctypes/test_cfuncs.py +++ b/Lib/test/test_ctypes/test_cfuncs.py @@ -111,24 +111,28 @@ def test_ulong_plus(self): self.assertEqual(self._dll.tf_bL(b' ', 4294967295), 1431655765) self.assertEqual(self.U(), 4294967295) + @need_symbol('c_longlong') def test_longlong(self): self._dll.tf_q.restype = c_longlong self._dll.tf_q.argtypes = (c_longlong, ) self.assertEqual(self._dll.tf_q(-9223372036854775806), -3074457345618258602) self.assertEqual(self.S(), -9223372036854775806) + @need_symbol('c_longlong') def test_longlong_plus(self): self._dll.tf_bq.restype = c_longlong self._dll.tf_bq.argtypes = (c_byte, c_longlong) self.assertEqual(self._dll.tf_bq(0, -9223372036854775806), -3074457345618258602) self.assertEqual(self.S(), -9223372036854775806) + @need_symbol('c_ulonglong') def test_ulonglong(self): self._dll.tf_Q.restype = c_ulonglong self._dll.tf_Q.argtypes = (c_ulonglong, ) self.assertEqual(self._dll.tf_Q(18446744073709551615), 6148914691236517205) self.assertEqual(self.U(), 18446744073709551615) + @need_symbol('c_ulonglong') def test_ulonglong_plus(self): self._dll.tf_bQ.restype = c_ulonglong self._dll.tf_bQ.argtypes = (c_byte, c_ulonglong) @@ -159,12 +163,14 @@ def test_double_plus(self): self.assertEqual(self._dll.tf_bd(0, 42.), 14.) self.assertEqual(self.S(), 42) + @need_symbol('c_longdouble') def test_longdouble(self): self._dll.tf_D.restype = c_longdouble self._dll.tf_D.argtypes = (c_longdouble,) self.assertEqual(self._dll.tf_D(42.), 14.) self.assertEqual(self.S(), 42) + @need_symbol('c_longdouble') def test_longdouble_plus(self): self._dll.tf_bD.restype = c_longdouble self._dll.tf_bD.argtypes = (c_byte, c_longdouble) diff --git a/Lib/test/test_ctypes/test_functions.py b/Lib/test/test_ctypes/test_functions.py index 4a784c8d798..a3db0033533 100644 --- a/Lib/test/test_ctypes/test_functions.py +++ b/Lib/test/test_ctypes/test_functions.py @@ -128,6 +128,7 @@ def test_doubleresult(self): self.assertEqual(result, -21) self.assertEqual(type(result), float) + @need_symbol('c_longdouble') def test_longdoubleresult(self): f = dll._testfunc_D_bhilfD f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_longdouble] diff --git a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h index da1941caf39..88eb9f59922 100644 --- a/Modules/_ctypes/ctypes.h +++ b/Modules/_ctypes/ctypes.h @@ -19,7 +19,11 @@ * to avoid allocating a massive buffer on the stack. */ #ifndef CTYPES_MAX_ARGCOUNT - #define CTYPES_MAX_ARGCOUNT 1024 + #ifdef __EMSCRIPTEN__ + #define CTYPES_MAX_ARGCOUNT 1000 + #else + #define CTYPES_MAX_ARGCOUNT 1024 + #endif #endif typedef struct tagPyCArgObject PyCArgObject; diff --git a/Tools/wasm/README.md b/Tools/wasm/README.md index 4a711a6eb56..94b3729a5da 100644 --- a/Tools/wasm/README.md +++ b/Tools/wasm/README.md @@ -173,6 +173,8 @@ ## Misc [bpo-46390](https://bugs.python.org/issue46390). - Python's object allocator ``obmalloc`` is disabled by default. - ``ensurepip`` is not available. +- Some ``ctypes`` features like ``c_longlong`` and ``c_longdouble`` may need + NodeJS option ``--experimental-wasm-bigint``. ## wasm32-emscripten in browsers diff --git a/configure b/configure index c7bafb3b949..34de0f7f1b6 100755 --- a/configure +++ b/configure @@ -6775,13 +6775,11 @@ then case $ac_sys_system/$ac_sys_emscripten_target in #( Emscripten/node*) : + # bigint for ctypes c_longlong, c_longdouble + HOSTRUNNER="node --experimental-wasm-bigint" if test "x$enable_wasm_pthreads" = xyes; then : - HOSTRUNNER='node --experimental-wasm-threads --experimental-wasm-bulk-memory' - -else - - HOSTRUNNER='node' + HOSTRUNNER="$HOSTRUNNER --experimental-wasm-threads --experimental-wasm-bulk-memory" fi ;; #( diff --git a/configure.ac b/configure.ac index 4f8e7e3cd46..3b70532e4d0 100644 --- a/configure.ac +++ b/configure.ac @@ -1486,10 +1486,10 @@ if test -z "$HOSTRUNNER" then AS_CASE([$ac_sys_system/$ac_sys_emscripten_target], [Emscripten/node*], [ + # bigint for ctypes c_longlong, c_longdouble + HOSTRUNNER="node --experimental-wasm-bigint" AS_VAR_IF([enable_wasm_pthreads], [yes], [ - HOSTRUNNER='node --experimental-wasm-threads --experimental-wasm-bulk-memory' - ], [ - HOSTRUNNER='node' + HOSTRUNNER="$HOSTRUNNER --experimental-wasm-threads --experimental-wasm-bulk-memory" ]) ], dnl TODO: support other WASI runtimes