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.
This commit is contained in:
Christian Heimes 2022-06-24 12:40:43 +02:00 committed by GitHub
parent ab077d1e17
commit 8625802d85
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 26 additions and 9 deletions

View File

@ -141,6 +141,7 @@ from test.support import (cpython_only,
check_impl_detail, requires_debug_ranges, check_impl_detail, requires_debug_ranges,
gc_collect) gc_collect)
from test.support.script_helper import assert_python_ok from test.support.script_helper import assert_python_ok
from test.support import threading_helper
from opcode import opmap from opcode import opmap
COPY_FREE_VARS = opmap['COPY_FREE_VARS'] COPY_FREE_VARS = opmap['COPY_FREE_VARS']
@ -723,6 +724,7 @@ if check_impl_detail(cpython=True) and ctypes is not None:
self.assertEqual(extra.value, 300) self.assertEqual(extra.value, 300)
del f del f
@threading_helper.requires_working_threading()
def test_free_different_thread(self): def test_free_different_thread(self):
# Freeing a code object on a different thread then # Freeing a code object on a different thread then
# where the co_extra was set should be safe. # where the co_extra was set should be safe.

View File

@ -122,6 +122,7 @@ class BasicWrapTestCase(unittest.TestCase):
result = f(self.wrap(-10), self.wrap(cb)) result = f(self.wrap(-10), self.wrap(cb))
self.assertEqual(result, -18) self.assertEqual(result, -18)
@need_symbol('c_longlong')
def test_longlong_callbacks(self): def test_longlong_callbacks(self):
f = dll._testfunc_callback_q_qf f = dll._testfunc_callback_q_qf

View File

@ -65,10 +65,12 @@ class Callbacks(unittest.TestCase):
def test_ulong(self): def test_ulong(self):
self.check_type(c_ulong, 42) self.check_type(c_ulong, 42)
@need_symbol('c_longlong')
def test_longlong(self): def test_longlong(self):
self.check_type(c_longlong, 42) self.check_type(c_longlong, 42)
self.check_type(c_longlong, -42) self.check_type(c_longlong, -42)
@need_symbol('c_ulonglong')
def test_ulonglong(self): def test_ulonglong(self):
self.check_type(c_ulonglong, 42) self.check_type(c_ulonglong, 42)
@ -82,6 +84,7 @@ class Callbacks(unittest.TestCase):
self.check_type(c_double, 3.14) self.check_type(c_double, 3.14)
self.check_type(c_double, -3.14) self.check_type(c_double, -3.14)
@need_symbol('c_longdouble')
def test_longdouble(self): def test_longdouble(self):
self.check_type(c_longdouble, 3.14) self.check_type(c_longdouble, 3.14)
self.check_type(c_longdouble, -3.14) self.check_type(c_longdouble, -3.14)

View File

@ -111,24 +111,28 @@ class CFunctions(unittest.TestCase):
self.assertEqual(self._dll.tf_bL(b' ', 4294967295), 1431655765) self.assertEqual(self._dll.tf_bL(b' ', 4294967295), 1431655765)
self.assertEqual(self.U(), 4294967295) self.assertEqual(self.U(), 4294967295)
@need_symbol('c_longlong')
def test_longlong(self): def test_longlong(self):
self._dll.tf_q.restype = c_longlong self._dll.tf_q.restype = c_longlong
self._dll.tf_q.argtypes = (c_longlong, ) self._dll.tf_q.argtypes = (c_longlong, )
self.assertEqual(self._dll.tf_q(-9223372036854775806), -3074457345618258602) self.assertEqual(self._dll.tf_q(-9223372036854775806), -3074457345618258602)
self.assertEqual(self.S(), -9223372036854775806) self.assertEqual(self.S(), -9223372036854775806)
@need_symbol('c_longlong')
def test_longlong_plus(self): def test_longlong_plus(self):
self._dll.tf_bq.restype = c_longlong self._dll.tf_bq.restype = c_longlong
self._dll.tf_bq.argtypes = (c_byte, c_longlong) self._dll.tf_bq.argtypes = (c_byte, c_longlong)
self.assertEqual(self._dll.tf_bq(0, -9223372036854775806), -3074457345618258602) self.assertEqual(self._dll.tf_bq(0, -9223372036854775806), -3074457345618258602)
self.assertEqual(self.S(), -9223372036854775806) self.assertEqual(self.S(), -9223372036854775806)
@need_symbol('c_ulonglong')
def test_ulonglong(self): def test_ulonglong(self):
self._dll.tf_Q.restype = c_ulonglong self._dll.tf_Q.restype = c_ulonglong
self._dll.tf_Q.argtypes = (c_ulonglong, ) self._dll.tf_Q.argtypes = (c_ulonglong, )
self.assertEqual(self._dll.tf_Q(18446744073709551615), 6148914691236517205) self.assertEqual(self._dll.tf_Q(18446744073709551615), 6148914691236517205)
self.assertEqual(self.U(), 18446744073709551615) self.assertEqual(self.U(), 18446744073709551615)
@need_symbol('c_ulonglong')
def test_ulonglong_plus(self): def test_ulonglong_plus(self):
self._dll.tf_bQ.restype = c_ulonglong self._dll.tf_bQ.restype = c_ulonglong
self._dll.tf_bQ.argtypes = (c_byte, c_ulonglong) self._dll.tf_bQ.argtypes = (c_byte, c_ulonglong)
@ -159,12 +163,14 @@ class CFunctions(unittest.TestCase):
self.assertEqual(self._dll.tf_bd(0, 42.), 14.) self.assertEqual(self._dll.tf_bd(0, 42.), 14.)
self.assertEqual(self.S(), 42) self.assertEqual(self.S(), 42)
@need_symbol('c_longdouble')
def test_longdouble(self): def test_longdouble(self):
self._dll.tf_D.restype = c_longdouble self._dll.tf_D.restype = c_longdouble
self._dll.tf_D.argtypes = (c_longdouble,) self._dll.tf_D.argtypes = (c_longdouble,)
self.assertEqual(self._dll.tf_D(42.), 14.) self.assertEqual(self._dll.tf_D(42.), 14.)
self.assertEqual(self.S(), 42) self.assertEqual(self.S(), 42)
@need_symbol('c_longdouble')
def test_longdouble_plus(self): def test_longdouble_plus(self):
self._dll.tf_bD.restype = c_longdouble self._dll.tf_bD.restype = c_longdouble
self._dll.tf_bD.argtypes = (c_byte, c_longdouble) self._dll.tf_bD.argtypes = (c_byte, c_longdouble)

