From e24990146d5d4fb315bc674416cc81bf462ced6f Mon Sep 17 00:00:00 2001 From: Dick Hollenbeck <dick@softplc.com> Date: Mon, 18 Jul 2016 13:23:09 -0400 Subject: [PATCH] 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. --- include/base_struct.h | 16 +- include/class_collector.h | 5 +- include/core/typeinfo.h | 101 ++--- include/hashtables.h | 82 ++-- include/macros.h | 18 +- include/utf8.h | 2 + pcbnew/class_board.cpp | 10 +- pcbnew/class_board.h | 25 +- pcbnew/class_netclass.cpp | 4 +- pcbnew/class_netclass.h | 15 +- pcbnew/class_netinfo.h | 708 +++++++++++++++++------------------ pcbnew/class_netinfolist.cpp | 48 +++ pcbnew/class_pad.h | 2 + pcbnew/io_mgr.h | 2 + pcbnew/scripting/board.i | 16 +- pcbnew/scripting/pcbnew.i | 40 +- polygon/PolyLine.h | 4 + scripting/kicad.i | 55 +-- scripting/wx.i | 102 ++++- 19 files changed, 716 insertions(+), 539 deletions(-) diff --git a/include/base_struct.h b/include/base_struct.h index 0143567389..3d11391de9 100644 --- a/include/base_struct.h +++ b/include/base_struct.h @@ -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; */ diff --git a/include/class_collector.h b/include/class_collector.h index 173ca7d24b..fd817a445a 100644 --- a/include/class_collector.h +++ b/include/class_collector.h @@ -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; diff --git a/include/core/typeinfo.h b/include/core/typeinfo.h index b6f1ce626c..1c4c4e597f 100644 --- a/include/core/typeinfo.h +++ b/include/core/typeinfo.h @@ -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 diff --git a/include/hashtables.h b/include/hashtables.h index 7a625bce23..99108c637c 100644 --- a/include/hashtables.h +++ b/include/hashtables.h @@ -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_ diff --git a/include/macros.h b/include/macros.h index 95bcb04466..c93863d960 100644 --- a/include/macros.h +++ b/include/macros.h @@ -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 diff --git a/include/utf8.h b/include/utf8.h index 41137d83f9..f654f862d3 100644 --- a/include/utf8.h +++ b/include/utf8.h @@ -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_ diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp index 94157be4ab..3fcf32bb2c 100644 --- a/pcbnew/class_board.cpp +++ b/pcbnew/class_board.cpp @@ -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 ); diff --git a/pcbnew/class_board.h b/pcbnew/class_board.h index 4e4c97c688..452daf6516 100644 --- a/pcbnew/class_board.h +++ b/pcbnew/class_board.h @@ -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() { diff --git a/pcbnew/class_netclass.cpp b/pcbnew/class_netclass.cpp index 46bc606f3b..858175b16c 100644 --- a/pcbnew/class_netclass.cpp +++ b/pcbnew/class_netclass.cpp @@ -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(); diff --git a/pcbnew/class_netclass.h b/pcbnew/class_netclass.h index 658f182f8b..3a4c206601 100644 --- a/pcbnew/class_netclass.h +++ b/pcbnew/class_netclass.h @@ -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(); } diff --git a/pcbnew/class_netinfo.h b/pcbnew/class_netinfo.h index b4d76a0cb4..e179fb694a 100644 --- a/pcbnew/class_netinfo.h +++ b/pcbnew/class_netinfo.h @@ -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_ diff --git a/pcbnew/class_netinfolist.cpp b/pcbnew/class_netinfolist.cpp index 7574aaa286..dbfe2d82c4 100644 --- a/pcbnew/class_netinfolist.cpp +++ b/pcbnew/class_netinfolist.cpp @@ -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 ) diff --git a/pcbnew/class_pad.h b/pcbnew/class_pad.h index 03e59483fc..12223ab040 100644 --- a/pcbnew/class_pad.h +++ b/pcbnew/class_pad.h @@ -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 diff --git a/pcbnew/io_mgr.h b/pcbnew/io_mgr.h index 24d548a08a..87e217a045 100644 --- a/pcbnew/io_mgr.h +++ b/pcbnew/io_mgr.h @@ -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_ diff --git a/pcbnew/scripting/board.i b/pcbnew/scripting/board.i index da0e10aa01..8073257d07 100644 --- a/pcbnew/scripting/board.i +++ b/pcbnew/scripting/board.i @@ -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"; } + }; + } +%} diff --git a/pcbnew/scripting/pcbnew.i b/pcbnew/scripting/pcbnew.i index 1e69396483..782de685b0 100644 --- a/pcbnew/scripting/pcbnew.i +++ b/pcbnew/scripting/pcbnew.i @@ -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 diff --git a/polygon/PolyLine.h b/polygon/PolyLine.h index b60cd37ca6..d6a1f89295 100644 --- a/polygon/PolyLine.h +++ b/polygon/PolyLine.h @@ -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 { diff --git a/scripting/kicad.i b/scripting/kicad.i index 6316a6dcae..58194a2550 100644 --- a/scripting/kicad.i +++ b/scripting/kicad.i @@ -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: diff --git a/scripting/wx.i b/scripting/wx.i index aa03a3f432..dddd68391b 100644 --- a/scripting/wx.i +++ b/scripting/wx.i @@ -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)) {