LINUX.ORG.RU

Python. Embedding. Пара вопросов.

 


0

3

Гайз, есть сабж.

1) как динамически засандалить в интерпретатор вот такую штуку?

module.object.method

т.е. без привлечения файла, на лету, как грится. искурили ман питоновский, но что-то не выходит каменный цветочек. простой вариант типа

module.method

делается легко (при инициализации скармливаешь массив функций). но мне надо разделить эти методы по дополнительным неймспейсам ибо названия функций могут совпадать по определенным причинам.

2) существует ли возможность обрабатывать одним хендлером несколько питоновских функций, но при этом знать названия функций, которые вызывают сишный хендлер (т.е. без костылей-оберток, которыми вручную подставлять называние)?

Deleted

Последнее исправление: cetjs2 (всего исправлений: 2)

module.object.method

мне надо разделить эти методы по дополнительным неймспейсам

Так тебе нужен объект или вложенный модуль?

обрабатывать одним хендлером несколько питоновских функций, но при этом знать названия функций, которые вызывают сишный хендлер (т.е. без костылей-оберток, которыми вручную подставлять называние)?

Теоретически, можно посмотреть стек вызовов, но проще сделать обертки. Судя по странности задачи, ты хочешь не того, о чем спрашиваешь.

P.S. Поскольку вопросы сформулированы по-норкомански, я на всякий случай спрошу - ты точно говоришь об embedding, т. е. встраивании интерпретатора в Си-программу?

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от tailgunner

Так тебе нужен объект или вложенный модуль?

без разницы, главное, чтобы можно было размещать функции с одинаковым названием.

Теоретически, можно посмотреть стек вызовов

не катит. на стековерфлоу чувак тоже посоветовал, но в стеке хранится только фунция которая вызывала мою с сишным колбеком. а мне нужно именно название моей точки входа.

Поскольку вопросы сформулированы по-норкомански

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

ты точно говоришь об embedding

да, именно, встраивание питона в сишный код. грубо говоря, представь, что я пишу софтину на ссях, к которой можно писать плагины на питоне (а-ля как саблайм это делает).

PS: пункт 1 вроде осилил.

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от Deleted

грубо говоря, представь, что я пишу софтину на ссях, к которой можно писать плагины на питоне (а-ля как саблайм это делает).

Если тебе нужно вызывать Си-функции из плагинов на Python, я бы сначала попробовал делать так: плагинам предоставляется интерфейс на Python, который занимается всей магией вроде «динамического засандаливания» и генерации оберток, а потом вызывает Си-функции через ctypes.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

давай поясню суть задачи...

есть софтина, которая запускает разные питоновские модули и должна для каждого модуля дать динамически набор функций, которые можно вызывать из модуля (для каждого свой такой набор функций). физически, тела этих функций отсутствуют, но есть один колбек для них всех. и вот мне в этом колбеке нужно понимать, какую динамическую функцию дернул модуль.

другими словами - есть два py файла, в одном из них есть вызовы фунций fun1 и fun2, тела которых отсутствуют, в другом fun3 и fun4 - то же самое. и вот, я запускаю свою сишную программу, котрая форкает чилдов для каждого модуля, те инициализируют интерпретатор, и суют в нейм спейс массив из двух функций, но в качестве хендлера этих функций (fun1 и fun2) я могу заюзать только статическую функцию (плюсами с объектами и методами тут не выехать). хардкодить два хендлера не могу ибо названия и количество этих функций отлично для каждого модуля.

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

Deleted
()
Ответ на: комментарий от tailgunner

для более наглядного представления...

мне прилетает python-файл и к нему прилагается некий спек-файл, где описаны названия функций, которые я должен обеспечить своим обработчиком. дальше моя софтина запускает этот модуль и динамически подставляет эти функции со своим колбеком, а потом по сети отправляет в другую систему инфу «такой-то модуль дернул такую-то функцию с таким-то параметром, что мне ему ответить?», система отвечает и я возвращаю модулю этот ответ.

Deleted
()
Ответ на: комментарий от Deleted

Ну я так и понял.

# mod1.py

import api

api.whatever.fun1()
api.whatever.fun2()
# api.py

import ctypes as ct

