Я пытаюсь разработать оболочку Cython для библиотеки вычислительной топологии C++ GUDHI (http://gudhi.gforge.inria.fr). Классы GUDHI принимают другие классы в качестве своих аргументов, и эти классы передают другие подклассы своим методам. Так что довольно грязно нажимать прямо на Cython. У меня есть пример кода ниже.
Я разместил вопрос в группе cython google, и кто-то предложил мне написать упрощающую оболочку на C++, чтобы скрыть эту сложность от Cython. текст комментария приведен ниже.
Альтернативой, если все усложняется, является написание упрощающих оболочек на C++ и их вызов. (Раньше это было необходимо до того, как Cython поддержал любой C++, и все еще может быть полезным, если используются эзотерические функции C++, даже если это просто объявление пары определений типов. В приведенном ниже коде, где он определяет (и отменяет и переопределяет (!)) макросы, чтобы справиться с тем, что в противном случае было бы очень многословным кодом, это может быть вашим лучшим выбором.) Вы также можете выполнять приведения [1] (динамические или иные) для преобразования между типами, которые Cython не знает, связаны.
Вот пример кода, чтобы дать вам представление об иерархии.
typedef CGAL::Epick_d< CGAL::Dimension_tag<2> > Kernel;
--- needs to be passed into
Gudhi::alpha_complex::Alpha_complex<Kernel> alpha_complex_from_points(points, alpha_square_max_value);
Epick_d.h
--- Epick_d.h depends upon these libraries
#include <CGAL/NewKernel_d/Cartesian_base.h>
#include <CGAL/NewKernel_d/Cartesian_static_filters.h>
#include <CGAL/NewKernel_d/Cartesian_filter_K.h>
#include <CGAL/NewKernel_d/Wrapper/Cartesian_wrap.h>
#include <CGAL/NewKernel_d/Kernel_d_interface.h>
#include <CGAL/internal/Exact_type_selector.h>
#include <CGAL/Interval_nt.h>
--- Sample source code for Epick_d.h
namespace CGAL {
#define CGAL_BASE \
Cartesian_filter_K< Cartesian_base_d<double, Dim>, \
Cartesian_base_d<Interval_nt_advanced, Dim>, \
Cartesian_base_d<internal::Exact_field_selector<double>::Type, Dim> \
>
template<class Dim>
struct Epick_d_help1
: CGAL_BASE
{
CGAL_CONSTEXPR Epick_d_help1(){}
CGAL_CONSTEXPR Epick_d_help1(int d):CGAL_BASE(d){}
};
#undef CGAL_BASE
#define CGAL_BASE \
Cartesian_static_filters<Dim,Epick_d_help1<Dim>,Epick_d_help2<Dim> >
template<class Dim>
struct Epick_d_help2
: CGAL_BASE
{
CGAL_CONSTEXPR Epick_d_help2(){}
CGAL_CONSTEXPR Epick_d_help2(int d):CGAL_BASE(d){}
};
#undef CGAL_BASE
#define CGAL_BASE \
Kernel_d_interface< \
Cartesian_wrap< \
Epick_d_help2<Dim>, \
Epick_d<Dim> > >
template<class Dim>
struct Epick_d
: CGAL_BASE
{
CGAL_CONSTEXPR Epick_d(){}
CGAL_CONSTEXPR Epick_d(int d):CGAL_BASE(d){}
};
#undef CGAL_BASE
}
#endif
Я не знаю, как разработать оболочку C++, которая будет совместима с Cython, но при этом скроет иерархию от Cython.
Вот моя идея, но я не был уверен, что это то, что подразумевается под упрощающей оболочкой. Таким образом, класс GUDHI берет массив n-мерных точек, а затем выполняет над ними некоторые геометрические вычисления. Так что прямо сейчас, если я хочу напрямую обернуть класс GUDHI, например Simplex_tree(subclass)
, мне нужно сообщить об этом Cython. Вместо этого я мог бы написать класс C++, который просто брал бы массив точек, вычислял результаты и затем возвращал бы массив. Итак, в каком-то псевдокоде что-то вроде
Class(*array)
constructor(*array)
loop:
take values from *array and create CGAL::Point_d
push new CGAL::Point_d to std::vector<CGAL::Point_d>
include all of the hierarchical class operations here.
method_1(std::vector)
include all of the hierarchical operations here, but
return the result as a simple array or struct.
Смогу ли я тогда обернуть этот класс в cython без необходимости передавать всю иерархию классов, потому что я только передаю указатель массива на функцию?