View File

@ -128,6 +128,7 @@ class FunctionTestCase(unittest.TestCase):
self.assertEqual(result, -21) self.assertEqual(result, -21)
self.assertEqual(type(result), float) self.assertEqual(type(result), float)
@need_symbol('c_longdouble')
def test_longdoubleresult(self): def test_longdoubleresult(self):
f = dll._testfunc_D_bhilfD f = dll._testfunc_D_bhilfD
f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_longdouble] f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_longdouble]

View File

@ -19,7 +19,11 @@
* to avoid allocating a massive buffer on the stack. * to avoid allocating a massive buffer on the stack.
*/ */
#ifndef CTYPES_MAX_ARGCOUNT #ifndef CTYPES_MAX_ARGCOUNT
#define CTYPES_MAX_ARGCOUNT 1024 #ifdef __EMSCRIPTEN__
#define CTYPES_MAX_ARGCOUNT 1000
#else
#define CTYPES_MAX_ARGCOUNT 1024
#endif
#endif #endif
typedef struct tagPyCArgObject PyCArgObject; typedef struct tagPyCArgObject PyCArgObject;

View File

@ -173,6 +173,8 @@ functions.
[bpo-46390](https://bugs.python.org/issue46390). [bpo-46390](https://bugs.python.org/issue46390).
- Python's object allocator ``obmalloc`` is disabled by default. - Python's object allocator ``obmalloc`` is disabled by default.
- ``ensurepip`` is not available. - ``ensurepip`` is not available.
- Some ``ctypes`` features like ``c_longlong`` and ``c_longdouble`` may need
NodeJS option ``--experimental-wasm-bigint``.
## wasm32-emscripten in browsers ## wasm32-emscripten in browsers

8
configure generated vendored
View File

@ -6775,13 +6775,11 @@ then
case $ac_sys_system/$ac_sys_emscripten_target in #( case $ac_sys_system/$ac_sys_emscripten_target in #(
Emscripten/node*) : Emscripten/node*) :
# bigint for ctypes c_longlong, c_longdouble
HOSTRUNNER="node --experimental-wasm-bigint"
if test "x$enable_wasm_pthreads" = xyes; then : if test "x$enable_wasm_pthreads" = xyes; then :
HOSTRUNNER='node --experimental-wasm-threads --experimental-wasm-bulk-memory' HOSTRUNNER="$HOSTRUNNER --experimental-wasm-threads --experimental-wasm-bulk-memory"
else
HOSTRUNNER='node'
fi fi
;; #( ;; #(

View File

@ -1486,10 +1486,10 @@ if test -z "$HOSTRUNNER"
then then
AS_CASE([$ac_sys_system/$ac_sys_emscripten_target], AS_CASE([$ac_sys_system/$ac_sys_emscripten_target],
[Emscripten/node*], [ [Emscripten/node*], [
# bigint for ctypes c_longlong, c_longdouble
HOSTRUNNER="node --experimental-wasm-bigint"
AS_VAR_IF([enable_wasm_pthreads], [yes], [ AS_VAR_IF([enable_wasm_pthreads], [yes], [
HOSTRUNNER='node --experimental-wasm-threads --experimental-wasm-bulk-memory' HOSTRUNNER="$HOSTRUNNER --experimental-wasm-threads --experimental-wasm-bulk-memory"
], [
HOSTRUNNER='node'
]) ])
], ],
dnl TODO: support other WASI runtimes dnl TODO: support other WASI runtimes