Pcbnew: major swig fix.

* Switched hashtables.h over to std::undordered_map from boost version.

* Added new macros DECL_VEC_FOR_SWIG() and DECL_MAP_FOR_SWIG() in macros.h.
  These along with future DECL_HASH_FOR_SWIG() unify the declaration to swig
  and C++ so that the resultant type name is common in both languages, and
  the types AGREE.

* Fixed swigging of NETINFO_ITEM and NETINFO_LIST via magic.

* Newly exposed (python wrapped) are: D_PADS, TRACKS (was TRACK_PTRS),
  NETNAME_MAP, NETCODE_MAP, wxString (without constructor purposely, read
  comment in wx.i), MARKERS, ZONE_CONTAINERS, NETCLASSPTR, KICAD_T types.

* std::vector<SOMETHING*> tends to end up named SOMETHINGS in C++ and python.
  Having the name consistent between like types is helpful, and between
  languages.  std::map<> ends up as SOMETHING_MAP.

* NETINFO_LIST::m_netNames and NETINFO_LIST::m_netCodes are now std::map
  instead of hashtables, because swig does not yet support std::unordered_map.

* You can now get to any netclass or net info.   NETNAMES_MAP and NETCODES_MAP
  are traversable basically the same as a python dictionary using a python
  string (not wsString) as the key!  The wxString typemap converts python
  string to wxString before the lookup happens.  Iteration also works.
This commit is contained in:
Dick Hollenbeck 2016-07-18 13:23:09 -04:00 committed by Wayne Stambaugh
parent f83a76a970
commit e24990146d
19 changed files with 716 additions and 539 deletions

View File

@ -41,6 +41,7 @@
#include <class_eda_rect.h>
#include <functional>
#if defined(DEBUG)
#include <iostream> // needed for Show()
extern std::ostream& operator <<( std::ostream& out, const wxSize& size );
@ -86,17 +87,20 @@ class MSG_PANEL_ITEM;
/**
* Typedef INSPECTOR
* is used to inspect and possibly collect the
* (search) results of Iterating over a list or tree of KICAD_T objects.
* (search) results of iterating over a list or tree of KICAD_T objects.
* Provide an implementation as needed to inspect EDA_ITEMs visited via
* the EDA_ITEM::Visit() and EDA_ITEM::IterateForward().
* EDA_ITEM::Visit() and EDA_ITEM::IterateForward().
* <p>
* The lambda function is used within the EDA_ITEM::Iterate() function.
* It is used primarily for searching, but not limited to that. It can also
* collect or modify the scanned objects.
* FYI the std::function may hold a lambda, std::bind, pointer to func, or
* ptr to member function, per modern C++. It is used primarily for searching,
* but not limited to that. It can also collect or modify the scanned objects.
* 'Capturing' lambdas are particularly convenient because they can use context
* and this often means @a aTestData is not used.
*
* @param aItem An EDA_ITEM to examine.
* @param aTestData is arbitrary data needed by the inspector to determine
* if the EDA_ITEM under test meets its match criteria.
* if the EDA_ITEM under test meets its match criteria, and is often NULL
* with the advent of capturing lambdas.
* @return A #SEARCH_RESULT type #SEARCH_QUIT if the iterator function is to
* stop the scan, else #SEARCH_CONTINUE;
*/

View File

