Cython:C++;具有嵌套typedef的类 根据StAdvOp溢出中的问题/答案,不可能直接在Cython中重写C++嵌套类型DEFDES。我有这样一个问题,我不知道哪种方法是正确的/最佳的
让我举一个更具体的例子。下面,你可以找到两个C++文件(一个报头,一个.h和一个.cp)和两个相应的Cython文件(一个PXD和一个PYX)的内容。在C++标题文件中,名为Cython:C++;具有嵌套typedef的类 根据StAdvOp溢出中的问题/答案,不可能直接在Cython中重写C++嵌套类型DEFDES。我有这样一个问题,我不知道哪种方法是正确的/最佳的,c++,class,nested,cython,typedef,C++,Class,Nested,Cython,Typedef,让我举一个更具体的例子。下面,你可以找到两个C++文件(一个报头,一个.h和一个.cp)和两个相应的Cython文件(一个PXD和一个PYX)的内容。在C++标题文件中,名为 CPPPyGrim.H./C>可以看到嵌套的Type文件声明;例如,对应于Graph::iterator::nn\u iterator的我不知道如何在相应的graph.pxd文件中公开它。或者,换句话说,我不知道什么是“官方”或“标准”方式 一些相关信息。如果您检查cython包装的STL,您可以找到嵌套的typedef。
Graph::iterator::nn\u iterator
的我不知道如何在相应的graph.pxd
文件中公开它。或者,换句话说,我不知道什么是“官方”或“标准”方式
一些相关信息。如果您检查cython包装的STL,您可以找到嵌套的typedef。例如,在utility.pxd
或vector.pxd
文件中。但是,ctypedef
的嵌套用法仅用于模板声明嵌套的typedef是否仅在cython中用于模板声明?
C++头文件:
// file : cpp_graph.h
#ifndef Included_cpp_graph
#define Included_cpp_graph
#include <cassert>
#include <cstddef>
#include <set>
#include <map>
#include <iostream>
#include <string>
#include <sstream>
#include "to_string_patch.h"
#ifndef Defined_bint
#define Defined_bint
typedef int bint;
#endif
class Graph {
public:
typedef std::set< int > t_nn;
typedef std::set< int >::iterator nn_iterator;
typedef std::map< int , t_nn > t_node_to_nn;
class iterator
{
// To iterate over nodes.
friend class Graph;
public:
typedef iterator self_type;
typedef int value_type;
typedef int & reference;
typedef int * pointer;
typedef t_node_to_nn::iterator map_iterator;
typedef std::forward_iterator_tag iterator_category;
iterator( map_iterator map_it ) : _map_it( map_it ) { }
self_type operator++() { _map_it++; return *this; } // PREFIX
self_type operator++(int junk) { self_type i = *this; _map_it++; return i; } // POSTFIX
value_type operator*() { return ( * _map_it ).first; } // Return the index "i"
Graph::t_nn * operator->() { return & ( * _map_it ).second; } // Return a pointer to the contained t_nn.
bool operator==( const self_type & rhs ) { return _map_it == rhs._map_it; }
bool operator!=( const self_type & rhs ) { return _map_it != rhs._map_it; }
private:
map_iterator _map_it;
};
class const_iterator
{
friend class Vertex;
public:
typedef const_iterator self_type;
typedef int value_type;
typedef int & reference;
typedef int * pointer;
typedef t_node_to_nn::iterator map_iterator;
typedef std::forward_iterator_tag iterator_category;
const_iterator( map_iterator map_it ) : _map_it( map_it ) { }
self_type operator++() { _map_it++; return *this; } // PREFIX
self_type operator++(int junk) { self_type i = *this; _map_it++; return i; } // POSTFIX
const value_type operator*() { return ( * _map_it ).first; } // Return the index "i"
const Graph::t_nn * operator->() { return & ( * _map_it ).second; } // Return a pointer to the contained t_nn.
bool operator==( const self_type& rhs ) { return _map_it == rhs._map_it; }
bool operator!=( const self_type& rhs ) { return _map_it != rhs._map_it; }
private:
map_iterator _map_it;
};
iterator begin() { _node_to_nn.begin(); }
iterator end() { _node_to_nn.end(); }
const_iterator begin() const { _node_to_nn.begin(); }
const_iterator end() const { _node_to_nn.end(); }
nn_iterator nn_begin( int i ) { assert( has_node( i ) ); return _node_to_nn[ i ].begin(); }
nn_iterator nn_end( int i ) { assert( has_node( i ) ); return _node_to_nn[ i ].end(); }
Graph() : _num_links( 0 ) {}
~Graph() { _node_to_nn.clear(); _num_links = 0; }
Graph & subgraph( std::set< int > & nodes ) {
Graph * S = new Graph();
for ( std::set< int >::iterator n_it = nodes.begin() ; n_it != nodes.end() ; n_it++ ) {
int i = ( * n_it );
assert( has_node( i ) );
for ( nn_iterator j_it = nn_begin( i ) ; j_it != nn_end( i ) ; j_it++ ) {
int j = ( * j_it );
if ( nodes.count( j ) > 0 ) { S -> add_link( i , j ); }
}
}
return ( * S );
}
int num_nodes() { return _node_to_nn.size(); }
int num_links() { return _num_links; }
int degree( int i ) { return _node_to_nn[ i ].size(); }
double avrg_degree() { return ( ( double ) 2 * num_nodes() ) / ( ( double ) _num_links ); }
bool has_node( int i ) { return _node_to_nn.count( i ) > 0; }
bool has_nn( int i , int j ) {
if ( has_node( i ) ) { return _node_to_nn[ i ].count( j ) > 0; }
return false;
}
bool has_link( int i , int j ) { return has_nn( i , j ); }
void add_node( int i ) { _node_to_nn[ i ].count( 0 ); } // Trick...
void add_link( int i , int j ) {
if ( has_link( i , j ) ) { return; }
_node_to_nn[ i ].insert( j );
_node_to_nn[ j ].insert( i );
_num_links += 1;
}
void del_link( int i , int j ) {
if ( has_link( i , j ) ) {
_node_to_nn[ i ].erase( j );
_node_to_nn[ j ].erase( i );
_num_links -= 1;
}
}
void del_node( int i ) {
iterator i_it = _node_to_nn.find( i );
for( nn_iterator j_it = i_it -> begin() ; j_it != i_it -> end() ; j_it++ ) { del_link( i , ( * j_it ) ); }
_node_to_nn.erase( i_it._map_it );
}
void clear_node( int i ) { del_node( i ); add_node( i ); } // Trick...
private:
t_node_to_nn _node_to_nn;
int _num_links;
};
std::ostream& operator<<( std::ostream& os , Graph & G );
typedef Graph::t_nn Graph_t_nn
typedef
#endif // Included_cpp_graph
我使用
名称空间
关键字获得了嵌套定义,指定了嵌套声明。比如,如果你在C++标题中有如下的名字:<代码> MyToo.HPP >:
namespace MyStuff {
struct Outer {
struct Inner {
int value;
};
Inner member;
};
}
…您可以像这样对这些结构进行加密:
cdef extern from "mystuff.hpp" namespace "MyStuff::Outer":
cppclass Inner:
int value
cdef extern from "mystuff.hpp" namespace "MyStuff":
cppclass Outer:
Inner member
…如果您将C++-land中的所有内容都封装在一个名称空间中(否则,第二个cdef
在其声明中没有名称空间,这在我看来更为复杂),那么它的阅读会更加连贯
我有许多现实世界中目前正在使用的例子:,。我认为嵌套TypeDef只允许在cython主分支中使用(即,在cython 0.25中发布时可用):此特定错误可通过将ctypedef
s向上移动到.pyx文件结构的模块级别来解决–换句话说,将ctypedef cset[int]t_nn
置于cdef extern
/cppclass图形
块的外部和上方。毕竟,模板类型cset
在.pyx文件中是全局可用的,而不是嵌套的–在您正在查看的头文件中有一个词汇相似的typedef
,这一事实在这种情况下没有什么区别(在编写cythonextern
定义时,不必指定标题中的所有内容)。感谢这两个有用的信息。最终,我找到了@fish2000在评论中提到的解决方案,并且是我现在正在实施的解决方案。但是,下面提到的解决方案似乎最合适。欢迎您使用–很高兴使用。您可能会想使用名称空间策略来解决此问题E你所拥有的内部迭代器结构,当然,你至少要把 TyPufF的所有实例更改为<代码> cTyWordFux/Cube >或类似的东西。最有可能的是,你可以用只从Cython中调用的方法和/或运算符来定义迭代器结构,省略大部分或全部的C++ BOI。lerplate.谢谢你的回答。它与我所怀疑的一致:嵌套的typedef定义暂时不起作用;我们必须通过“明确提及整个路径”来重新定义typedef的层次结构关于cython在我的代码中重新定义的冗余,我也同意你的观点。大多数定义/成员是不需要的,可以避免。我也在学习:)两个例子都是死的。我想知道您是否介意列出一个完整的示例或更新链接。@Jzl5325修复了它们,谢谢–我已继续重新组织该项目的目录结构。如果人为的例子缺少一些具体的东西,请告诉我,我也会补充。
# file : graph.pyx
# === Cython cimports ===
from libcpp cimport bool
from libcpp.set cimport set as cset
from libcpp.map cimport map as cmap
from cython.operator cimport dereference as deref, preincrement as inc
# === Ctypedefs for Graph class ===
# @ graph.pxd
# === Exposing the C++ Graph class ===
cdef extern from "cpp_graph2.h":
cdef cppclass Graph:
#public:
ctypedef cset[ int ] t_nn
ctypedef cset[ int ].iterator nn_iterator
ctypedef cmap[ int , t_nn ] t_node_to_nn
cppclass iterator:
#friend class Graph;
#public:
typedef iterator self_type
typedef int value_type
typedef int & reference
typedef int * pointer
typedef t_node_to_nn::iterator map_iterator
typedef std::forward_iterator_tag iterator_category
iterator( map_iterator map_it )
self_type operator++()
self_type operator++(int junk)
value_type operator*()
Graph::t_nn * operator->()
bool operator==( const self_type & rhs )
bool operator!=( const self_type & rhs )
#private:
# map_iterator _map_it;
cppclass const_iterator:
#friend class Vertex;
#public:
typedef const_iterator self_type
typedef int value_type
typedef int & reference
typedef int * pointer
typedef t_node_to_nn::iterator map_iterator
typedef std::forward_iterator_tag iterator_category
const_iterator( map_iterator map_it )
self_type operator++()
self_type operator++(int junk)
const value_type operator*()
const Graph::t_nn * operator->()
bool operator==( const self_type& rhs )
bool operator!=( const self_type& rhs )
#private:
# map_iterator _map_it;
iterator begin()
iterator end()
const_iterator begin() const
const_iterator end() const
nn_iterator nn_begin( int i )
nn_iterator nn_end( int i )
Graph()
~Graph()
Graph & subgraph( std::set< int > & nodes )
int num_nodes()
int num_links()
int degree( int i )
double avrg_degree()
bool has_node( int i )
bool has_nn( int i , int j )
bool has_link( int i , int j )
void add_node( int i )
void add_link( int i , int j )
void del_link( int i , int j )
void del_node( int i )
void clear_node( int i )
#private:
#t_node_to_nn _node_to_nn;
#int _num_links;
# === Python Wrapper for the C++ Graph class ===
cdef class PyGraph:
# === Data-members ===
# @ graph.pxd
# === Function-members ===
def __cinit__( self ):
self._c_graph = new Graph()
def __dealloc__( self ):
del self._c_graph
# TODO : implement the methods for adding and deleting nodes/links.
###########################################################
# setup build_ext...
###########################################################
Error compiling Cython file:
------------------------------------------------------------
...
# === Exposing the C++ Graph class ===
cdef extern from "cpp_graph2.h":
cdef cppclass Graph:
#public:
ctypedef cset[ int ] t_nn
^
------------------------------------------------------------
ExcessDegreeModel/graph.pxd:51:8: Expected an identifier, found 'ctypedef'
...
namespace MyStuff {
struct Outer {
struct Inner {
int value;
};
Inner member;
};
}
cdef extern from "mystuff.hpp" namespace "MyStuff::Outer":
cppclass Inner:
int value
cdef extern from "mystuff.hpp" namespace "MyStuff":
cppclass Outer:
Inner member