#c #python #templates #swig #shared-ptr
#c #python #шаблоны #swig #общий доступ-ptr
Вопрос:
Я использую SWIG с общими указателями boost для создания расширений python. Моя текущая проблема заключается в том, что макрос SWIG_SHARED_PTR, похоже, работает по-другому с шаблонными классами. Я приведу два примера, один без шаблонов (example) и один с шаблонами (example2).
Сначала я включу код, а в конце покажу разницу в поведении двух расширений в python.
Основная проблема заключается в том, что без шаблонов общие указатели отображаются в python как
<example.Derived; proxy of <Swig Object of type 'derived_sptr *' at 0xb772c4b8> >
принимая во внимание, что когда обернутый класс является созданным шаблоном, он отображается как
<Swig Object of type 'derived_int_sptr *' at 0xb787e4b8>
Я новичок в шаблонах C , поэтому вполне возможно, что проблемы, с которыми я сталкиваюсь, не имеют ничего общего с SWIG.
Без шаблонов (работает нормально)
example.h
#include <boost/shared_ptr.hpp>
#ifndef EXAMPLE_H
#define EXAMPLE_H
class Base {
public:
Base(int number1);
int get_number1();
virtual int get_number2() = 0;
protected:
int number1;
};
class Derived : public Base {
public:
Derived(int number1, int number2);
int get_number2();
private:
int number2;
};
typedef boost::shared_ptr<Base> base_sptr;
typedef boost::shared_ptr<Derived> derived_sptr;
derived_sptr make_derived(int number1, int number2);
int get_number1(base_sptr b);
#endif
example.cc
#include "example.h"
Base::Base(int number1) :
number1(number1)
{}
int Base::get_number1() {
return number1;
}
Derived::Derived(int number1, int number2) :
Base(number1),
number2(number2)
{}
int Derived::get_number2() {
return number2;
}
derived_sptr make_derived(int number1, int number2) {
return derived_sptr(new Derived(number1, number2));
}
int get_number1(base_sptr b) {
return b->get_number1();
}
пример.i
%module example
%{
#include "example.h"
%}
%include boost_shared_ptr.i
SWIG_SHARED_PTR(base_sptr, Base)
SWIG_SHARED_PTR_DERIVED(derived_sptr, Base, Derived)
%include example.h
With Templates (doesn’t work)
example2.h
#include <boost/shared_ptr.hpp>
#ifndef EXAMPLE2_H
#define EXAMPLE2_H
template <typename T>
class Base {
public:
Base(T number1);
T get_number1();
virtual T get_number2() = 0;
protected:
T number1;
};
template <typename T>
class Derived : public Base<T> {
public:
Derived(T number1, T number2);
T get_number2();
private:
T number2;
};
typedef Base<int> base_int;
typedef Derived<int> derived_int;
typedef boost::shared_ptr<base_int> base_int_sptr;
typedef boost::shared_ptr<derived_int> derived_int_sptr;
derived_int_sptr make_derived_int(int number1, int number2);
int get_number1_int(base_int_sptr b);
#endif
example2.cc
#include "example2.h"
template <typename T>
Base<T>::Base(T number1) :
number1(number1)
{}
template <typename T>
T Base<T>::get_number1() {
return number1;
}
template <typename T>
Derived<T>::Derived(T number1, T number2) :
Base<T>(number1),
number2(number2)
{}
template <typename T>
T Derived<T>::get_number2() {
return number2;
}
template class Base<int>;
template class Derived<int>;
derived_int_sptr make_derived_int(int number1, int number2) {
return derived_int_sptr(new Derived<int>(number1, number2));
}
int get_number1_int(base_int_sptr b) {
return b->get_number1();
}
пример2.i
%module example2
%{
#include "example2.h"
%}
%include boost_shared_ptr.i
SWIG_SHARED_PTR(base_int_sptr, base_int)
SWIG_SHARED_PTR_DERIVED(derived_int_sptr, base_int, derived_int)
%include example.h
%template(base_int) Base<int>;
%template(derived_int) Derived<int>;
Пример различия:
> import example
> d = example.make_derived(4, 5)
> d
> <example.Derived; proxy of <Swig Object of type 'derived_sptr *' at 0xb77327a0> >
> d.get_number1()
4
> example.get_number1(d)
4
> import example2
> d = example2.make_derived_int(4, 5)
> d
<Swig Object of type 'derived_int_sptr *' at 0xb787e4b8>
> d.get_number1()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'SwigPyObject' object has no attribute 'get_number1'
> example.get_number1_int(d)
4
Ответ №1:
SWIG может быть очень щепетилен в отношении порядка, в котором объекты отображаются в нем, с его внутренней системой типов.
Попробуйте переместить свои %template
инструкции так, чтобы они шли перед вашими SWIG_SHARED_PTR
инструкциями.
Комментарии:
1. Если я это сделаю, я получу сообщения об ошибках: example.i:7: Ошибка: Шаблон ‘Base’ не определен. пример.i: 8: Ошибка: «Производный» шаблон не определен. пример.i:11: Предупреждение (303): %extend определено для необъявленного класса derived_int. Я понимаю, что операторы %template должны появляться после определения шаблона, но макрос SWIG_SHARED_PTR должен появляться заранее. Я продолжу играть с упорядочением, чтобы посмотреть, смогу ли я заставить что-то работать. Спасибо за предложение.
2. Я нашел проблему. Спасибо за предложение, оно указало мне правильное направление.
Ответ №2:
В примере 2.i строки
SWIG_SHARED_PTR(base_int_sptr, base_int)
SWIG_SHARED_PTR_DERIVED(derived_int_sptr, base_int, derived_int)
должен быть заменен на
SWIG_SHARED_PTR(base_int_sptr, Base<int>)
SWIG_SHARED_PTR_DERIVED(derived_int_sptr, Base<int>, Derived<int>)