Videre
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
import ctypes
|
||||
import unittest
|
||||
from numba.core import types
|
||||
from numba.core.extending import intrinsic
|
||||
from numba import jit, njit
|
||||
from numba.tests.support import captured_stdout
|
||||
|
||||
|
||||
@intrinsic
|
||||
def _pyapi_bytes_as_string(typingctx, csrc, size):
|
||||
sig = types.voidptr(csrc, size) # cstring == void*
|
||||
|
||||
def codegen(context, builder, sig, args):
|
||||
[csrc, size] = args
|
||||
api = context.get_python_api(builder)
|
||||
b = api.bytes_from_string_and_size(csrc, size)
|
||||
return api.bytes_as_string(b)
|
||||
return sig, codegen
|
||||
|
||||
|
||||
def PyBytes_AsString(uni):
|
||||
# test_PyBytes_AsString will call this function with a unicode type.
|
||||
# We then use the underlying buffer to create a PyBytes object and call the
|
||||
# PyBytes_AsString function with PyBytes object as argument
|
||||
return _pyapi_bytes_as_string(uni._data, uni._length)
|
||||
|
||||
|
||||
@intrinsic
|
||||
def _pyapi_bytes_as_string_and_size(typingctx, csrc, size):
|
||||
# return a tuple containing the c-string and size
|
||||
retty = types.Tuple.from_types((csrc, size))
|
||||
sig = retty(csrc, size)
|
||||
|
||||
def codegen(context, builder, sig, args):
|
||||
[csrc, size] = args
|
||||
pyapi = context.get_python_api(builder)
|
||||
b = pyapi.bytes_from_string_and_size(csrc, size)
|
||||
p_cstr = builder.alloca(pyapi.cstring)
|
||||
p_size = builder.alloca(pyapi.py_ssize_t)
|
||||
pyapi.bytes_as_string_and_size(b, p_cstr, p_size)
|
||||
|
||||
cstr = builder.load(p_cstr)
|
||||
size = builder.load(p_size)
|
||||
tup = context.make_tuple(builder, sig.return_type, (cstr, size))
|
||||
return tup
|
||||
return sig, codegen
|
||||
|
||||
|
||||
def PyBytes_AsStringAndSize(uni):
|
||||
return _pyapi_bytes_as_string_and_size(uni._data, uni._length)
|
||||
|
||||
|
||||
class TestPythonAPI(unittest.TestCase):
|
||||
|
||||
def test_PyBytes_AsString(self):
|
||||
cfunc = jit(nopython=True)(PyBytes_AsString)
|
||||
cstr = cfunc('hello') # returns a cstring
|
||||
|
||||
fn = ctypes.pythonapi.PyBytes_FromString
|
||||
fn.argtypes = [ctypes.c_void_p]
|
||||
fn.restype = ctypes.py_object
|
||||
obj = fn(cstr)
|
||||
|
||||
# Use the cstring created from bytes_as_string to create a python
|
||||
# bytes object
|
||||
self.assertEqual(obj, b'hello')
|
||||
|
||||
def test_PyBytes_AsStringAndSize(self):
|
||||
cfunc = jit(nopython=True)(PyBytes_AsStringAndSize)
|
||||
tup = cfunc('hello\x00world') # returns a tuple: cstring and its size
|
||||
|
||||
fn = ctypes.pythonapi.PyBytes_FromStringAndSize
|
||||
fn.argtypes = [ctypes.c_void_p, ctypes.c_size_t]
|
||||
fn.restype = ctypes.py_object
|
||||
obj = fn(tup[0], tup[1])
|
||||
|
||||
# Use the cstring created from bytes_from_string_and_size to create
|
||||
# a python bytes object
|
||||
self.assertEqual(obj, b'hello\x00world')
|
||||
|
||||
|
||||
class PythonAPIEmptyArgs(unittest.TestCase):
|
||||
def test_empty_args(self):
|
||||
def callme(**kwargs):
|
||||
print("callme", kwargs)
|
||||
|
||||
@intrinsic
|
||||
def py_call(tyctx):
|
||||
def codegen(context, builder, sig, args):
|
||||
pyapi = context.get_python_api(builder)
|
||||
gil = pyapi.gil_ensure()
|
||||
|
||||
num = pyapi.long_from_longlong(
|
||||
context.get_constant(types.intp, 0xCAFE)
|
||||
)
|
||||
kwds = pyapi.dict_pack({"key": num}.items())
|
||||
fn_print = pyapi.unserialize(pyapi.serialize_object(callme))
|
||||
# segfault: https://github.com/numba/numba/issues/5871
|
||||
res = pyapi.call(fn_print, None, kwds)
|
||||
|
||||
pyapi.decref(res)
|
||||
pyapi.decref(fn_print)
|
||||
pyapi.decref(kwds)
|
||||
pyapi.decref(num)
|
||||
|
||||
pyapi.gil_release(gil)
|
||||
return res
|
||||
|
||||
return types.none(), codegen
|
||||
|
||||
@njit
|
||||
def foo():
|
||||
py_call()
|
||||
|
||||
with captured_stdout() as out:
|
||||
foo()
|
||||
d = {"key": 0xCAFE}
|
||||
expected = f"callme {d}\n"
|
||||
self.assertEqual(out.getvalue(), expected)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user