Скопируйте генератор через ctypesPython

Программы на Python
Anonymous
Скопируйте генератор через ctypes

Сообщение Anonymous »

Я пытаюсь скопировать генератор с помощью PyGen_New, передав объект фрейма. На данный момент я получаю следующую непонятную мне ошибку:
Traceback (most recent call last):
File "C:\test.py", line 19, in
frame = Frame(gen.gi_code)
^^^^^^^^^^^^^^^^^^
File "C:\test.py", line 11, in Frame
return ctypes.pythonapi.PyFrame_New(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
OSError: exception: access violation reading 0x0000000000000008

используемый код:
from types import CodeType, FrameType
import ctypes

ctypes.pythonapi.PyThreadState_Get.argtypes = None
ctypes.pythonapi.PyThreadState_Get.restype = ctypes.POINTER(ctypes.c_ulong)
ctypes.pythonapi.PyFrame_New.restype = ctypes.POINTER(ctypes.py_object)

def Frame(code_obj: CodeType, globals: dict = None, locals: dict = None) -> FrameType:
"""Instantiates a FrameType object"""
return ctypes.pythonapi.PyFrame_New(
ctypes.pythonapi.PyThreadState_Get(),
ctypes.cast(id(code_obj), ctypes.POINTER(ctypes.c_int)),
globals,
locals,
)

gen = (i for i in range(3))
frame = Frame(gen.gi_code)

ctypes.pythonapi.PyGen_New.restype = ctypes.POINTER(ctypes.py_object)
new_gen = ctypes.pythonapi.PyGen_New(
ctypes.cast(id(frame), ctypes.POINTER(ctypes.c_void_p))
)

for value in new_gen:
print(value)

Примечание: я понимаю, что копирование и травление генераторов не предусмотрено языком cpython, поэтому вам не нужно рассказывать мне об этом и обо всех трудностях, связанных с попыткой (это не суть этого вопроса). Суть этого вопроса в преодолении и понимании нюансов ошибки, возникающей при решении конкретного проблемного случая; это не должно быть обобщаемой проблемой для всех экземпляров генератора.
Кроме того, да, здесь используются детали реализации уровня C. Я знаю нюансы этого; это не суть этого вопроса.
код был запущен на Python версии 3.11.9
Обновить
Следующий раздел кода устраняет ошибку, но сейчас я работаю над тем, как получить фактический приведенный/сформированный тип генератора.
код:
from types import CodeType, FrameType
import ctypes

ctypes.pythonapi.PyFrame_New.argtypes = (
ctypes.POINTER(ctypes.c_ulong),
ctypes.POINTER(ctypes.c_ulong),
ctypes.py_object,
ctypes.py_object
)
ctypes.pythonapi.PyFrame_New.restype = ctypes.py_object
ctypes.pythonapi.PyThreadState_Get.argtypes = None
ctypes.pythonapi.PyThreadState_Get.restype = ctypes.POINTER(ctypes.c_ulong)

def Frame(code_obj: CodeType, globals: dict = {}, locals: dict = {}) -> FrameType:
"""Instantiates a FrameType object"""
return ctypes.pythonapi.PyFrame_New(
ctypes.pythonapi.PyThreadState_Get(),
ctypes.cast(id(code_obj), ctypes.POINTER(ctypes.c_ulong)),
globals,
locals
)
gen = (i for i in range(3))
frame = Frame(gen.gi_code)

ctypes.pythonapi.PyGen_New.argtypes = [ctypes.POINTER(ctypes.py_object)]
ctypes.pythonapi.PyGen_New.restype = ctypes.POINTER(ctypes.py_object)

new_gen = ctypes.pythonapi.PyGen_New(
ctypes.cast(id(frame), ctypes.POINTER(ctypes.py_object))
)

## This section below does not work ##
for value in new_gen:
print(value)

Вернуться в «Python»