libself = ct.CDLL(None)
# здесь можно делать что угодно

class YouDontNeedThisButOhWell:
  def fun1():
    # здесь тоже можно делать что угодно
    libself.handler()

  def fun2():
    # и здесь тоже
    libself.handler()

whatever = YouDontNeedThisButOhWell()

(можно сделать и нормальную иерархию модулей вместо класса YouDontNeedThisButOhWell)

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

Как по мне, так вкрячивание объектов в неймспейс из Си (ты ведь это пытаешься сделать?) - гораздо худший говнокод.

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от tailgunner

собсно так и делал, через класс, но без ctypes.

(ты ведь это пытаешься сделать?) - гораздо худший говнокод.

говнокод для меня - генерить файл и потом его же скармливать интерпретатору, который я инициализировал у себя сишным кодом. вот это я считаю говнокодом. смысл этих телодвижений, если сей финт можно сделать штатными средствами питоновского API?

Deleted
()
Ответ на: комментарий от Deleted

говнокод для меня - генерить файл и потом его же скармливать интерпретатору

Я и не предлагал «генерить» файл.

смысл этих телодвижений, если сей финт можно сделать штатными средствами питоновского API?

Ну, если ты и правда предпочитаешь писать на Си то, что можно написать на Pytnon, дело твое.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Я и не предлагал «генерить» файл.

я ж говорю, у меня эти модули приходят в виде одного файла + спекфайл. т.е. либо я динамически вкрячиваю, либо генерю файло-обертку.

Deleted
()

если коротко:

PyMODINIT_FUNC
init_container(void)
{
  PyObject *m = Py_InitModule("container", ContainerMethods);
  if (m == NULL)
    return;
  
  PyObject *d, *module;
  d = PyModule_GetDict(m);
  module = PyImport_AddModule("module1");
  PyDict_SetItemString(d, "module1", module);
  Py_DECREF(module);
}
если полностью: http://pastebin.com/q6hdu3Vh

anonymous
()

Python. Embedding.

пистонутые совсем мозги свои протрахали...

anonymous
()
Ответ на: комментарий от Deleted

у меня эти модули приходят в виде одного файла + спекфайл. т.е. либо я динамически вкрячиваю, либо генерю файло-обертку.

Ладно, я напишу это еще раз, но точно последний: если бы динамическое вкрячивание было написано на Python (а не Python C API) оно было бы гораздо проще. Почти тривиально. </thread>

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

в твоем примере есть статик функция test_add. представь, что эту функцию мы забиндили к двум питон методам add и add1. нужно внутри test_add распознать откуда пришёл вызов, из add или add1

Deleted
()
Ответ на: комментарий от anonymous

я потерял нить твоих мыслей :). у тебя хороший пример, я именно так и делал, но беда в том, что мне нужно каким-то образом отличить внутри такой статической функции откуда приходит вызов. т.е. мне нужно откуда-то выудить название «add» или «add1». вот с этим я пока не могу разобраться. буду признателен, если подскажешь.

Deleted
()
Ответ на: комментарий от anonymous

хмм, странно, что мне не попалась эта ветка. вроде с гуглом у меня отношения хорошие, не ругались, а на эту страницу меня никак не вывело после всех моих потуг в поиске солюшена. спасибо!

Deleted
()
Ответ на: комментарий от Deleted

только у меня повторить не получилось. для обычных питон функций имена правильные, а для функций си модуля имена <module>.

anonymous
()
Ответ на: комментарий от Deleted
#include <frameobject.h>

static PyObject *
test_add(PyObject *self, PyObject *args)
{
    int a,b;
    if (!PyArg_ParseTuple(args, "ii", &a, &b))
        return NULL;

    PyThreadState * ts = PyThreadState_Get();
    PyObject* obj = *ts->frame->f_valuestack;
    obj = PyObject_GetAttrString(obj, "__name__");
    obj = PyObject_Repr(obj);
    const char* text = PyString_AsString(obj);

    printf("%s\n",
        text
    );

    return PyLong_FromLong(a+b);
}
anonymous
()
Ответ на: комментарий от Deleted

даже строчка лишняя есть:

obj = PyObject_Repr(obj);
и контроль ссылок нужно к этому приделать

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.