Я пытаюсь скопировать генератор с помощью 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)