Как я могу позволить общей библиотеке, вызываемой Python, получать доступ к глобальным переменным одного и того же экземPython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Как я могу позволить общей библиотеке, вызываемой Python, получать доступ к глобальным переменным одного и того же экзем

Сообщение Anonymous »

Итак, я создал этот файл main.py:

Код: Выделить всё

#!/usr/bin/python3

import ctypes

foo = 1

# Should print 2, but prints 1
def print_foo():
global foo
print(foo)

def main():
global foo
foo = 2

dll = ctypes.PyDLL("./foo.so")

foo = dll.foo
foo.restype = None
foo()

if __name__ == "__main__":
main()
и этот foo.c:

Код: Выделить всё

#define PY_SSIZE_T_CLEAN
#include 

#include 

#define CHECK_PYTHON_ERROR() {\
if (PyErr_Occurred()) {\
PyErr_Print();\
fprintf(stderr, "Error detected in foo.c:%d\n", __LINE__);\
exit(EXIT_FAILURE);\
}\
}

void foo(void) {
PyObject *module = PyImport_ImportModule("main");
CHECK_PYTHON_ERROR();
assert(module);

PyObject *print_foo = PyObject_GetAttrString(module, "print_foo");
CHECK_PYTHON_ERROR();
assert(print_foo);

PyObject *result = PyObject_CallObject(print_foo, NULL);
CHECK_PYTHON_ERROR();
assert(result);
}
Я скомпилировал foo.c в foo.so с помощью gcc foo.c -o foo.so -shared -fPIC -Wall -Wextra -Wpedantic -Wfatal-errors -g -lpython3.13 -I/home/trez/.pyenv/versions/3.13.0/include/python3.13 -L/home/trez/.pyenv/versions/3.13.0/lib -ldl -Wl,-rpath,/home/trez/.pyenv/versions/3.13.0/lib -lm, где они последние флаги получены при запуске python3.13-config --includes --ldflags.
Запуск python3.13 main.py выводит 1. Это означает, что оператор foo = 2 не выполнялся в экземпляре, который напечатал foo, что плохо.
Причина, по которой эта программа в настоящее время печатает 1, заключается в том, что поскольку вызов PyImport_ImportModule() (docs) по сути создает новую среду, а не повторно использует исходную.
Изменение на PyImport_AddModule() (docs) или PyImport_AddModuleRef() (документы) печатает это:

Код: Выделить всё

AttributeError: module 'main' has no attribute 'print_foo'
Error detected in foo.c:20
Если мы посмотрим на PyImport_AddModule его документацию, мы просто увидим:

Аналогично PyImport_AddModuleRef() , но возвращает заимствованную ссылку.

И если мы затем посмотрим на PyImport_AddModuleRef его документацию, то увидим вот это фрагмент:

Эта функция не загружает и не импортирует модуль; если модуль еще не был загружен, вы получите пустой объект модуля. Используйте PyImport_ImportModule() или один из его вариантов для импорта модуля.

Похоже, это означает, что AttributeError: модуль 'main' не имеет атрибута ' Ошибка print_foo' была вызвана тем, что модуль не загружался. Однако для меня это не имеет смысла, поскольку использование PyImport_AddModule/

Код: Выделить всё

PyImport_AddModuleRef
и добавив это после строки Assert(module);:

Код: Выделить всё

PyObject *g = PyEval_GetGlobals();
CHECK_PYTHON_ERROR();
PyObject *g_repr = PyObject_Repr(g);
CHECK_PYTHON_ERROR();
const char *s = PyUnicode_AsUTF8(g_repr);
CHECK_PYTHON_ERROR();
printf("s: '%s'\n", s);
печатает это:

Код: Выделить всё

s: '{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': , '__spec__': None, '__annotations__': {}, '__builtins__': , '__file__': '/home/trez/Programming/ctypes-run-bug/main.py', '__cached__': None, 'ctypes': , 'foo': , 'print_foo': , 'main': }'
AttributeError: module 'main' has no attribute 'print_foo'
Error detected in foo.c:28
Обратите внимание на «print_foo»: в конце первой строки, подразумевающую, что функция найдена.< /p>
Я предполагаю, что здесь происходит то, что эти глобальные переменные взяты из исходного экземпляра Python, но Вызов PyImport_AddModule("main") каким-то образом не может найти этот экземпляр. Приветствую.

Подробнее здесь: https://stackoverflow.com/questions/792 ... on-instanc
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

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