У меня есть два класса С++, которые, например, предполагают
class A
{
};
class B
{
};
Затем я оборачиваю их с помощью SWIG, чтобы создать привязки Python.
%include "A.h"
%include "B.h"
...etc
На стороне Python я использую их как
a = A()
b = B()
Я хотел бы каким-то образом обеспечить, чтобы порядок уничтожения был ~B()
, а затем ~A()
. Если они вызываются в другом порядке, ~B()
будет segfault из-за по существу висячих указателей.
Могу ли я каким-либо образом изменить интерфейс SWIG, чтобы сначала принудительно уничтожить B
? Например, разрешить его использование только в контекстном менеджере? Добавить ссылку на объект A
? Взять аргумент A
в конструкторе B
и увеличить его счетчик ссылок?
Что произойдет, если вы создадите B
без A
или A
без B
? Вы должны проектировать свои классы так, чтобы подобные вещи не могли произойти.
Я не уверен, что Ульрих имел в виду под диспетчером контекста, так что это может быть та же идея. Создайте новый класс AB, пусть AB обрабатывает создание и уничтожение классов A и B в коде C++. Передайте только AB в Python.
@john Что может быть правдой или ложью, но в целом, вероятно, бесполезный совет.
@ZanLynx: термин «менеджер контекста» — это термин Python. По сути, это гарантирует, что часть кода создается двумя операциями, одной при входе и одной при выходе, что очень похоже на, например, a scoped_lock
, который использует RAII.
Во-первых, Python не гарантирует порядок уничтожения. Если вам нужно что-то вроде RAII C++, используйте для этого контекстный менеджер.
Во-вторых, если ваш код на С++ дает сбои, это вина вашего кода на С++. В общем, вы должны стремиться к коду, который даже не компилируется, если его неправильно использовать. Здесь я предлагаю вам передать shared_ptr<A>
в B
, чтобы убедиться, что A
не уничтожен до B
.
Я хотел бы попробовать ваше второе предложение, но я думаю, что застрял на деталях. Я могу добавить std::shared_ptr<A>
в конструктор B
, но в приведенном выше коде Python, когда я говорю a = A()
, если я затем передам этот объект следующему объекту как b = B(a)
, как Python узнает, что a
является shared_ptr
, и не удалить его, так как b
теперь также имеет частичное владение им?
Вы можете оставить это Python, который будет следить за тем, чтобы объекты оставались живыми до тех пор, пока на них все еще есть ссылки.
Если дизайн вашего класса требует, чтобы объекты уничтожались в определенном порядке, то ваш дизайн класса неверен.