nataraj: (Default)
Swami Dhyan Nataraj ([personal profile] nataraj) wrote2022-07-28 10:51 pm
Entry tags:

Призовая игра с встраиванием питона

Я не возьмусь определять что мне более отвратительно libboost или python. Но право скажу собранные вместе в boost::python они производят на свет субстанцию непревзойденного свойства.

 #include <boost/python.hpp>
 #include <stdio.h>

int main()
{
  Py_InitializeEx(0);

  boost::python::object modMath = boost::python::import("math");
  boost::python::object cosFunc = modMath.attr("cos");

  Py_Finalize();
}

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

Историю с локализацией места проблемы в портируемой программе с последующим вынесением в приведенный standalone, я опущу из-за малосодержательности и нецензурности... Скажу только, что gdb плюс правильно выбранные места для breakpoint'ов рулят.

Далее в процессе плясок вокруг этого примера вдруг обнаруживаю что вот так не падает:

int main()
{
  Py_InitializeEx(0);
  {
    boost::python::object modMath = boost::python::import("math");
    boost::python::object cosFunc = modMath.attr("cos");
  }
  Py_Finalize();
}

Ага! думаю я. Оно позвало деструктор до финалайза а не после и все перестало падать... Надо сделать так же!

Но вот проблема... аналог переменной cosFunc в портируемой программе глобальная... Создается пустая, а потом после инициалайза заполняется. Можно было бы раскинуть мозгами, как запихнуть туда указатель вместо самого объекта, и сказать ему в нужный момент delete. Но менять весь остальной код очень не хотелось...

А нельзя ли так, чтобы для сложного объекта вызвался деструктор а сам объект опять заполнить пустым значением?

Оказывается можно:

int main()
{
  Py_InitializeEx(0);
  boost::python::object cosFunc;
  {
    boost::python::object modMath  = boost::python::import("math");
    cosFunc = modMath.attr("cos");
  }
  cosFunc = boost::python::object();
  Py_Finalize();
}

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

И вот так -- тоже не падает...

P.S. Отдельно доставила рекомендация документации на 1.55 boost::python просто не вызывать Py_Finalize(), типа не надо вам это.

P.P.S. Пришел к мысли что сам питон не падает только потому что и так ползает. And you should not boost it.

P.P.P.S. Честно говоря не верил, что осилю с этим разобраться. Без знания, что буста, что питона... Ан нет, получилось...

vitus_wagner: My photo 2005 (Default)

[personal profile] vitus_wagner 2022-07-29 12:49 pm (UTC)(link)

Сам питон не падает, потому что не на плюсах написан.

Но вообще, если подумать, в переходе от 2-го питона к 3-му есть что-то общее с переходом от C к C++.

А в Tcl вообще этот переход замаскировали внутри минорно версии - от 8.0 к 8.1.

Edited 2022-07-29 12:52 (UTC)
vitus_wagner: My photo 2005 (Default)

[personal profile] vitus_wagner 2022-07-29 12:53 pm (UTC)(link)

Ну и кто ж тебе доктор не знать питона. Не любить его ты имеешь право, но не знать-то зачем? Я вот windows не люблю, однако ж Рихтера прочитал. И C++ не люблю, а труп страуса прорабатывал аж дважды - 2-е издание и 4-е.

vitus_wagner: My photo 2005 (Default)

[personal profile] vitus_wagner 2022-07-31 05:54 am (UTC)(link)

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

Особенно если программирование для тебя про философию, знать типичные когнитивные ловушки. в которые попадаются люди, занимающиеся этим - надо.

Тут как раз windows является такой типичной когнитивной ловушкой.

С питоном как с экосистемой еще интереснее. Там у истоков стояли люди с вполне нормальным философским взглядом на мир, тот же Гвидо. Но потом понабежали как раз люди, испорченный неправильным ООП Java и Windows.