@ -55,7 +55,8 @@ class EDA_ITEM;
class COLLECTOR
{
protected:
INSPECTOR_FUNC m_inspector;
/// a class common bridge into the polymorphic Inspect()
INSPECTOR_FUNC m_inspector;
/// Which object types to scan
const KICAD_T* m_ScanTypes;
@ -75,7 +76,7 @@ protected:
public:
COLLECTOR() :
// Inspect() is virtual so calling it from a class common inspector preserves polymorphism.
m_inspector( [=] ( EDA_ITEM* aItem, void* aTestData ) { return Inspect( aItem, aTestData ); } )
m_inspector( [=] ( EDA_ITEM* aItem, void* aTestData ) { return this->Inspect( aItem, aTestData ); } )
{
m_ScanTypes = 0;
m_TimeAtCollection = 0;

View File

@ -26,10 +26,63 @@
#ifndef __KICAD_TYPEINFO_H
#define __KICAD_TYPEINFO_H
#ifndef SWIG
#include <cstdio>
template<typename T>
struct remove_pointer
{
typedef T type;
};
template<typename T>
struct remove_pointer<T*>
{
typedef typename remove_pointer<T>::type type;
};
/**
* Function IsA()
*
* Checks if the type of aObject is T.
* @param aObject object for type check
* @return true, if aObject type equals T.
*/
template <class T, class I>
bool IsA( const I* aObject )
{
return aObject && remove_pointer<T>::type::ClassOf( aObject );
}
template <class T, class I>
bool IsA( const I& aObject )
{
return remove_pointer<T>::type::ClassOf( &aObject );
}
/**
* Function dyn_cast()
*
* A lightweight dynamic downcast. Casts aObject to type Casted*.
* Uses EDA_ITEM::Type() and EDA_ITEM::ClassOf() to check if type matches.
* @param aObject object to be casted
* @return down-casted object or NULL if type doesn't match Casted.
*/
template<class Casted, class From>
Casted dyn_cast( From aObject )
{
if( remove_pointer<Casted>::type::ClassOf ( aObject ) )
return static_cast<Casted>( aObject );
return NULL;
}
class EDA_ITEM;
#endif // SWIG
/**
* Enum KICAD_T
* is the set of class identification values, stored in EDA_ITEM::m_StructType
@ -129,52 +182,4 @@ enum KICAD_T
MAX_STRUCT_TYPE_ID
};
template<typename T>
struct remove_pointer
{
typedef T type;
};
template<typename T>
struct remove_pointer<T*>
{
typedef typename remove_pointer<T>::type type;
};
/**
* Function IsA()
*
* Checks if the type of aObject is T.
* @param aObject object for type check
* @return true, if aObject type equals T.
*/
template <class T, class I>
bool IsA( const I* aObject )
{
return aObject && remove_pointer<T>::type::ClassOf( aObject );
}
template <class T, class I>
bool IsA( const I& aObject )
{
return remove_pointer<T>::type::ClassOf( &aObject );
}
/**
* Function dyn_cast()
*
* A lightweight dynamic downcast. Casts aObject to type Casted*.
* Uses EDA_ITEM::Type() and EDA_ITEM::ClassOf() to check if type matches.
* @param aObject object to be casted
* @return down-casted object or NULL if type doesn't match Casted.
*/
template<class Casted, class From>
Casted dyn_cast( From aObject )
{
if( remove_pointer<Casted>::type::ClassOf ( aObject ) )
return static_cast<Casted>( aObject );
return NULL;
}
#endif // __KICAD_TYPEINFO_H

View File

@ -28,32 +28,10 @@
#include <base_struct.h>
#include <wx/string.h>
// Three strategies for providing a portable hashtable are given.
// C++, boost, and wx, in that order. C++ solution is no good for mingw.
// So boost seems best for all platforms.
// Two competing strategies for providing portable hashtables are given:
// std C++ and boost.
#if 0 // C++ std::unordered_map, maybe in the future
#include <unordered_map>
/// Map a C string to an integer. Used in DSNLEXER.
typedef std::unordered_map< std::string, int > KEYWORD_MAP;
/// Map a C string to an EDA_RECT.
/// The key is the classname of the derived wxformbuilder dialog.
typedef std::unordered_map< std::string, EDA_RECT > RECT_MAP;
#elif 1 // boost::unordered_map
// fix a compile bug at line 97 of boost/detail/container_fwd.hpp
#define BOOST_DETAIL_TEST_FORCE_CONTAINER_FWD
#include <boost/unordered_map.hpp>
// see http://www.boost.org/doc/libs/1_49_0/doc/html/boost/unordered_map.html
// First some utility classes and functions common to both strategies..
/// Equality test for "const char*" type used in very specialized KEYWORD_MAP below
struct iequal_to : std::binary_function< const char*, const char*, bool >
@ -117,6 +95,57 @@ struct WXSTRING_HASH : std::unary_function<wxString, std::size_t>
};
class NETINFO_ITEM;
#if 1 // C++ std::unordered_map, trying it now
#include <unordered_map>
#ifdef SWIG
/// Declare a std::unordered_map and also the swig %template in unison
#define DECL_HASH_FOR_SWIG(TypeName, KeyType, ValueType) namespace std { %template(TypeName) unordered_map<KeyType, ValueType>; } typedef std::unordered_map<KeyType, ValueType> TypeName;
#else
/// Declare a std::unordered_map but no swig %template
#define DECL_HASH_FOR_SWIG(TypeName, KeyType, ValueType) typedef std::unordered_map<KeyType, ValueType> TypeName;
#endif
/**
* Type KEYWORD_MAP
* is a hashtable made of a const char* and an int. Note that use of this
* type outside very specific circumstances is foolish since there is no storage
* provided for the actual C string itself. This type assumes use with type KEYWORD
* that is created by CMake and that table creates *constant* storage for C strings
* (and pointers to those C strings). Here we are only interested in the C strings
* themselves and only the pointers are duplicated within the hashtable.
* If the strings were not constant and fixed, this type would not work.
* Also note that normally a hashtable (i.e. unordered_map) using a const char* key
* would simply compare the 32 bit or 64 bit pointers themselves, rather than
* the C strings which they are known to point to in this context.
* I force the latter behavior by supplying both "hash" and "equality" overloads
* to the hashtable (unordered_map) template.
* @author Dick Hollenbeck
*/
typedef std::unordered_map< const char*, int, fnv_1a, iequal_to > KEYWORD_MAP;
/// Map a C string to an EDA_RECT.
/// The key is the classname of the derived wxformbuilder dialog.
typedef std::unordered_map< std::string, EDA_RECT > RECT_MAP;
#elif 1 // boost::unordered_map
// fix a compile bug at line 97 of boost/detail/container_fwd.hpp
#define BOOST_DETAIL_TEST_FORCE_CONTAINER_FWD
#include <boost/unordered_map.hpp>
// see http://www.boost.org/doc/libs/1_49_0/doc/html/boost/unordered_map.html
/**
* Type KEYWORD_MAP
* is a hashtable made of a const char* and an int. Note that use of this
@ -140,6 +169,9 @@ typedef boost::unordered_map< const char*, int, fnv_1a, iequal_to > KEYWORD_
/// The key is the classname of the derived wxformbuilder dialog.
typedef boost::unordered_map< std::string, EDA_RECT > RECT_MAP;
typedef boost::unordered_map< const wxString, NETINFO_ITEM*, WXSTRING_HASH > NETNAMES_MAP;
typedef boost::unordered_map< const int, NETINFO_ITEM* > NETCODES_MAP;
#endif
#endif // HASHTABLES_H_

View File

@ -24,13 +24,16 @@
/**
* @file macros.h
* @brief This file contains miscellaneous helper definitions and functions.
* @brief This file contains miscellaneous commonly used macros and functions.
*/
#ifndef MACROS_H
#define MACROS_H
#include <wx/wx.h>
#include <vector>
#include <map>
/**
* Macro TO_UTF8
@ -116,4 +119,15 @@ template <typename T> inline const T& Clamp( const T& lower, const T& value, con
}
#endif /* ifdef MACRO_H */
#ifdef SWIG
/// Declare a std::vector and also the swig %template in unison
#define DECL_VEC_FOR_SWIG(TypeName, MemberType) namespace std { %template(TypeName) vector<MemberType>; } typedef std::vector<MemberType> TypeName;
#define DECL_MAP_FOR_SWIG(TypeName, KeyType, ValueType) namespace std { %template(TypeName) map<KeyType, ValueType>; } typedef std::map<KeyType, ValueType> TypeName;
#else
/// Declare a std::vector but no swig %template
#define DECL_VEC_FOR_SWIG(TypeName, MemberType) typedef std::vector<MemberType> TypeName;
#define DECL_MAP_FOR_SWIG(TypeName, KeyType, ValueType) typedef std::map<KeyType, ValueType> TypeName;
#endif
#endif // MACROS_H

View File

@ -126,6 +126,7 @@ public:
*/
static int uni_forward( const unsigned char* aSequence, unsigned* aResult = NULL );
#ifndef SWIG
/**
* class uni_iter
* is a non-muting iterator that walks through unicode code points in the UTF8 encoded
@ -225,6 +226,7 @@ public:
{
return uni_iter( data() + size() );
}
#endif // SWIG
};
#endif // UTF8_H_

View File

@ -176,7 +176,7 @@ void BOARD::Move( const wxPoint& aMoveVector ) // overload
}
void BOARD::chainMarkedSegments( wxPoint aPosition, const LSET& aLayerSet, TRACK_PTRS* aList )
void BOARD::chainMarkedSegments( wxPoint aPosition, const LSET& aLayerSet, TRACKS* aList )
{
LSET layer_set = aLayerSet;
@ -1608,7 +1608,7 @@ TRACK* BOARD::GetVisibleTrack( TRACK* aStartingTrace, const wxPoint& aPosition,
#if defined(DEBUG) && 0
static void dump_tracks( const char* aName, const TRACK_PTRS& aList )
static void dump_tracks( const char* aName, const TRACKS& aList )
{
printf( "%s: count=%zd\n", aName, aList.size() );
@ -1634,7 +1634,7 @@ TRACK* BOARD::MarkTrace( TRACK* aTrace, int* aCount,
double* aTraceLength, double* aPadToDieLength,
bool aReorder )
{
TRACK_PTRS trackList;
TRACKS trackList;
if( aCount )
*aCount = 0;
@ -1704,8 +1704,8 @@ TRACK* BOARD::MarkTrace( TRACK* aTrace, int* aCount,
}
else // mark the chain using both ends of the initial segment
{
TRACK_PTRS from_start;
TRACK_PTRS from_end;
TRACKS from_start;
TRACKS from_end;
chainMarkedSegments( aTrace->GetStart(), layer_set, &from_start );
chainMarkedSegments( aTrace->GetEnd(), layer_set, &from_end );

View File

@ -59,9 +59,6 @@ class REPORTER;
class RN_DATA;
class SHAPE_POLY_SET;
// non-owning container of item candidates when searching for items on the same track.
typedef std::vector< TRACK* > TRACK_PTRS;
/**
* Enum LAYER_T
@ -156,6 +153,11 @@ protected:
};
DECL_VEC_FOR_SWIG(MARKERS, MARKER_PCB*)
DECL_VEC_FOR_SWIG(ZONE_CONTAINERS, ZONE_CONTAINER*)
DECL_VEC_FOR_SWIG(TRACKS, TRACK*)
/**
* Class BOARD
* holds information pertinent to a Pcbnew printed circuit board.
@ -168,15 +170,9 @@ private:
/// the board filename
wxString m_fileName;
// @todo: switch to boost:ptr_vector, and change ~BOARD()
typedef std::vector<MARKER_PCB*> MARKERS;
/// MARKER_PCBs for clearance problems, owned by pointer.
MARKERS m_markers;
// @todo: switch to boost::ptr_vector, and change ~BOARD()
typedef std::vector<ZONE_CONTAINER*> ZONE_CONTAINERS;
/// edge zone descriptors, owned by pointer.
ZONE_CONTAINERS m_ZoneDescriptorList;
@ -214,7 +210,7 @@ private:
* @param aLayerSet The allowed layers for segments to search.
* @param aList The track list to fill with points of flagged segments.
*/
void chainMarkedSegments( wxPoint aPosition, const LSET& aLayerSet, TRACK_PTRS* aList );
void chainMarkedSegments( wxPoint aPosition, const LSET& aLayerSet, TRACKS* aList );
public:
static inline bool ClassOf( const EDA_ITEM* aItem )
@ -778,15 +774,12 @@ public:
/**
* Function GetPads
* returns a list of all the pads by value. The returned list is not
* returns a reference to a list of all the pads. The returned list is not
* sorted and contains pointers to PADS, but those pointers do not convey
* ownership of the respective PADs.
* @return std::vector<D_PAD*> - a full list of pads
* @return D_PADS - a full list of pads
*/
std::vector<D_PAD*> GetPads()
{
return m_NetInfo.m_PadsFullList;
}
const D_PADS& GetPads() { return m_NetInfo.m_PadsFullList; }
void BuildListOfNets()
{

View File

@ -119,7 +119,7 @@ bool NETCLASSES::Add( NETCLASSPTR aNetClass )
NETCLASSPTR NETCLASSES::Remove( const wxString& aNetName )
{
NETCLASSMAP::iterator found = m_NetClasses.find( aNetName );
NETCLASS_MAP::iterator found = m_NetClasses.find( aNetName );
if( found != m_NetClasses.end() )
{
@ -137,7 +137,7 @@ NETCLASSPTR NETCLASSES::Find( const wxString& aName ) const
if( aName == NETCLASS::Default )
return m_Default;
NETCLASSMAP::const_iterator found = m_NetClasses.find( aName );
NETCLASS_MAP::const_iterator found = m_NetClasses.find( aName );
if( found == m_NetClasses.end() )
return NETCLASSPTR();

View File

@ -34,6 +34,7 @@
#include <set>
#include <map>
#include <macros.h>
#include <wx/string.h>
#include <richio.h>
@ -207,7 +208,14 @@ public:
#endif
};
typedef std::shared_ptr<NETCLASS> NETCLASSPTR;
#ifdef SWIG
%shared_ptr( NETCLASSPTR );
#endif
DECL_MAP_FOR_SWIG( NETCLASS_MAP, wxString, NETCLASSPTR );
/**
* Class NETCLASSES
@ -218,10 +226,9 @@ typedef std::shared_ptr<NETCLASS> NETCLASSPTR;
class NETCLASSES
{
private:
typedef std::map<wxString, NETCLASSPTR> NETCLASSMAP;
/// all the NETCLASSes except the default one.
NETCLASSMAP m_NetClasses;
NETCLASS_MAP m_NetClasses;
/// the default NETCLASS.
NETCLASSPTR m_Default;
@ -239,11 +246,11 @@ public:
m_NetClasses.clear();
}
typedef NETCLASSMAP::iterator iterator;
typedef NETCLASS_MAP::iterator iterator;
iterator begin() { return m_NetClasses.begin(); }
iterator end() { return m_NetClasses.end(); }
typedef NETCLASSMAP::const_iterator const_iterator;
typedef NETCLASS_MAP::const_iterator const_iterator;
const_iterator begin() const { return m_NetClasses.begin(); }
const_iterator end() const { return m_NetClasses.end(); }

View File

@ -30,15 +30,14 @@
* Classes to handle info on nets
*/
#ifndef __CLASSES_NETINFO__
#define __CLASSES_NETINFO__
#ifndef CLASS_NETINFO_
#define CLASS_NETINFO_
#include <macros.h>
#include <gr_basic.h>
#include <class_netclass.h>
#include <class_board_item.h>
#include <boost/unordered_map.hpp>
#include <hashtables.h>
class wxDC;
@ -46,7 +45,6 @@ class wxPoint;
class LINE_READER;
class EDA_DRAW_PANEL;
class EDA_DRAW_FRAME;
class NETINFO_ITEM;
class D_PAD;
class BOARD;
class BOARD_ITEM;
@ -117,363 +115,7 @@ public:
};
class NETINFO_MAPPING
{
public:
NETINFO_MAPPING()
{
m_board = NULL;
}
/**
* Function SetBoard
* Sets a BOARD object that is used to prepare the net code map.
*/
void SetBoard( const BOARD* aBoard )
{
m_board = aBoard;
Update();
}
/**
* Function Update
* Prepares a mapping for net codes so they can be saved as consecutive numbers.
* To retrieve a mapped net code, use translateNet() function after calling this.
*/
void Update();
/**
* Function Translate
* Translates net number according to the map prepared by Update() function. It
* allows to have items stored with consecutive net codes.
* @param aNetCode is an old net code.
* @return Net code that follows the mapping.
*/
int Translate( int aNetCode ) const;
#ifndef SWIG
///> Wrapper class, so you can iterate through NETINFO_ITEM*s, not
///> std::pair<int/wxString, NETINFO_ITEM*>
class iterator
{
public:
iterator( std::map<int, int>::const_iterator aIter, const NETINFO_MAPPING* aMapping ) :
m_iterator( aIter ), m_mapping( aMapping )
{
}
/// pre-increment operator
const iterator& operator++()
{
++m_iterator;
return *this;
}
/// post-increment operator
iterator operator++( int )
{
iterator ret = *this;
++m_iterator;
return ret;
}
NETINFO_ITEM* operator*() const;
NETINFO_ITEM* operator->() const;
bool operator!=( const iterator& aOther ) const
{
return m_iterator != aOther.m_iterator;
}
bool operator==( const iterator& aOther ) const
{
return m_iterator == aOther.m_iterator;
}
private:
std::map<int, int>::const_iterator m_iterator;
const NETINFO_MAPPING* m_mapping;
};
/**
* Function begin()
* Returns iterator to the first entry in the mapping.
* NOTE: The entry is a pointer to the original NETINFO_ITEM object, this it contains
* not mapped net code.
*/
iterator begin() const
{
return iterator( m_netMapping.begin(), this );
}
/**
* Function end()
* Returns iterator to the last entry in the mapping.
* NOTE: The entry is a pointer to the original NETINFO_ITEM object, this it contains
* not mapped net code.
*/
iterator end() const
{
return iterator( m_netMapping.end(), this );
}
#endif
/**
* Function GetSize
* @return Number of mapped nets (i.e. not empty nets for a given BOARD object).
*/
int GetSize() const
{
return m_netMapping.size();
}
private:
///> Board for which mapping is prepared
const BOARD* m_board;
///> Map that allows saving net codes with consecutive numbers (for compatibility reasons)
std::map<int, int> m_netMapping;
};
/**
* Class NETINFO_LIST
* is a container class for NETINFO_ITEM elements, which are the nets. That makes
* this class a container for the nets.
*/
class NETINFO_LIST
{
friend class BOARD;
public:
NETINFO_LIST( BOARD* aParent );
~NETINFO_LIST();
/**
* Function GetItem
* @param aNetCode = netcode to identify a given NETINFO_ITEM
* @return NETINFO_ITEM* - by \a aNetCode, or NULL if not found
*/
NETINFO_ITEM* GetNetItem( int aNetCode ) const
{
NETCODES_MAP::const_iterator result = m_netCodes.find( aNetCode );
if( result != m_netCodes.end() )
return (*result).second;
return NULL;
}
/**
* Function GetItem
* @param aNetName = net name to identify a given NETINFO_ITEM
* @return NETINFO_ITEM* - by \a aNetName, or NULL if not found
*/
NETINFO_ITEM* GetNetItem( const wxString& aNetName ) const
{
NETNAMES_MAP::const_iterator result = m_netNames.find( aNetName );
if( result != m_netNames.end() )
return (*result).second;
return NULL;
}
/**
* Function GetNetCount
* @return the number of nets ( always >= 1 )
* because the first net is the "not connected" net and always exists
*/
unsigned GetNetCount() const { return m_netNames.size(); }
/**
* Function AppendNet
* adds \a aNewElement to the end of the net list. Negative net code means it is going to be
* auto-assigned.
*/
void AppendNet( NETINFO_ITEM* aNewElement );
/**
* Function RemoveNet
* Removes a new from the net list.
*/
void RemoveNet( NETINFO_ITEM* aNet );
/**
* Function GetPadCount
* @return the number of pads in board
*/
unsigned GetPadCount() const { return m_PadsFullList.size(); }
/**
* Function GetPads
* returns a list of all the pads (so long as buildPadsFullList() has
* been recently called). Returned list contains non-owning pointers.
* @return std::vector<D_PAD*>& - a full list of pads
std::vector<D_PAD*>& GetPads()
{
return m_PadsFullList;
}
*/
/**
* Function GetPad
* @return the pad idx from m_PadsFullList
*/
D_PAD* GetPad( unsigned aIdx ) const
{
if( aIdx < m_PadsFullList.size() )
return m_PadsFullList[aIdx];
else
return NULL;
}
bool DeletePad( D_PAD* aPad )
{
std::vector<D_PAD*>::iterator it = m_PadsFullList.begin();
std::vector<D_PAD*>::iterator end = m_PadsFullList.end();
for( ; it != end; ++it )
{
if( *it == aPad )
{
m_PadsFullList.erase( it );
return true;
}
}
return false;
}
///> Constant that holds the "unconnected net" number (typically 0)
///> all items "connected" to this net are actually not connected items
static const int UNCONNECTED;
///> Constant that forces initialization of a netinfo item to the NETINFO_ITEM ORPHANED
///> (typically -1) when calling SetNetCode od board connected items
static const int ORPHANED;
///> NETINFO_ITEM meaning that there was no net assigned for an item, as there was no
///> board storing net list available.
static NETINFO_ITEM ORPHANED_ITEM;
#if defined(DEBUG)
void Show() const;
#endif
typedef boost::unordered_map<const wxString, NETINFO_ITEM*, WXSTRING_HASH> NETNAMES_MAP;
typedef boost::unordered_map<const int, NETINFO_ITEM*> NETCODES_MAP;
#ifndef SWIG
///> Wrapper class, so you can iterate through NETINFO_ITEM*s, not
///> std::pair<int/wxString, NETINFO_ITEM*>
class iterator
{
public:
iterator( NETNAMES_MAP::const_iterator aIter ) : m_iterator( aIter )
{
}
/// pre-increment operator
const iterator& operator++()
{
++m_iterator;
return *this;
}
/// post-increment operator
iterator operator++( int )
{
iterator ret = *this;
++m_iterator;
return ret;
}
NETINFO_ITEM* operator*() const
{
return m_iterator->second;
}
NETINFO_ITEM* operator->() const
{
return m_iterator->second;
}
bool operator!=( const iterator& aOther ) const
{
return m_iterator != aOther.m_iterator;
}
bool operator==( const iterator& aOther ) const
{
return m_iterator == aOther.m_iterator;
}
private:
NETNAMES_MAP::const_iterator m_iterator;
};
iterator begin() const
{
return iterator( m_netNames.begin() );
}
iterator end() const
{
return iterator( m_netNames.end() );
}
#endif
BOARD* GetParent() const
{
return m_Parent;
}
private:
/**
* Function clear
* deletes the list of nets (and free memory)
*/
void clear();
/**
* Function buildListOfNets
* builds or rebuilds the list of NETINFO_ITEMs
* The list is sorted by names.
*/
void buildListOfNets();
/**
* Function buildPadsFullList
* creates the pad list, and initializes:
* m_Pads (list of pads)
* set m_Status_Pcb = LISTE_PAD_OK;
* and clear for all pads in list the m_SubRatsnest member;
* clear m_Pcb->m_FullRatsnest
*/
void buildPadsFullList();
/**
* Function getFreeNetCode
* returns the first available net code that is not used by any other net.
*/
int getFreeNetCode();
BOARD* m_Parent;
NETNAMES_MAP m_netNames; ///< map for a fast look up by net names
NETCODES_MAP m_netCodes; ///< map for a fast look up by net codes
std::vector<D_PAD*> m_PadsFullList; ///< contains all pads, sorted by pad's netname.
///< can be used in ratsnest calculations.
int m_newNetCode; ///< possible value for new net code assignment
};
DECL_VEC_FOR_SWIG( D_PADS, D_PAD* )
/**
* Class NETINFO_ITEM
@ -496,10 +138,11 @@ private:
// item of the net classes list
NETCLASSPTR m_NetClass;
BOARD* m_parent; ///< The parent board the net belongs to.
BOARD* m_parent; ///< The parent board the net belongs to.
public:
std::vector<D_PAD*> m_PadInNetList; ///< List of pads connected to this net
D_PADS m_PadInNetList; ///< List of pads connected to this net
unsigned m_RatsnestStartIdx; /* Starting point of ratsnests of this
* net (included) in a general buffer of
@ -705,7 +348,340 @@ public:
{
return m_parent;
}
};
#ifndef SWIG
class NETINFO_MAPPING
{
public:
NETINFO_MAPPING()
{
m_board = NULL;
}
/**
* Function SetBoard
* Sets a BOARD object that is used to prepare the net code map.
*/
void SetBoard( const BOARD* aBoard )
{
m_board = aBoard;
Update();
}
/**
* Function Update
* Prepares a mapping for net codes so they can be saved as consecutive numbers.
* To retrieve a mapped net code, use translateNet() function after calling this.
*/
void Update();
/**
* Function Translate
* Translates net number according to the map prepared by Update() function. It
* allows to have items stored with consecutive net codes.
* @param aNetCode is an old net code.
* @return Net code that follows the mapping.
*/
int Translate( int aNetCode ) const;
#ifndef SWIG
///> Wrapper class, so you can iterate through NETINFO_ITEM*s, not
///> std::pair<int/wxString, NETINFO_ITEM*>
class iterator
{
public:
iterator( std::map<int, int>::const_iterator aIter, const NETINFO_MAPPING* aMapping ) :
m_iterator( aIter ), m_mapping( aMapping )
{
}
/// pre-increment operator
const iterator& operator++()
{
++m_iterator;
return *this;
}
/// post-increment operator
iterator operator++( int )
{
iterator ret = *this;
++m_iterator;
return ret;
}
NETINFO_ITEM* operator*() const;
NETINFO_ITEM* operator->() const;
bool operator!=( const iterator& aOther ) const
{
return m_iterator != aOther.m_iterator;
}
bool operator==( const iterator& aOther ) const
{
return m_iterator == aOther.m_iterator;
}
private:
std::map<int, int>::const_iterator m_iterator;
const NETINFO_MAPPING* m_mapping;
};
/**
* Function begin()
* Returns iterator to the first entry in the mapping.
* NOTE: The entry is a pointer to the original NETINFO_ITEM object, this it contains
* not mapped net code.
*/
iterator begin() const
{
return iterator( m_netMapping.begin(), this );
}
/**
* Function end()
* Returns iterator to the last entry in the mapping.
* NOTE: The entry is a pointer to the original NETINFO_ITEM object, this it contains
* not mapped net code.
*/
iterator end() const
{
return iterator( m_netMapping.end(), this );
}
#endif
/**
* Function GetSize
* @return Number of mapped nets (i.e. not empty nets for a given BOARD object).
*/
int GetSize() const
{
return m_netMapping.size();
}
private:
///> Board for which mapping is prepared
const BOARD* m_board;
///> Map that allows saving net codes with consecutive numbers (for compatibility reasons)
std::map<int, int> m_netMapping;
};
#endif // SWIG
#if 0
// waiting for swig to support std::unordered_map, see
// http://www.swig.org/Doc3.0/CPlusPlus11.html
// section 7.3.3
#include <hashtables.h>
DECL_HASH_FOR_SWIG( NETNAMES_MAP, wxString, NETINFO_ITEM* )
DECL_HASH_FOR_SWIG( NETCODES_MAP, int, NETINFO_ITEM* )
#else
// use std::map for now
DECL_MAP_FOR_SWIG( NETNAMES_MAP, wxString, NETINFO_ITEM* )
DECL_MAP_FOR_SWIG( NETCODES_MAP, int, NETINFO_ITEM* )
#endif
/**
* Class NETINFO_LIST
* is a container class for NETINFO_ITEM elements, which are the nets. That makes
* this class a container for the nets.
*/
class NETINFO_LIST
{
friend class BOARD;
public:
NETINFO_LIST( BOARD* aParent );
~NETINFO_LIST();
/**
* Function GetItem
* @param aNetCode = netcode to identify a given NETINFO_ITEM
* @return NETINFO_ITEM* - by \a aNetCode, or NULL if not found
*/
NETINFO_ITEM* GetNetItem( int aNetCode ) const;
/**
* Function GetItem
* @param aNetName = net name to identify a given NETINFO_ITEM
* @return NETINFO_ITEM* - by \a aNetName, or NULL if not found
*/
NETINFO_ITEM* GetNetItem( const wxString& aNetName ) const;
/**
* Function GetNetCount
* @return the number of nets ( always >= 1 )
* because the first net is the "not connected" net and always exists
*/
unsigned GetNetCount() const { return m_netNames.size(); }
/**
* Function AppendNet
* adds \a aNewElement to the end of the net list. Negative net code means it is going to be
* auto-assigned.
*/
void AppendNet( NETINFO_ITEM* aNewElement );
/**
* Function RemoveNet
* Removes a new from the net list.
*/
void RemoveNet( NETINFO_ITEM* aNet );
/**
* Function GetPadCount
* @return the number of pads in board
*/
unsigned GetPadCount() const { return m_PadsFullList.size(); }
/**
* Function GetPads
* returns a list of all the pads (so long as buildPadsFullList() has
* been recently called). Returned list contains non-owning pointers.
* @return D_PADS& - a full list of pads
*/
const D_PADS& GetPads() const { return m_PadsFullList; }
/// Return the name map, at least for python.
const NETNAMES_MAP& GetNets() const { return m_netNames; }
/**
* Function GetPad
* @return D_PAD* - the pad from m_PadsFullList or nullptr if bad @a aIdx
*/
D_PAD* GetPad( unsigned aIdx ) const;
bool DeletePad( D_PAD* aPad );
///> Constant that holds the "unconnected net" number (typically 0)
///> all items "connected" to this net are actually not connected items
static const int UNCONNECTED;
///> Constant that forces initialization of a netinfo item to the NETINFO_ITEM ORPHANED
///> (typically -1) when calling SetNetCode od board connected items
static const int ORPHANED;
///> NETINFO_ITEM meaning that there was no net assigned for an item, as there was no
///> board storing net list available.
static NETINFO_ITEM ORPHANED_ITEM;
#if defined(DEBUG)
void Show() const;
#endif
#ifndef SWIG
///> Wrapper class, so you can iterate through NETINFO_ITEM*s, not
///> std::pair<int/wxString, NETINFO_ITEM*>
class iterator
{
public:
iterator( NETNAMES_MAP::const_iterator aIter ) : m_iterator( aIter )
{
}
/// pre-increment operator
const iterator& operator++()
{
++m_iterator;
return *this;
}
/// post-increment operator
iterator operator++( int )
{
iterator ret = *this;
++m_iterator;
return ret;
}
NETINFO_ITEM* operator*() const
{
return m_iterator->second;
}
NETINFO_ITEM* operator->() const
{
return m_iterator->second;
}
bool operator!=( const iterator& aOther ) const
{
return m_iterator != aOther.m_iterator;
}
bool operator==( const iterator& aOther ) const
{
return m_iterator == aOther.m_iterator;
}
private:
NETNAMES_MAP::const_iterator m_iterator;
};
iterator begin() const
{
return iterator( m_netNames.begin() );
}
iterator end() const
{
return iterator( m_netNames.end() );
}
#endif
BOARD* GetParent() const
{
return m_Parent;
}
private:
/**
* Function clear
* deletes the list of nets (and free memory)
*/
void clear();
/**
* Function buildListOfNets
* builds or rebuilds the list of NETINFO_ITEMs
* The list is sorted by names.
*/
void buildListOfNets();
/**
* Function buildPadsFullList
* creates the pad list, and initializes:
* m_Pads (list of pads)
* set m_Status_Pcb = LISTE_PAD_OK;
* and clear for all pads in list the m_SubRatsnest member;
* clear m_Pcb->m_FullRatsnest
*/
void buildPadsFullList();
/**
* Function getFreeNetCode
* returns the first available net code that is not used by any other net.
*/
int getFreeNetCode();
BOARD* m_Parent;
NETNAMES_MAP m_netNames; ///< map of <wxString, NETINFO_ITEM*>, is NETINFO_ITEM owner
NETCODES_MAP m_netCodes; ///< map of <int, NETINFO_ITEM*> is NOT owner
D_PADS m_PadsFullList; ///< contains all pads, sorted by pad's netname.
///< can be used in ratsnest calculations.
int m_newNetCode; ///< possible value for new net code assignment
};
@ -731,4 +707,4 @@ enum StatusPcbFlags {
};
#endif // __CLASSES_NETINFO__
#endif // CLASS_NETINFO_

View File

@ -69,6 +69,28 @@ void NETINFO_LIST::clear()
}
NETINFO_ITEM* NETINFO_LIST::GetNetItem( int aNetCode ) const
{
NETCODES_MAP::const_iterator result = m_netCodes.find( aNetCode );
if( result != m_netCodes.end() )
return (*result).second;
return NULL;
}
NETINFO_ITEM* NETINFO_LIST::GetNetItem( const wxString& aNetName ) const
{
NETNAMES_MAP::const_iterator result = m_netNames.find( aNetName );
if( result != m_netNames.end() )
return (*result).second;
return NULL;
}
void NETINFO_LIST::RemoveNet( NETINFO_ITEM* aNet )
{
for( NETCODES_MAP::iterator i = m_netCodes.begin(); i != m_netCodes.end(); ++i )
@ -121,6 +143,32 @@ void NETINFO_LIST::AppendNet( NETINFO_ITEM* aNewElement )
}
D_PAD* NETINFO_LIST::GetPad( unsigned aIdx ) const
{
if( aIdx < m_PadsFullList.size() )
return m_PadsFullList[aIdx];
else
return NULL;
}
bool NETINFO_LIST::DeletePad( D_PAD* aPad )
{
std::vector<D_PAD*>::iterator it = m_PadsFullList.begin();
std::vector<D_PAD*>::iterator end = m_PadsFullList.end();
for( ; it != end; ++it )
{
if( *it == aPad )
{
m_PadsFullList.erase( it );
return true;
}
}
return false;
}
/* sort function, to sort pad list by netnames
* this is a case sensitive sort.
* DO NOT change it because NETINFO_ITEM* BOARD::FindNet( const wxString& aNetname )

View File

@ -581,6 +581,7 @@ private: // Private variable members:
// Actually computed and cached on demand by the accessor
mutable int m_boundingRadius; ///< radius of the circle containing the pad shape
#ifndef SWIG
/// Pad name (4 char) or a long identifier (used in pad name
/// comparisons because this is faster than string comparison)
union
@ -589,6 +590,7 @@ private: // Private variable members:
char m_Padname[PADNAMEZ]; // zero padded at end to full size
wxUint32 m_NumPadName; // same number of bytes as m_Padname[]
};
#endif
wxPoint m_Pos; ///< pad Position on board

View File

@ -445,6 +445,7 @@ public:
};
#ifndef SWIG
/**
* Class RELEASER
* releases a PLUGIN in the context of a potential thrown exception, through
@ -495,6 +496,7 @@ public:
return plugin;
}
};
#endif
};
#endif // IO_MGR_H_

View File

@ -70,7 +70,8 @@
// std::vector templates
%template(VIA_DIMENSION_Vector) std::vector<VIA_DIMENSION>;
%template (RATSNEST_Vector) std::vector<RATSNEST_ITEM>;
%template(RATSNEST_Vector) std::vector<RATSNEST_ITEM>;
%extend BOARD
{
@ -115,3 +116,16 @@
self.SetEnd0(end)
}
}
%feature("notabstract") NETINFO_ITEM;
// http://swig.10945.n7.nabble.com/std-containers-and-pointers-td3728.html
%{
namespace swig {
template <> struct traits<NETINFO_ITEM> {
typedef pointer_category category;
static const char* type_name() { return "NETINFO_ITEM"; }
};
}
%}

View File

@ -35,17 +35,22 @@
%include "docstrings.i"
#endif
%include "kicad.i"
// ignore a couple of items that generate warnings from swig built code
%include <convert_to_biu.h>
%include <fpid.h>
%ignore NETINFO_ITEM;
// ignore a couple of items that generate warnings from swig built code
%ignore BOARD_ITEM::ZeroOffset;
%ignore D_PAD::m_PadSketchModePenSize;
class BASE_SET {};
%ignore BASE_SET;
// rename the Add method of classes to Add native, so we will handle
// the Add method in python
%rename(AddNative) *::Add;
// fix method names conflicts
@ -85,16 +90,14 @@
#include <wx_python_helpers.h>
#include <class_board_item.h>
#include <class_board_connected_item.h>
#include <class_netinfo.h>
#include <class_board_design_settings.h>
#include <class_board.h>
#include <class_module.h>
#include <class_track.h>
#include <class_zone.h>
#include <zones.h>
#include <layers_id_colors_and_visibility.h>
#include <class_pad.h>
#include <pad_shapes.h>
#include <class_netinfo.h>
#include <class_pcb_text.h>
#include <class_dimension.h>
#include <class_drawsegment.h>
@ -102,16 +105,19 @@
#include <class_mire.h>
#include <class_text_mod.h>
#include <class_edge_mod.h>
#include <dlist.h>
#include <class_zone_settings.h>
#include <class_netclass.h>
#include <class_netinfo.h>
#include <colors.h>
//#include <dlist.h>
#include <class_zone_settings.h>
#include <pcbnew_scripting_helpers.h>
#include <plotcontroller.h>
#include <pcb_plot_params.h>
#include <exporters/gendrill_Excellon_writer.h>
#include <colors.h>
#include <class_board.h>
BOARD *GetBoard(); /* get current editor board */
%}
@ -124,16 +130,14 @@
%include <class_board_item.h>
%include <class_board_connected_item.h>
%include <class_board_design_settings.h>
%include <class_board.h>
%include <pad_shapes.h>
%include <class_pad.h>
%include <class_netinfo.h>
%include <class_module.h>
%include <class_track.h>
%include <class_zone.h>
%include <zones.h>
%include <layers_id_colors_and_visibility.h>
%include <class_pad.h>
%include <pad_shapes.h>
%include <class_netinfo.h>
%include <class_pcb_text.h>
%include <class_dimension.h>
%include <class_drawsegment.h>
@ -144,14 +148,16 @@
%include <dlist.h>
%include <class_zone_settings.h>
%include <class_netclass.h>
%include <class_netinfo.h>
%include <class_board_design_settings.h>
%include <plotcontroller.h>
%include <pcb_plot_params.h>
%include <plot_common.h>
%include <exporters/gendrill_Excellon_writer.h>
%include <colors.h>
%include <class_board.h>
%include "board_item.i"
%include <pcbnew_scripting_helpers.h>
@ -167,6 +173,8 @@
%include "plugins.i"
%include "units.i"
// Extend LSET by 2 methods to add or remove layers from the layer list
// Mainly used to add or remove layers of a pad layer list
%extend LSET

View File

@ -104,6 +104,8 @@ public:
{ return (x != cpt2.x) || (y != cpt2.y) || (end_contour != cpt2.end_contour); }
};
#ifndef SWIG
/**
* CPOLYGONS_LIST handle a list of contours (polygons corners).
* Each corner is a CPolyPt item.
@ -205,6 +207,8 @@ public:
*/
int GetContoursCount() const;
};
#endif
class CPolyLine
{

View File

@ -31,21 +31,37 @@
%include <std_basic_string.i>
%include <std_string.i>
%include <std_map.i>
%include <std_shared_ptr.i>
/* ignore some constructors of EDA_ITEM that will make the build fail */
/*
http://www.swig.org/Doc3.0/CPlusPlus11.html
7.3.3 Hash tables
%nodefaultctor EDA_ITEM;
The new hash tables in the STL are unordered_set, unordered_multiset,
unordered_map, unordered_multimap. These are not available in SWIG, but in
principle should be easily implemented by adapting the current STL containers.
%include <std_unordered_map.i>
*/
// ignore some constructors of EDA_ITEM that will make the build fail
%nodefaultctor EDA_ITEM;
%ignore EDA_ITEM::EDA_ITEM( EDA_ITEM* parent, KICAD_T idType );
%ignore EDA_ITEM::EDA_ITEM( KICAD_T idType );
%ignore EDA_ITEM::EDA_ITEM( const EDA_ITEM& base );
%warnfilter(401) EDA_ITEM;
%warnfilter(509) UTF8;
/* swig tries to wrap SetBack/SetNext on derived classes, but this method is
private for most childs, so if we don't ignore it won't compile */
%ignore EDA_ITEM::SetBack;
%ignore EDA_ITEM::SetNext;
/* ignore other functions that cause trouble */
// ignore other functions that cause trouble
%ignore InitKiCadAbout;
%ignore GetCommandOptions;
@ -55,9 +71,10 @@
%ignore operator=;
/* headers/imports that must be included in the _wrapper.cpp at top */
// headers/imports that must be included in the _wrapper.cpp at top
%{
#include <macros.h>
#include <cstddef>
#include <dlist.h>
#include <base_struct.h>
@ -75,27 +92,13 @@
#include <convert_to_biu.h>
%}
/* all the wx wrappers for wxString, wxPoint, wxRect, wxChar .. */
// all the wx wrappers for wxString, wxPoint, wxRect, wxChar ..
%include <wx.i>
/* exception handling */
/* the IO_ERROR exception handler, not working yet... */
/*
%exception
{
try {
$function
}
catch (IO_ERROR e) {
PyErr_SetString(PyExc_IOError,"IO error");
return NULL;
}
}
*/
/* header files that must be wrapped */
// header files that must be wrapped
%include <macros.h>
%include <core/typeinfo.h>
%include <dlist.h>
%include <base_struct.h>
%include <class_eda_rect.h>
@ -104,13 +107,11 @@
%include <class_colors_design_settings.h>
%include <class_marker_base.h>
%include <eda_text.h>
%include <convert_to_biu.h>
%include <fpid.h>
/* special iteration wrapper for DLIST objects */
// special iteration wrapper for DLIST objects
%include "dlist.i"
/* std template mappings */
// std template mappings
%template(intVector) std::vector<int>;
%template(str_utf8_Map) std::map< std::string,UTF8 >;
@ -120,7 +121,7 @@
// TODO: wrapper of BASE_SET (see std::bitset<LAYER_ID_COUNT> BASE_SET;)
/* KiCad plugin handling */
// KiCad plugin handling
%include "kicadplugins.i"
// map CPolyLine and classes used in CPolyLine:

View File

@ -166,8 +166,9 @@ public:
wxPoint __sub__(const wxPoint& pt) { return *self - pt; }
void Set(long x, long y) { self->x = x; self->y = y; }
PyObject* Get()
{
{
PyObject* tup = PyTuple_New(2);
PyTuple_SET_ITEM(tup, 0, PyInt_FromLong(self->x));
PyTuple_SET_ITEM(tup, 1, PyInt_FromLong(self->y));
@ -199,21 +200,78 @@ public:
/* they handle the conversion from/to strings */
%typemap(in) wxChar { wxString str = Py2wxString($input); $1 = str[0]; }
%typemap(in) wxChar { wxString str = Py2wxString($input); $1 = str[0]; }
%typemap(out) wxChar { wxString str($1); $result = wx2PyString(str); }
// wxString wrappers /////////////////////////////////////////////////////////
%typemap(out) wxString&
// wxString /////////////////////////////////////////////////////////
/*
The wxString typemaps below are sufficient to handle two cases but not
a third.
1) Arguments into wrapped C++ functions taking wxString as parameters can be
passed as python strings, not wxString. In fact you cannot create a wxString
from python, only in C++.
2) Wrapped C++ functions returning wxString will have that wxString
converted to a python unicode or string automatically.
Both of these features are a result of the wxString typemaps below. Note
that this philosophy is very agreeable, and is consistent with the
philosophy adopted by wxPython. In fact one might wish that KiCad did not
use wxString in any of its data structures, and merely used UTF8s, which
will convert automatically to and from wxString when needed.
There is another case that typemaps to not address, and no, this is not the
construction of wxString from python, but rather the examination of wxString
in situ, i.e. in a data structure within the BOARD. It does not match either
case above. So the class wxString {} spec block below is in here to allow
examination of a wxString's value when operating python interactively or
when printing a value in situ that was not returned from a wrapped function.
Remember wxString return values of functions are converted by the typemaps.
No wxString constructor is given to SWIG, since wxString contruction is
always done in C++, but python needs to know that it can delete a wxString
when necessary. And most importantly we need to see a string's contents so
the __str__() function must show content.
*/
class wxString
{
%#if wxUSE_UNICODE
$result = PyUnicode_FromWideChar($1->c_str(), $1->Len());
%#else
$result = PyString_FromStringAndSize($1->c_str(), $1->Len());
%#endif
public:
// this is not C++ source, it is SWIG interface spec
virtual ~wxString();
%extend
{
PyObject* __str__()
{
%#if wxUSE_UNICODE
return PyUnicode_FromWideChar( $self->c_str(), $self->Len() );
%#else
return PyString_FromStringAndSize( $self->c_str(), $self->Len() );
%#endif
}
}
%pythoncode
{
def __repr__(self): return 'wxString(\'' + self.__str__() + '\')'
}
};
// wxString typemaps
%typemap(in) wxString {
wxString* sptr = newWxStringFromPy($input);
if (sptr == NULL) SWIG_fail;
$1 = *sptr;
delete sptr;
}
%apply wxString& { wxString* }
%typemap(out) wxString
{
@ -224,6 +282,7 @@ public:
%#endif
}
%typemap(varout) wxString
{
%#if wxUSE_UNICODE
@ -233,6 +292,7 @@ public:
%#endif
}
%typemap(in) wxString& (bool temp=false)
{
$1 = newWxStringFromPy($input);
@ -240,26 +300,30 @@ public:
temp = true;
}
%typemap(out) wxString&
{
%#if wxUSE_UNICODE
$result = PyUnicode_FromWideChar($1->c_str(), $1->Len());
%#else
$result = PyString_FromStringAndSize($1->c_str(), $1->Len());
%#endif
}
%typemap(freearg) wxString&
{
if (temp$argnum)
delete $1;
}
%typemap(in) wxString {
wxString* sptr = newWxStringFromPy($input);
if (sptr == NULL) SWIG_fail;
$1 = *sptr;
delete sptr;
}
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER) wxString& {
$1 = PyString_Check($input) || PyUnicode_Check($input);
}
%apply wxString& { wxString* }
// wxArrayString wrappers //////////////////////////////////////////////////////
// wxArrayString //////////////////////////////////////////////////////
%typemap(in) wxArrayString& (bool temp=false) {
if (!PySequence_Check($input))
{