From 7311f07eafc6128483367b39bf0bb1e4650e377f Mon Sep 17 00:00:00 2001 From: Dick Hollenbeck Date: Tue, 20 Sep 2016 11:59:43 -0400 Subject: [PATCH] SWIG Improvements *) Extend SWIG support deeper into the BOARD class. *) Move swig *.i files into a directory identified for SWIG, in preparation for a parallel universe involving Phoenix's SIP. *) Move swig files which will be common to both eeschema and pcbnew into common/swig. *) Sketch out a "common" python module, and plan on dovetailing that into a libkicad_shared.{dll,so} *) Add common/swig/ki_exceptions.i and define a macro HANDLE_EXCEPTIONS() which is to be applied to any function which needs C++ to python exception translation. *) Move the test for SWIG tool into top level CMakeLists.txt file for use in all python modules beyond pcbnew, i.e. eeschema and common. *) Add SWIG_MODULE_pcbnew_EXTRA_DEPS which generates a better Makefile, one which rebuilds the swig generated *.cxx file when one of its dependencies change. *) Re-architect the board.i file so that it can be split into multiple *.i files easily. *) Make some KIWAY from python progress, in preparation for Modular KiCad phase III. --- CMakeLists.txt | 5 + CMakeModules/config.h.cmake | 4 +- common/CMakeLists.txt | 62 +++++ common/footprint_info.cpp | 2 +- common/kiway.cpp | 32 ++- common/pgm_base.cpp | 20 +- {scripting => common/swig}/dlist.i | 7 + common/swig/ki_exception.i | 65 +++++ common/swig/kicad.i | 158 ++++++++++++ scripting/kicad.i => common/swig/kicad.i.orig | 1 + common/swig/kiway.i | 234 ++++++++++++++++++ common/swig/kiway_player.i | 20 ++ {scripting => common/swig}/wx.i | 0 .../swig}/wx_python_helpers.cpp | 0 .../swig}/wx_python_helpers.h | 6 +- include/kiway.h | 45 ++-- include/kiway_player.h | 8 +- include/layers_id_colors_and_visibility.h | 2 +- include/macros.h | 5 +- include/pgm_base.h | 66 ++--- kicad/pgm_kicad.h | 17 +- pcbnew/CMakeLists.txt | 78 +++--- pcbnew/class_board.cpp | 44 ++-- pcbnew/class_board.h | 10 +- pcbnew/class_netclass.cpp | 2 +- pcbnew/class_netclass.h | 19 +- pcbnew/pcb_parser.cpp | 3 +- .../examples/createFPC40.py | 0 .../examples/createPcb.py | 0 .../examples/hidePcbValuesShowReferences.py | 0 .../{scripting => python}/examples/listPcb.py | 0 .../examples/listPcbLibrary.py | 0 .../kicad_pyshell/__init__.py | 0 .../plugins/FPC_(SMD_type)_footprintwizard.py | 0 .../plugins/FootprintWizardDrawingAids.py | 0 .../plugins/HelpfulFootprintWizardPlugin.py | 0 .../{scripting => python}/plugins/PadArray.py | 0 .../{scripting => python}/plugins/__init__.py | 0 .../plugins/bga_wizard.py | 0 .../plugins/circular_pad_array_wizard.py | 0 .../plugins/qfn_wizard.py | 0 .../plugins/qfp_wizard.py | 0 .../plugins/sdip_wizard.py | 0 .../plugins/touch_slider_wizard.py | 0 .../plugins/uss39_barcode.py | 0 .../plugins/zip_wizard.py | 0 pcbnew/{scripting => swig}/TODO.txt | 0 pcbnew/{scripting => swig}/board.i | 189 ++++++++++++-- pcbnew/swig/board.i.orig | 0 pcbnew/swig/board.i.rej | 147 +++++++++++ pcbnew/{scripting => swig}/board_item.i | 0 pcbnew/{scripting => swig}/module.i | 0 pcbnew/{scripting => swig}/pcbnew.i | 94 ++----- pcbnew/swig/pcbnew.i.orig | 0 pcbnew/swig/pcbnew.i.rej | 29 +++ .../pcbnew_footprint_wizards.cpp | 0 .../pcbnew_footprint_wizards.h | 0 .../pcbnew_scripting_helpers.cpp | 0 .../pcbnew_scripting_helpers.h | 0 pcbnew/{scripting => swig}/plugins.i | 6 +- .../swig}/python_scripting.cpp | 0 {scripting => pcbnew/swig}/python_scripting.h | 0 pcbnew/{scripting => swig}/tests/test1.py | 0 pcbnew/{scripting => swig}/tests/test2.py | 0 pcbnew/{scripting => swig}/units.i | 57 +++-- plugins/3d/vrml/CMakeLists.txt | 1 + 66 files changed, 1136 insertions(+), 302 deletions(-) rename {scripting => common/swig}/dlist.i (98%) create mode 100644 common/swig/ki_exception.i create mode 100644 common/swig/kicad.i rename scripting/kicad.i => common/swig/kicad.i.orig (99%) create mode 100644 common/swig/kiway.i create mode 100644 common/swig/kiway_player.i rename {scripting => common/swig}/wx.i (100%) rename {scripting => common/swig}/wx_python_helpers.cpp (100%) rename {scripting => common/swig}/wx_python_helpers.h (85%) rename pcbnew/{scripting => python}/examples/createFPC40.py (100%) mode change 100755 => 100644 rename pcbnew/{scripting => python}/examples/createPcb.py (100%) mode change 100755 => 100644 rename pcbnew/{scripting => python}/examples/hidePcbValuesShowReferences.py (100%) rename pcbnew/{scripting => python}/examples/listPcb.py (100%) mode change 100755 => 100644 rename pcbnew/{scripting => python}/examples/listPcbLibrary.py (100%) mode change 100755 => 100644 rename pcbnew/{scripting => python}/kicad_pyshell/__init__.py (100%) rename pcbnew/{scripting => python}/plugins/FPC_(SMD_type)_footprintwizard.py (100%) rename pcbnew/{scripting => python}/plugins/FootprintWizardDrawingAids.py (100%) rename pcbnew/{scripting => python}/plugins/HelpfulFootprintWizardPlugin.py (100%) rename pcbnew/{scripting => python}/plugins/PadArray.py (100%) rename pcbnew/{scripting => python}/plugins/__init__.py (100%) rename pcbnew/{scripting => python}/plugins/bga_wizard.py (100%) rename pcbnew/{scripting => python}/plugins/circular_pad_array_wizard.py (100%) rename pcbnew/{scripting => python}/plugins/qfn_wizard.py (100%) rename pcbnew/{scripting => python}/plugins/qfp_wizard.py (100%) rename pcbnew/{scripting => python}/plugins/sdip_wizard.py (100%) rename pcbnew/{scripting => python}/plugins/touch_slider_wizard.py (100%) rename pcbnew/{scripting => python}/plugins/uss39_barcode.py (100%) rename pcbnew/{scripting => python}/plugins/zip_wizard.py (100%) rename pcbnew/{scripting => swig}/TODO.txt (100%) rename pcbnew/{scripting => swig}/board.i (54%) create mode 100644 pcbnew/swig/board.i.orig create mode 100644 pcbnew/swig/board.i.rej rename pcbnew/{scripting => swig}/board_item.i (100%) rename pcbnew/{scripting => swig}/module.i (100%) rename pcbnew/{scripting => swig}/pcbnew.i (62%) create mode 100644 pcbnew/swig/pcbnew.i.orig create mode 100644 pcbnew/swig/pcbnew.i.rej rename pcbnew/{scripting => swig}/pcbnew_footprint_wizards.cpp (100%) rename pcbnew/{scripting => swig}/pcbnew_footprint_wizards.h (100%) rename pcbnew/{scripting => swig}/pcbnew_scripting_helpers.cpp (100%) rename pcbnew/{scripting => swig}/pcbnew_scripting_helpers.h (100%) rename pcbnew/{scripting => swig}/plugins.i (88%) rename {scripting => pcbnew/swig}/python_scripting.cpp (100%) rename {scripting => pcbnew/swig}/python_scripting.h (100%) rename pcbnew/{scripting => swig}/tests/test1.py (100%) rename pcbnew/{scripting => swig}/tests/test2.py (100%) rename pcbnew/{scripting => swig}/units.i (58%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 065995b410..5ff860bcd2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -574,6 +574,11 @@ set( INC_AFTER # Find Python and other scripting resources if( KICAD_SCRIPTING OR KICAD_SCRIPTING_MODULES ) + + # SWIG 3.0 or later require for C++11 support. + find_package( SWIG 3.0 REQUIRED ) + include( ${SWIG_USE_FILE} ) + # force a python version < 3.0 set( PythonInterp_FIND_VERSION 2.6 ) set( PythonLibs_FIND_VERSION 2.6 ) diff --git a/CMakeModules/config.h.cmake b/CMakeModules/config.h.cmake index 01359cc003..700ec2a7a8 100644 --- a/CMakeModules/config.h.cmake +++ b/CMakeModules/config.h.cmake @@ -74,8 +74,8 @@ /// A file extension with a leading '.' is a suffix, and this one is used on /// top level program modules which implement the KIFACE. -#define KIFACE_SUFFIX wxT( "@KIFACE_SUFFIX@" ) -#define KIFACE_PREFIX wxT( "@KIFACE_PREFIX@" ) +#define KIFACE_SUFFIX "@KIFACE_SUFFIX@" +#define KIFACE_PREFIX "@KIFACE_PREFIX@" /// Name of repo from which this build came. #define KICAD_REPO_NAME "@KICAD_REPO_NAME@" diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 6b6e1feb7c..4d304ae8b8 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -225,6 +225,7 @@ set( COMMON_SRCS eda_dde.cpp eda_doc.cpp eda_pattern_match.cpp + exceptions.cpp filter_reader.cpp # findkicadhelppath.cpp.notused deprecated, use searchhelpfilefullpath.cpp gbr_metadata.cpp @@ -507,3 +508,64 @@ target_link_libraries( dsntest common ${wxWidgets_LIBRARIES} rt ) add_dependencies( dsntest lib-dependencies ) target_link_libraries( pcbcommon 3d-viewer ) + + +# kiway.so +if( future AND KICAD_SCRIPTING OR KICAD_SCRIPTING_MODULES ) + #file( MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/scripting ) + + set( SWIG_FLAGS + -I${CMAKE_CURRENT_SOURCE_DIR}/../include + -I${CMAKE_CURRENT_SOURCE_DIR}/swig/wx + ) + + if( DEBUG ) + set( SWIG_FLAGS ${SWIG_FLAGS} -DDEBUG ) + endif() + + # call SWIG in C++ mode: https://cmake.org/cmake/help/v3.2/module/UseSWIG.html + set_source_files_properties( swig/kiway.i PROPERTIES CPLUSPLUS ON ) + + # collect CFLAGS , and pass them to swig later + get_directory_property( DirDefs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMPILE_DEFINITIONS ) + foreach( d ${DirDefs} ) + set( SWIG_FLAGS ${SWIG_FLAGS} -D${d} ) + endforeach() + + set( CMAKE_SWIG_FLAGS ${SWIG_FLAGS} ) + + #set( SWIG_OPTS -python -c++ -outdir ${CMAKE_CURRENT_BINARY_DIR} ${SWIG_FLAGS} ) + + include_directories( BEFORE ${INC_BEFORE} ) + include_directories( + ../common + ${INC_AFTER} + ) + + set( SWIG_MODULE_kiway_EXTRA_DEPS + ../common/swig/ki_exception.i + ../common/swig/kicad.i + ) + + swig_add_module( kiway python + swig/kiway.i + #../common/kiway.cpp + #../common/project.cpp + #../common/pgm_base.cpp + #../common/ + ) + + swig_link_libraries( kiway + common + bitmaps + ${wxWidgets_LIBRARIES} + ${PYTHON_LIBRARIES} + ) + + if( MAKE_LINK_MAPS ) + set_target_properties( _kiway PROPERTIES + LINK_FLAGS "${TO_LINKER},-cref ${TO_LINKER},-Map=_kiway.so.map" + ) + endif() + +endif() diff --git a/common/footprint_info.cpp b/common/footprint_info.cpp index dab09cf9e8..ff4fdee9f6 100644 --- a/common/footprint_info.cpp +++ b/common/footprint_info.cpp @@ -306,7 +306,7 @@ void FOOTPRINT_LIST::DisplayErrors( wxTopLevelWindow* aWindow ) for( unsigned i = 0; i" ) + m_errors[i].errorText + wxT( "

" ); + msg += wxT( "

" ) + m_errors[i].Problem() + wxT( "

" ); } dlg.AddHTML_Text( msg ); diff --git a/common/kiway.cpp b/common/kiway.cpp index fef1689389..65f8cc53c1 100644 --- a/common/kiway.cpp +++ b/common/kiway.cpp @@ -93,19 +93,19 @@ void KIWAY::SetTop( wxFrame* aTop ) } -const wxString KIWAY::dso_full_path( FACE_T aFaceId ) +const wxString KIWAY::dso_search_path( FACE_T aFaceId ) { - const wxChar* name; + const char* name; switch( aFaceId ) { - case FACE_SCH: name = KIFACE_PREFIX wxT( "eeschema" ); break; - case FACE_PCB: name = KIFACE_PREFIX wxT( "pcbnew" ); break; - case FACE_CVPCB: name = KIFACE_PREFIX wxT( "cvpcb" ); break; - case FACE_GERBVIEW: name = KIFACE_PREFIX wxT( "gerbview" ); break; - case FACE_PL_EDITOR: name = KIFACE_PREFIX wxT( "pl_editor" ); break; - case FACE_PCB_CALCULATOR: name = KIFACE_PREFIX wxT( "pcb_calculator" ); break; - case FACE_BMP2CMP: name = KIFACE_PREFIX wxT( "bitmap2component" ); break; + case FACE_SCH: name = KIFACE_PREFIX "eeschema"; break; + case FACE_PCB: name = KIFACE_PREFIX "pcbnew"; break; + case FACE_CVPCB: name = KIFACE_PREFIX "cvpcb"; break; + case FACE_GERBVIEW: name = KIFACE_PREFIX "gerbview"; break; + case FACE_PL_EDITOR: name = KIFACE_PREFIX "pl_editor"; break; + case FACE_PCB_CALCULATOR: name = KIFACE_PREFIX "pcb_calculator"; break; + case FACE_BMP2CMP: name = KIFACE_PREFIX "bitmap2component"; break; default: wxASSERT_MSG( 0, wxT( "caller has a bug, passed a bad aFaceId" ) ); @@ -113,7 +113,17 @@ const wxString KIWAY::dso_full_path( FACE_T aFaceId ) } #ifndef __WXMAC__ - wxFileName fn = wxStandardPaths::Get().GetExecutablePath(); + wxString path; + + if( m_ctl & (KFCTL_STANDALONE | KFCTL_CPP_PROJECT_SUITE) ) + { + // The 2 *.cpp program launchers: single_top.cpp and kicad.cpp expect + // the *.kiface's to reside in same diretory as their binaries do. + // Not so for python launcher, identified by KFCTL_PY_PROJECT_SUITE + path = wxStandardPaths::Get().GetExecutablePath(); + } + + wxFileName fn = path; #else // we have the dso's in main OSX bundle kicad.app/Contents/PlugIns wxFileName fn = Pgm().GetExecutablePath(); @@ -159,7 +169,7 @@ KIFACE* KIWAY::KiFACE( FACE_T aFaceId, bool doLoad ) // DSO with KIFACE has not been loaded yet, does caller want to load it? if( doLoad ) { - wxString dname = dso_full_path( aFaceId ); + wxString dname = dso_search_path( aFaceId ); wxDynamicLibrary dso; diff --git a/common/pgm_base.cpp b/common/pgm_base.cpp index 936853463f..ce26c2b7f8 100644 --- a/common/pgm_base.cpp +++ b/common/pgm_base.cpp @@ -285,7 +285,6 @@ PGM_BASE::PGM_BASE() m_locale = NULL; m_common_settings = NULL; - m_wx_app = NULL; m_show_env_var_dialog = true; setLanguageId( wxLANGUAGE_DEFAULT ); @@ -296,11 +295,11 @@ PGM_BASE::PGM_BASE() PGM_BASE::~PGM_BASE() { - destroy(); + Destroy(); } -void PGM_BASE::destroy() +void PGM_BASE::Destroy() { // unlike a normal destructor, this is designed to be called more than once safely: @@ -315,6 +314,13 @@ void PGM_BASE::destroy() } +wxApp& PGM_BASE::App() +{ + wxASSERT( wxTheApp ); + return *wxTheApp; +} + + void PGM_BASE::SetEditorName( const wxString& aFileName ) { m_editor_name = aFileName; @@ -383,7 +389,7 @@ const wxString PGM_BASE::AskUserForPreferredEditor( const wxString& aDefaultEdit } -bool PGM_BASE::initPgm() +bool PGM_BASE::InitPgm() { wxFileName pgm_name( App().argv[0] ); @@ -609,10 +615,10 @@ void PGM_BASE::loadCommonSettings() } -void PGM_BASE::saveCommonSettings() +void PGM_BASE::SaveCommonSettings() { // m_common_settings is not initialized until fairly late in the - // process startup: initPgm(), so test before using: + // process startup: InitPgm(), so test before using: if( m_common_settings ) { wxString cur_dir = wxGetCwd(); @@ -846,7 +852,7 @@ void PGM_BASE::SetLocalEnvVariables( const ENV_VAR_MAP& aEnvVarMap ) if( m_common_settings ) m_common_settings->DeleteGroup( pathEnvVariables ); - saveCommonSettings(); + SaveCommonSettings(); // Overwrites externally defined environment variable until the next time the application // is run. diff --git a/scripting/dlist.i b/common/swig/dlist.i similarity index 98% rename from scripting/dlist.i rename to common/swig/dlist.i index 9ea7712a3b..72d6f360a3 100644 --- a/scripting/dlist.i +++ b/common/swig/dlist.i @@ -24,6 +24,13 @@ /* DLIST python iteration code, to allow standard iteration over DLIST */ +%include + +%{ +#include +%} + + %extend DLIST { %pythoncode diff --git a/common/swig/ki_exception.i b/common/swig/ki_exception.i new file mode 100644 index 0000000000..0a42cc8404 --- /dev/null +++ b/common/swig/ki_exception.i @@ -0,0 +1,65 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2016 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +%warnfilter(511) IO_ERROR; + +%include ki_exception.h + +%{ +#include +%} + +%include exception.i + +// Target a specific function with "C++ to python exception handling and +// translation code". Invoke this macro separately for each C++ function +// that throws. This is a less bulkier scheme than assuming that ALL C++ +// functions throw, because they do not all throw. +%define HANDLE_EXCEPTIONS(function) +%exception function { + try + { + $action + } + catch( const IO_ERROR& e ) + { + UTF8 str = e.Problem(); + + SWIG_exception( SWIG_IOError, str.c_str() ); + return NULL; + } + catch( const std::exception& e ) + { + std::string str = e.what(); + + SWIG_exception( SWIG_IOError, str.c_str() ); + return NULL; + } + catch( ... ) + { + SWIG_fail; + } +} +%enddef + diff --git a/common/swig/kicad.i b/common/swig/kicad.i new file mode 100644 index 0000000000..6382369e01 --- /dev/null +++ b/common/swig/kicad.i @@ -0,0 +1,158 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 NBEE Embedded Systems, Miguel Angel Ajo + * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file kicad.i + * @brief General wrappers for kicad / wx structures and classes + */ + +%include +%include +%include +%include +%include +%include + +%include "ki_exception.i" // affects all that follow it + +/* +http://www.swig.org/Doc3.0/CPlusPlus11.html +7.3.3 Hash tables + +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 +*/ + +// 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 InitKiCadAbout; +%ignore GetCommandOptions; + +%rename(getWxRect) operator wxRect; +%ignore operator <<; +%ignore operator=; + +%include dlist.i + +// headers/imports that must be included in the _wrapper.cpp at top + +%{ + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #include + #include + #include + #include + #include +%} + +// all the wx wrappers for wxString, wxPoint, wxRect, wxChar .. +%include wx.i + +// header files that must be wrapped + +%include macros.h +%include core/typeinfo.h +%include base_struct.h +%include class_eda_rect.h +%include common.h +%include class_title_block.h +%include class_colors_design_settings.h +%include class_marker_base.h +%include eda_text.h + + +// std template mappings +%template(intVector) std::vector; +%template(str_utf8_Map) std::map< std::string,UTF8 >; + +// wrapper of BASE_SEQ (see typedef std::vector BASE_SEQ;) +%template(base_seqVect) std::vector; + +// TODO: wrapper of BASE_SET (see std::bitset BASE_SET;) + + +// KiCad plugin handling +%include "kicadplugins.i" + +// map CPolyLine and classes used in CPolyLine: +#include <../polygon/PolyLine.h> +%include <../polygon/PolyLine.h> + +// ignore warning relative to operator = and operator ++: +#pragma SWIG nowarn=362,383 + +// Rename operators defined in utf8.h +%rename(utf8_to_charptr) operator char* () const; +%rename(utf8_to_wxstring) operator wxString () const; + +#include +%include + +%extend UTF8 +{ + const char* Cast_to_CChar() { return (self->c_str()); } + + %pythoncode + %{ + + # Get the char buffer of the UTF8 string + def GetChars(self): + return self.Cast_to_CChar() + + # Convert the UTF8 string to a python string + # Same as GetChars(), but more easy to use in print command + def __str__(self): + return self.GetChars() + + %} +} diff --git a/scripting/kicad.i b/common/swig/kicad.i.orig similarity index 99% rename from scripting/kicad.i rename to common/swig/kicad.i.orig index 58194a2550..19fa123bf5 100644 --- a/scripting/kicad.i +++ b/common/swig/kicad.i.orig @@ -32,6 +32,7 @@ %include %include %include +%include /* http://www.swig.org/Doc3.0/CPlusPlus11.html diff --git a/common/swig/kiway.i b/common/swig/kiway.i new file mode 100644 index 0000000000..3c97a018ca --- /dev/null +++ b/common/swig/kiway.i @@ -0,0 +1,234 @@ + +//%module(directors="1") kiway +%module kiway + +/* +%import _defs.i +%import _window.i +%import _toplvl.i +%threadWrapperOff // _defs.i turns on thread protection, turn it off +*/ + +%include ki_exception.i // affects all that follow it + +%include pgm_base.h +%include frame_type.h +%include mail_type.h +%include project.h +%include kiway.h +%include kiway_express.h + +%include kiway_player.i + + +HANDLE_EXCEPTIONS(KIWAY::Player) + +%constant KIWAY Kiway; + +%pythoncode +%{ +#import wx +%} + + +%{ +#include +#include +#include + +#include +#include +#include + + +// Only a single KIWAY is supported in this single_top top level component, +// which is dedicated to loading only a single DSO. +KIWAY Kiway( &Pgm(), KFCTL_PY_PROJECT_SUITE ); + + + + + +/** + * Struct PGM_PYTHON + * implements PGM_BASE with its own OnPgmInit() and OnPgmExit(). + */ +static struct PGM_PYTHON : public PGM_BASE +{ +#if 0 + bool OnPgmInit( wxApp* aWxApp ) + { + // first thing: set m_wx_app + SetApp( aWxApp ); + + if( !initPgm() ) + return false; + + // Use KIWAY to create a top window, which registers its existence also. + // "TOP_FRAME" is a macro that is passed on compiler command line from CMake, + // and is one of the types in FRAME_T. + KIWAY_PLAYER* frame = Kiway.Player( FRAME_PCB, true ); + + Kiway.SetTop( frame ); + + App().SetTopWindow( frame ); // wxApp gets a face. + + // Open project or file specified on the command line: + int argc = App().argc; + + if( argc > 1 ) + { + /* + gerbview handles multiple project data files, i.e. gerber files on + cmd line. Others currently do not, they handle only one. For common + code simplicity we simply pass all the arguments in however, each + program module can do with them what they want, ignore, complain + whatever. We don't establish policy here, as this is a multi-purpose + launcher. + */ + + std::vector argSet; + + for( int i=1; iOpenProjectFiles( argSet ) ) + { + // OpenProjectFiles() API asks that it report failure to the UI. + // Nothing further to say here. + + // We've already initialized things at this point, but wx won't call OnExit if + // we fail out. Call our own cleanup routine here to ensure the relevant resources + // are freed at the right time (if they aren't, segfaults will occur). + OnPgmExit(); + + // Fail the process startup if the file could not be opened, + // although this is an optional choice, one that can be reversed + // also in the KIFACE specific OpenProjectFiles() return value. + return false; + } + } + + frame->Show(); + + return true; + } + + void OnPgmExit() + { + Kiway.OnKiwayEnd(); + + saveCommonSettings(); + + // Destroy everything in PGM_BASE, especially wxSingleInstanceCheckerImpl + // earlier than wxApp and earlier than static destruction would. + PGM_BASE::destroy(); + } +#endif + + +#if 0 // multi-project + void PGM_KICAD::MacOpenFile( const wxString& aFileName ) + { + #if defined(__WXMAC__) + + KICAD_MANAGER_FRAME* frame = (KICAD_MANAGER_FRAME*) App().GetTopWindow(); + + frame->SetProjectFileName( aFileName ); + + wxCommandEvent loadEvent( 0, wxID_ANY ); + + frame->OnLoadProject( loadEvent ); + #endif + } + +#else + void MacOpenFile( const wxString& aFileName ) override + { + wxFileName filename( aFileName ); + + if( filename.FileExists() ) + { +#if 0 + // this pulls in EDA_DRAW_FRAME type info, which we don't want in + // the link image. + KIWAY_PLAYER* frame = dynamic_cast( App().GetTopWindow() ); +#else + KIWAY_PLAYER* frame = (KIWAY_PLAYER*) App().GetTopWindow(); +#endif + if( frame ) + frame->OpenProjectFiles( std::vector( 1, aFileName ) ); + } + } +#endif + +} program; + + +PGM_BASE& Pgm() +{ + return program; +} + +%} + +/* +import ctypes, os, sys +libcef_so = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'libcef.so') +if os.path.exists(libcef_so): +*/ + +%extend PGM_BASE { + + %pythoncode + %{ + + def OnPgmInit(self): + print "hereA" + + if not self.InitPgm(): + return False; + + print "hereB" + + try: + # A KIWAY_PLAYER is a wx.Window + frame = Kiway.Player( FRAME_SCH, True ) + + print "here0" + + except IOError as e: + print 'Player()', e + return None + + print "here1" + + Kiway.SetTop(frame) + + print "here2" + + return frame + %} +}; + diff --git a/common/swig/kiway_player.i b/common/swig/kiway_player.i new file mode 100644 index 0000000000..13da05e347 --- /dev/null +++ b/common/swig/kiway_player.i @@ -0,0 +1,20 @@ + +// Swig interface to classes KIWAY_PLAYER and KIWAY_HOLDER + +class wxFrame +{ +}; + +class KIWAY_PLAYER : public wxFrame +{ +}; + +%ignore wxFrame; +%ignore KIWAY_PLAYER; + +//%include kiway_player.h + +%{ +#include +%} + diff --git a/scripting/wx.i b/common/swig/wx.i similarity index 100% rename from scripting/wx.i rename to common/swig/wx.i diff --git a/scripting/wx_python_helpers.cpp b/common/swig/wx_python_helpers.cpp similarity index 100% rename from scripting/wx_python_helpers.cpp rename to common/swig/wx_python_helpers.cpp diff --git a/scripting/wx_python_helpers.h b/common/swig/wx_python_helpers.h similarity index 85% rename from scripting/wx_python_helpers.h rename to common/swig/wx_python_helpers.h index 2da11d654a..8c6753cc75 100644 --- a/scripting/wx_python_helpers.h +++ b/common/swig/wx_python_helpers.h @@ -1,5 +1,5 @@ -#ifndef __wx_helpers_h -#define __wx_helpers_h +#ifndef WX_HELPERS_H_ +#define WX_HELPERS_H_ #include #include @@ -15,4 +15,4 @@ PyObject* wx2PyString( const wxString& src ); void wxSetDefaultPyEncoding( const char* encoding ); const char* wxGetDefaultPyEncoding(); -#endif +#endif // WX_HELPERS_H_ diff --git a/include/kiway.h b/include/kiway.h index 43eafab1b2..300d6db123 100644 --- a/include/kiway.h +++ b/include/kiway.h @@ -103,6 +103,7 @@ as such! As such, it is OK to use UTF8 characters: #include #include #include +#include #define VTBL_ENTRY virtual @@ -114,6 +115,7 @@ as such! As such, it is OK to use UTF8 characters: // be mangled. #define KIFACE_INSTANCE_NAME_AND_VERSION "KIFACE_1" +#ifndef SWIG #if defined(__linux__) || defined(__FreeBSD__) #define LIB_ENV_VAR wxT( "LD_LIBRARY_PATH" ) #elif defined(__WXMAC__) @@ -123,7 +125,7 @@ as such! As such, it is OK to use UTF8 characters: #else #error Platform support missing #endif - +#endif // SWIG class wxConfigBase; class wxWindow; @@ -151,6 +153,8 @@ struct KIFACE // order of functions in this listing unless you recompile all clients of // this interface. + virtual ~KIFACE() throw() {} + #define KFCTL_STANDALONE (1<<0) ///< Am running as a standalone Top. #define KFCTL_CPP_PROJECT_SUITE (1<<1) ///< Am running under C++ project mgr, possibly with others #define KFCTL_PY_PROJECT_SUITE (1<<2) ///< Am running under python project mgr, possibly with others @@ -269,6 +273,8 @@ public: KIWAY_FACE_COUNT }; + ~KIWAY() throw () {} + /** * Function KifaceType * is a simple mapping function which returns the FACE_T which is known to @@ -278,7 +284,6 @@ public: */ static FACE_T KifaceType( FRAME_T aFrameType ); - // If you change the vtable, recompile all of KiCad. /** @@ -303,6 +308,8 @@ public: * * @return KIWAY_PLAYER* - a valid opened KIWAY_PLAYER or NULL if there * is something wrong or doCreate was false and the player has yet to be created. + * + * @throw IO_ERROR if the *.kiface file could not be found, filled with text saying what. */ VTBL_ENTRY KIWAY_PLAYER* Player( FRAME_T aFrameType, bool doCreate = true, KIWAY_PLAYER* aParent = NULL ); @@ -368,8 +375,8 @@ public: private: - /// Get the full path & name of the DSO holding the requested FACE_T. - static const wxString dso_full_path( FACE_T aFaceId ); + /// Get the [path &] name of the DSO holding the requested FACE_T. + const wxString dso_search_path( FACE_T aFaceId ); #if 0 /// hooked into m_top in SetTop(), marks child frame as closed. @@ -400,7 +407,6 @@ private: wxFrame* m_top; // Usually m_top is the Project manager - // a string array ( size KIWAY_PLAYER_COUNT ) to Store the frame name // of PLAYER frames which were run. // A non empty name means only a PLAYER was run at least one time. @@ -413,20 +419,11 @@ private: }; -/* -/// Given aProject, return its KIWAY* -inline KIWAY* PrjToKiway( PROJECT* aProject ) -{ - // It's ugly, but isolated. The compiler should simply do what's - // it's told to do here and shut up. - KIWAY* p = 0; - ptrdiff_t offset = (char*) &p->m_project - (char*) p; - - return (KIWAY*) ((char*)aProject - offset); -} -*/ - -extern KIWAY Kiway; // provided by single_top.cpp and kicad.cpp +#ifndef SWIG +// provided by single_top.cpp and kicad.cpp; +extern KIWAY Kiway; +// whereas python launchers: single_top.py and project manager instantiate as a python object +#endif /** @@ -444,16 +441,18 @@ extern KIWAY Kiway; // provided by single_top.cpp and kicad.cpp */ typedef KIFACE* KIFACE_GETTER_FUNC( int* aKIFACEversion, int aKIWAYversion, PGM_BASE* aProgram ); + +#ifndef SWIG + /// No name mangling. Each KIFACE (DSO/DLL) will implement this once. extern "C" { - #if defined(BUILD_KIWAY_DLL) -MY_API( KIFACE* ) KIFACE_GETTER( int* aKIFACEversion, int aKIWAYversion, PGM_BASE* aProgram ); + MY_API( KIFACE* ) KIFACE_GETTER( int* aKIFACEversion, int aKIWAYversion, PGM_BASE* aProgram ); #else -KIFACE* KIFACE_GETTER( int* aKIFACEversion, int aKIWAYversion, PGM_BASE* aProgram ); + KIFACE* KIFACE_GETTER( int* aKIFACEversion, int aKIWAYversion, PGM_BASE* aProgram ); #endif - } +#endif // SWIG #endif // KIWAY_H_ diff --git a/include/kiway_player.h b/include/kiway_player.h index eeff8a5b65..9738fd5d5d 100644 --- a/include/kiway_player.h +++ b/include/kiway_player.h @@ -105,7 +105,11 @@ class WX_EVENT_LOOP; * EDA_BASE_FRAME would not have sufficed because BM2CMP_FRAME_BASE is not * derived from it. */ +#ifdef SWIG +class KIWAY_PLAYER : public wxFrame, public KIWAY_HOLDER +#else class KIWAY_PLAYER : public EDA_BASE_FRAME, public KIWAY_HOLDER +#endif { public: KIWAY_PLAYER( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrameType, @@ -118,7 +122,7 @@ public: const wxPoint& aPos, const wxSize& aSize, long aStyle, const wxString& aWdoName = wxFrameNameStr ); - ~KIWAY_PLAYER(); + ~KIWAY_PLAYER() throw(); //--------------------------------------------------------- @@ -238,7 +242,9 @@ protected: wxString m_modal_string; bool m_modal_ret_val; // true if a selection was made +#ifndef SWIG DECLARE_EVENT_TABLE() +#endif }; diff --git a/include/layers_id_colors_and_visibility.h b/include/layers_id_colors_and_visibility.h index 24d819eef2..42b83c5946 100644 --- a/include/layers_id_colors_and_visibility.h +++ b/include/layers_id_colors_and_visibility.h @@ -235,7 +235,7 @@ public: /** * Constructor LSET( const LAYER_ID* aArray, unsigned aCount ) - * works well with an arry or LSEQ. + * works well with an array or LSEQ. */ LSET( const LAYER_ID* aArray, unsigned aCount ); diff --git a/include/macros.h b/include/macros.h index 52580428fc..bf81070340 100644 --- a/include/macros.h +++ b/include/macros.h @@ -33,6 +33,7 @@ #include #include #include +#include #include // std::shared_ptr /** @@ -123,12 +124,14 @@ template inline const T& Clamp( const T& lower, const T& value, con /// Declare a std::vector and also the swig %template in unison #define DECL_VEC_FOR_SWIG(TypeName, MemberType) namespace std { %template(TypeName) vector; } typedef std::vector TypeName; #define DECL_MAP_FOR_SWIG(TypeName, KeyType, ValueType) namespace std { %template(TypeName) map; } typedef std::map TypeName; -#define DECL_SPTR_FOR_SWIG(TypeName, MemberType) namespace std { %template(TypeName) std::shared_ptr; } typedef std::shared_ptr TypeName; +#define DECL_SPTR_FOR_SWIG(TypeName, MemberType) %shared_ptr(MemberType) namespace std { %template(TypeName) shared_ptr; } typedef std::shared_ptr TypeName; +#define DECL_SET_FOR_SWIG(TypeName, MemberType) namespace std { %template(TypeName) set; } typedef std::set TypeName; #else /// Declare a std::vector but no swig %template #define DECL_VEC_FOR_SWIG(TypeName, MemberType) typedef std::vector TypeName; #define DECL_MAP_FOR_SWIG(TypeName, KeyType, ValueType) typedef std::map TypeName; #define DECL_SPTR_FOR_SWIG(TypeName, MemberType) typedef std::shared_ptr TypeName; +#define DECL_SET_FOR_SWIG(TypeName, MemberType) typedef std::set TypeName; #endif #endif // MACROS_H diff --git a/include/pgm_base.h b/include/pgm_base.h index fae237ad5d..271f4f77d2 100644 --- a/include/pgm_base.h +++ b/include/pgm_base.h @@ -64,6 +64,8 @@ public: { } + ~ENV_VAR_ITEM() throw() {} // tell SWIG no exception + bool GetDefinedExternally() const { return m_isDefinedExternally; } void SetDefinedExternally( bool aIsDefinedExternally ) { @@ -106,16 +108,31 @@ class PGM_BASE { public: PGM_BASE(); - ~PGM_BASE(); + virtual ~PGM_BASE(); + +#if 0 + /* + + Derived classes must implement these two functions: OnPgmInit() and + OnPgmExit(), and since they are only called from same source file as their + implementation, these need not be virtual here. In fact, in the case of + python project manager's class PGM_PYTHON, these functions are actually + written in python. In total there are three implementations, corresponding + to the three defines given by kiface.h's KFCTL_* #defines. + + */ /** * Function OnPgmInit * this is the first executed function (like main() ) * @return true if the application can be started. */ - virtual bool OnPgmInit( wxApp* aWxApp ) = 0; // call this from wxApp::OnInit() + virtual bool OnPgmInit() = 0; // call this from wxApp::OnInit() - virtual void OnPgmExit() = 0; // call this from wxApp::OnExit() + virtual void OnPgmExit() = 0; // call this from wxApp::OnExit() +#endif + + //--------------------------------------------------------- /** * Function MacOpenFile @@ -123,9 +140,7 @@ public: * MacOSX requires it for file association. * @see http://wiki.wxwidgets.org/WxMac-specific_topics */ - virtual void MacOpenFile( const wxString& aFileName ) = 0; - - //--------------------------------------------------------- + VTBL_ENTRY void MacOpenFile( const wxString& aFileName ) = 0; VTBL_ENTRY wxConfigBase* CommonSettings() const { return m_common_settings; } @@ -273,20 +288,14 @@ public: /** * Function App * returns a bare naked wxApp, which may come from wxPython, SINGLE_TOP, or kicad.exe. - * Use this function instead of wxGetApp(). + * Should return what wxGetApp() returns. */ - VTBL_ENTRY wxApp& App() - { - wxASSERT( m_wx_app ); - return *m_wx_app; - } + VTBL_ENTRY wxApp& App(); //-------------------------------------------------------- static const wxChar workingDirKey[]; -protected: - /** * Function initPgm * initializes this program (process) in a KiCad standard way, @@ -298,7 +307,20 @@ protected: * But nothing relating to DSOs or projects. * @return bool - true if success, false if failure and program is to terminate. */ - bool initPgm(); + bool InitPgm(); + + // The PGM_* classes can have difficulties at termination if they + // are not destroyed soon enough. Relying on a static destructor can be + // too late for contained objects like wxSingleInstanceChecker. + void Destroy(); + + /** + * Function saveCommonSettings + * saves the program (process) settings subset which are stored .kicad_common + */ + void SaveCommonSettings(); + +protected: /** * Function loadCommonSettings @@ -306,12 +328,6 @@ protected: */ void loadCommonSettings(); - /** - * Function saveCommonSettings - * saves the program (process) settings subset which are stored .kicad_common - */ - void saveCommonSettings(); - /// prevents multiple instances of a program from being run at the same time. wxSingleInstanceChecker* m_pgm_checker; @@ -354,17 +370,11 @@ protected: /// Flag to indicate if the environment variable overwrite warning dialog should be shown. bool m_show_env_var_dialog; - - wxApp* m_wx_app; - - // The PGM_* classes can have difficulties at termination if they - // are not destroyed soon enough. Relying on a static destructor can be - // too late for contained objects like wxSingleInstanceChecker. - void destroy(); }; /// The global Program "get" accessor. +/// Implemented in: 1) common/single_top.cpp, 2) kicad/kicad.cpp, and 3) scripting/kiway.i extern PGM_BASE& Pgm(); #endif // PGM_BASE_H_ diff --git a/kicad/pgm_kicad.h b/kicad/pgm_kicad.h index 61990d9e9f..b16c9854ef 100644 --- a/kicad/pgm_kicad.h +++ b/kicad/pgm_kicad.h @@ -44,14 +44,15 @@ public: m_bm( "kicad" ) // indicates a "$HOME/.kicad wxConfig like" config file. {} - ~PGM_KICAD() + ~PGM_KICAD() throw() { - destroy(); + Destroy(); } - bool OnPgmInit( wxApp* aWxApp ); // overload PGM_BASE virtual - void OnPgmExit(); // overload PGM_BASE virtual - void MacOpenFile( const wxString& aFileName ); // overload PGM_BASE virtual + bool OnPgmInit(); + void OnPgmExit(); + + void MacOpenFile( const wxString& aFileName ); wxFileHistory& GetFileHistory() { return m_bm.m_history; } @@ -61,12 +62,12 @@ public: wxString GetHelpFileName() { return m_bm.m_help_file; } -protected: - // The PGM_* classes can have difficulties at termination if they // are not destroyed soon enough. Relying on a static destructor can be // too late for contained objects like wxSingleInstanceChecker. - void destroy(); + void Destroy(); + +protected: BIN_MOD m_bm; }; diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index 17291cff0b..337732a048 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -5,16 +5,14 @@ add_subdirectory(router) # psnrouter depends on make_lexer outputs in common (bug # 1285878 ) add_dependencies( pnsrouter pcbcommon ) +set( WXPYTHON_SWIG_DIR /usr/include/wx-3.0/wx/wxPython/i_files ) if( KICAD_SCRIPTING OR KICAD_SCRIPTING_MODULES ) file( MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/scripting ) - # SWIG 3.0 or later require for C++11 support. - find_package( SWIG 3.0 REQUIRED ) - include( ${SWIG_USE_FILE} ) - # Infrequently needed headers go at end of search paths, append to INC_AFTER - set( INC_AFTER ${INC_AFTER} ${CMAKE_CURRENT_SOURCE_DIR}/scripting ) + set( INC_AFTER ${INC_AFTER} swig ) + set( INC_AFTER ${INC_AFTER} ../common/swig ) #message( STATUS "pcbnew INC_AFTER:${INC_AFTER}" ) endif() @@ -317,10 +315,10 @@ set( PCBNEW_SCRIPTING_DIALOGS ) set( PCBNEW_SCRIPTING_PYTHON_HELPERS - ../scripting/wx_python_helpers.cpp - ../scripting/python_scripting.cpp - scripting/pcbnew_scripting_helpers.cpp - scripting/pcbnew_footprint_wizards.cpp + ../common/swig/wx_python_helpers.cpp + swig/python_scripting.cpp + swig/pcbnew_scripting_helpers.cpp + swig/pcbnew_footprint_wizards.cpp ) if( KICAD_SCRIPTING ) @@ -335,10 +333,11 @@ endif() if( KICAD_SCRIPTING OR KICAD_SCRIPTING_MODULES ) set( SWIG_FLAGS - -I${CMAKE_CURRENT_SOURCE_DIR}/../.. -I${CMAKE_CURRENT_SOURCE_DIR} -I${CMAKE_CURRENT_SOURCE_DIR}/../include -I${CMAKE_CURRENT_SOURCE_DIR}/../scripting + -I${CMAKE_CURRENT_SOURCE_DIR}/../common/swig + -I${WXPYTHON_SWIG_DIR} ) if( DEBUG ) @@ -346,7 +345,6 @@ if( KICAD_SCRIPTING OR KICAD_SCRIPTING_MODULES ) endif() # collect CFLAGS , and pass them to swig later - get_directory_property( DirDefs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMPILE_DEFINITIONS ) foreach( d ${DirDefs} ) set( SWIG_FLAGS ${SWIG_FLAGS} -D${d} ) @@ -370,21 +368,22 @@ if( KICAD_SCRIPTING ) DEPENDS pcbcommon DEPENDS plotcontroller.h DEPENDS exporters/gendrill_Excellon_writer.h - DEPENDS scripting/pcbnew.i - DEPENDS scripting/board.i - DEPENDS scripting/board_item.i - DEPENDS scripting/module.i - DEPENDS scripting/plugins.i - DEPENDS scripting/units.i - DEPENDS ../scripting/dlist.i - DEPENDS ../scripting/kicad.i - DEPENDS ../scripting/wx.i + DEPENDS swig/pcbnew.i + DEPENDS swig/board.i + DEPENDS swig/board_item.i + DEPENDS swig/module.i + DEPENDS swig/plugins.i + DEPENDS swig/units.i + DEPENDS ../common/swig/dlist.i + DEPENDS ../common/swig/kicad.i + DEPENDS ../common/swig/wx.i + DEPENDS ../common/swig/ki_exception.i DEPENDS ../scripting/kicadplugins.i COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/docstrings COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/docstrings/docstrings.i # this makes docstrings.i available if it doesn't exist - COMMAND ${SWIG_EXECUTABLE} ${SWIG_OPTS} -o ${CMAKE_CURRENT_BINARY_DIR}/pcbnew_wrap.cxx scripting/pcbnew.i + COMMAND ${SWIG_EXECUTABLE} ${SWIG_OPTS} -o ${CMAKE_CURRENT_BINARY_DIR}/pcbnew_wrap.cxx swig/pcbnew.i COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripting/build_tools/fix_swig_imports.py ${CMAKE_CURRENT_BINARY_DIR}/pcbnew.py WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) @@ -406,11 +405,22 @@ if( KICAD_SCRIPTING_MODULES ) #message( "building pcbnew scripting" ) set( CMAKE_SWIG_FLAGS ${SWIG_FLAGS} ) - set_source_files_properties( scripting/pcbnew.i PROPERTIES CPLUSPLUS ON ) + set_source_files_properties( swig/pcbnew.i PROPERTIES CPLUSPLUS ON ) + + # https://cmake.org/cmake/help/v3.2/module/UseSWIG.html + # Set this ..EXTRA_DEPS variable before invoking swig_add_module() macro + set( SWIG_MODULE_pcbnew_EXTRA_DEPS + swig/board.i + swig/board_item.i + swig/plugins.i + swig/units.i + ../common/swig/ki_exception.i + ../common/swig/kicad.i + ) swig_add_module( pcbnew python - scripting/pcbnew.i + swig/pcbnew.i ${PCBNEW_SCRIPTING_PYTHON_HELPERS} pcbnew.cpp ${PCBNEW_SRCS} @@ -674,14 +684,14 @@ if( KICAD_SCRIPTING ) add_dependencies( ScriptingPcbnewPyCopy ScriptingWxpythonCopy ) endif() - # scripting plugins - install( DIRECTORY ${PROJECT_SOURCE_DIR}/pcbnew/scripting/plugins/ + # python plugins + install( DIRECTORY ${PROJECT_SOURCE_DIR}/pcbnew/python/plugins/ DESTINATION ${KICAD_DATA}/scripting/plugins FILE_PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ ) - # scripting python shell - install( DIRECTORY ${PROJECT_SOURCE_DIR}/pcbnew/scripting/kicad_pyshell/ + # python shell + install( DIRECTORY ${PROJECT_SOURCE_DIR}/pcbnew/python/kicad_pyshell/ DESTINATION ${KICAD_DATA}/scripting/kicad_pyshell FILE_PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ ) @@ -724,17 +734,3 @@ if( APPLE ) ) endif() endif() - - -if( false ) # haven't been used in years. - # This one gets made only when testing. - add_executable( specctra_test EXCLUDE_FROM_ALL specctra_test.cpp specctra.cpp ) - target_link_libraries( specctra_test common ${wxWidgets_LIBRARIES} ) - - - # This one gets made only when testing. - add_executable( layer_widget_test WIN32 EXCLUDE_FROM_ALL - layer_widget.cpp - ) - target_link_libraries( layer_widget_test common ${wxWidgets_LIBRARIES} ) -endif() diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp index fd82c2b7d9..ad050ba71f 100644 --- a/pcbnew/class_board.cpp +++ b/pcbnew/class_board.cpp @@ -224,7 +224,7 @@ static void otherEnd( const TRACK& aTrack, const wxPoint& aNotThisEnd, wxPoint* /** * Function find_vias_and_tracks_at - * collects TRACKs and VIAs at aPos and returns true if any were VIAs. + * collects TRACKs and VIAs at aPos and returns the @a track_count which excludes vias. */ static int find_vias_and_tracks_at( TRACKS& at_next, TRACKS& in_net, LSET& lset, const wxPoint& next ) { @@ -296,10 +296,13 @@ static void checkConnectedTo( BOARD* aBoard, TRACKS* aList, const TRACKS& aTrack if( next == aGoal ) return; // success - if( aBoard->GetPad( next, lset ) ) + // Want an exact match on the position of next, i.e. pad at next, + // not a forgiving HitTest() with tolerance type of match, otherwise the overall + // algorithm will not work. GetPadFast() is an exact match as I write this. + if( aBoard->GetPadFast( next, lset ) ) { std::string m = StrPrintf( - "there is an intervening pad at:(xy %s) between start:(xy %s) and goal:(xy %s)", + "intervening pad at:(xy %s) between start:(xy %s) and goal:(xy %s)", BOARD_ITEM::FormatInternalUnits( next ).c_str(), BOARD_ITEM::FormatInternalUnits( aStart ).c_str(), BOARD_ITEM::FormatInternalUnits( aGoal ).c_str() @@ -313,13 +316,13 @@ static void checkConnectedTo( BOARD* aBoard, TRACKS* aList, const TRACKS& aTrack { std::string m = StrPrintf( "found %d tracks intersecting at (xy %s), exactly 2 would be acceptable.", - track_count, + track_count + aList->size() == 1 ? 1 : 0, BOARD_ITEM::FormatInternalUnits( next ).c_str() ); THROW_IO_ERROR( m ); } - // reduce lset down to the layer that the only track at 'next' is on. + // reduce lset down to the layer that the last track at 'next' is on. lset = aList->back()->GetLayerSet(); otherEnd( *aList->back(), next, &next ); @@ -334,21 +337,21 @@ static void checkConnectedTo( BOARD* aBoard, TRACKS* aList, const TRACKS& aTrack } -TRACKS BOARD::TracksInNetBetweenPoints( const wxPoint& aStartPos, const wxPoint& aEndPos, int aNetCode ) +TRACKS BOARD::TracksInNetBetweenPoints( const wxPoint& aStartPos, const wxPoint& aGoalPos, int aNetCode ) { TRACKS in_between_pts; - TRACKS on_start_pad; + TRACKS on_start_point; TRACKS in_net = TracksInNet( aNetCode ); // a small subset of TRACKs and VIAs for( auto t : in_net ) { if( t->Type() == PCB_TRACE_T && ( t->GetStart() == aStartPos || t->GetEnd() == aStartPos ) ) - on_start_pad.push_back( t ); + on_start_point.push_back( t ); } - IO_ERROR last_error; + wxString per_path_problem_text; - for( auto t : on_start_pad ) + for( auto t : on_start_point ) // explore each trace (path) leaving aStartPos { // checkConnectedTo() fills in_between_pts on every attempt. For failures // this set needs to be cleared. @@ -356,11 +359,12 @@ TRACKS BOARD::TracksInNetBetweenPoints( const wxPoint& aStartPos, const wxPoint& try { - checkConnectedTo( this, &in_between_pts, in_net, aEndPos, aStartPos, t ); + checkConnectedTo( this, &in_between_pts, in_net, aGoalPos, aStartPos, t ); } catch( const IO_ERROR& ioe ) // means not connected { - last_error = ioe; + per_path_problem_text += "\n\t"; + per_path_problem_text += ioe.Problem(); continue; // keep trying, there may be other paths leaving from aStartPos } @@ -369,17 +373,13 @@ TRACKS BOARD::TracksInNetBetweenPoints( const wxPoint& aStartPos, const wxPoint& return in_between_pts; } - if( on_start_pad.size() == 1 ) - throw last_error; - else - { - std::string m = StrPrintf( - "no path connecting start:(xy %s) with end:(xy %s)", + wxString m = wxString::Format( + "no clean path connecting start:(xy %s) with goal:(xy %s)", BOARD_ITEM::FormatInternalUnits( aStartPos ).c_str(), - BOARD_ITEM::FormatInternalUnits( aEndPos ).c_str() + BOARD_ITEM::FormatInternalUnits( aGoalPos ).c_str() ); - THROW_IO_ERROR( m ); - } + + THROW_IO_ERROR( m + per_path_problem_text ); } @@ -405,6 +405,8 @@ void BOARD::chainMarkedSegments( wxPoint aPosition, const LSET& aLayerSet, TRACK */ for( ; ; ) { + + if( GetPad( aPosition, layer_set ) != NULL ) return; diff --git a/pcbnew/class_board.h b/pcbnew/class_board.h index 7035e19102..89bd4d081a 100644 --- a/pcbnew/class_board.h +++ b/pcbnew/class_board.h @@ -1309,8 +1309,6 @@ public: * Function TrackInNet * collects all the TRACKs and VIAs that are members of a net given by aNetCode. * Used from python. - * @param aList is a non-owning container that is appended to with the TRACKs and VIAs, - * and is not initiallly cleared. * @param aNetCode gives the id of the net. * @return TRACKS - which are in the net identified by @a aNetCode. */ @@ -1321,17 +1319,19 @@ public: * collects all the TRACKs and VIAs that are members of a net given by aNetCode and that * make up a path between two end points. The end points must be carefully chosen, * and are typically the locations of two neighboring pads. The function fails if there - * is an intervening pad or a 3 way intersection at a track or via. + * is an intervening pad or a 3 way intersection at a track or via. The seeking starts + * at @a aStartPos and strives to travel to @a aGoalPos. * Used from python. * @param aStartPos must correspond to a point on the BOARD which has a TRACK end or start, * typically the location of either a via or pad. - * @param aEndPos must correspond to a point on the BOARD which has a TRACK end or start, + * @param aGoalPos must correspond to a point on the BOARD which has a TRACK end or start, * typically the location of either a via or pad. * @param aNetCode gives the id of the net. * @return TRACKS - non empty if success, empty if your aStartPos or aEndPos are bad or * the net is interrupted along the way by an intervening D_PAD or a 3 way path. + * @throw IO_ERROR in order to convey detailed error reason upon failure. */ - TRACKS TracksInNetBetweenPoints( const wxPoint& aStartPos, const wxPoint& aEndPos, int aNetCode ); + TRACKS TracksInNetBetweenPoints( const wxPoint& aStartPos, const wxPoint& aGoalPos, int aNetCode ); /** * Function GetFootprint diff --git a/pcbnew/class_netclass.cpp b/pcbnew/class_netclass.cpp index be1ad8f730..88d23420cc 100644 --- a/pcbnew/class_netclass.cpp +++ b/pcbnew/class_netclass.cpp @@ -35,7 +35,7 @@ // This will get mapped to "kicad_default" in the specctra_export. -const wxChar NETCLASS::Default[] = wxT( "Default" ); +const char NETCLASS::Default[] = "Default"; // Initial values for netclass initialization const int NETCLASS::DEFAULT_CLEARANCE = Millimeter2iu( 0.2 ); // track to track and track to pads clearance diff --git a/pcbnew/class_netclass.h b/pcbnew/class_netclass.h index bca0afcfcb..c12096d617 100644 --- a/pcbnew/class_netclass.h +++ b/pcbnew/class_netclass.h @@ -43,6 +43,9 @@ class BOARD; class BOARD_DESIGN_SETTINGS; +DECL_SET_FOR_SWIG( STRINGSET, wxString ) + + /** * Class NETCLASS * handles a collection of nets and the parameters used to route or @@ -66,8 +69,6 @@ protected: wxString m_Name; ///< Name of the net class wxString m_Description; ///< what this NETCLASS is for. - typedef std::set STRINGSET; - STRINGSET m_Members; ///< names of NET members of this class /// The units on these parameters is Internal Units (1 nm) @@ -86,7 +87,7 @@ protected: public: - static const wxChar Default[]; ///< the name of the default NETCLASS + static const char Default[]; ///< the name of the default NETCLASS /** * Constructor @@ -163,6 +164,8 @@ public: m_Members.erase( aName ); } + STRINGSET& NetNames() { return m_Members; } ///< for SWIG + const wxString& GetDescription() const { return m_Description; } void SetDescription( const wxString& aDesc ) { m_Description = aDesc; } @@ -231,10 +234,10 @@ class NETCLASSES private: /// all the NETCLASSes except the default one. - NETCLASS_MAP m_NetClasses; + NETCLASS_MAP m_NetClasses; /// the default NETCLASS. - NETCLASSPTR m_Default; + NETCLASSPTR m_Default; public: NETCLASSES(); @@ -277,10 +280,10 @@ public: /** * Function Add - * takes ownership of \a aNetclass and puts it into this NETCLASSES container. + * takes \a aNetclass and puts it into this NETCLASSES container. * @param aNetclass is netclass to add * @return true if the name within aNetclass is unique and it could be inserted OK, - * else false because the name was not unique and caller still owns aNetclass. + * else false because the name was not unique. */ bool Add( NETCLASSPTR aNetclass ); @@ -300,6 +303,8 @@ public: */ NETCLASSPTR Find( const wxString& aName ) const; + /// Provide public access to m_NetClasses so it gets swigged. + NETCLASS_MAP& NetClasses() { return m_NetClasses; } }; #endif // CLASS_NETCLASS_H diff --git a/pcbnew/pcb_parser.cpp b/pcbnew/pcb_parser.cpp index 228cbe9913..49c75df6ac 100644 --- a/pcbnew/pcb_parser.cpp +++ b/pcbnew/pcb_parser.cpp @@ -619,8 +619,7 @@ void PCB_PARSER::parseGeneralSection() throw( IO_ERROR, PARSE_ERROR ) break; default: // Skip everything but the board thickness. - wxLogDebug( wxT( "Skipping general section token %s " ), - GetChars( GetTokenString( token ) ) ); + //wxLogDebug( wxT( "Skipping general section token %s " ), GetChars( GetTokenString( token ) ) ); while( ( token = NextTok() ) != T_RIGHT ) { diff --git a/pcbnew/scripting/examples/createFPC40.py b/pcbnew/python/examples/createFPC40.py old mode 100755 new mode 100644 similarity index 100% rename from pcbnew/scripting/examples/createFPC40.py rename to pcbnew/python/examples/createFPC40.py diff --git a/pcbnew/scripting/examples/createPcb.py b/pcbnew/python/examples/createPcb.py old mode 100755 new mode 100644 similarity index 100% rename from pcbnew/scripting/examples/createPcb.py rename to pcbnew/python/examples/createPcb.py diff --git a/pcbnew/scripting/examples/hidePcbValuesShowReferences.py b/pcbnew/python/examples/hidePcbValuesShowReferences.py similarity index 100% rename from pcbnew/scripting/examples/hidePcbValuesShowReferences.py rename to pcbnew/python/examples/hidePcbValuesShowReferences.py diff --git a/pcbnew/scripting/examples/listPcb.py b/pcbnew/python/examples/listPcb.py old mode 100755 new mode 100644 similarity index 100% rename from pcbnew/scripting/examples/listPcb.py rename to pcbnew/python/examples/listPcb.py diff --git a/pcbnew/scripting/examples/listPcbLibrary.py b/pcbnew/python/examples/listPcbLibrary.py old mode 100755 new mode 100644 similarity index 100% rename from pcbnew/scripting/examples/listPcbLibrary.py rename to pcbnew/python/examples/listPcbLibrary.py diff --git a/pcbnew/scripting/kicad_pyshell/__init__.py b/pcbnew/python/kicad_pyshell/__init__.py similarity index 100% rename from pcbnew/scripting/kicad_pyshell/__init__.py rename to pcbnew/python/kicad_pyshell/__init__.py diff --git a/pcbnew/scripting/plugins/FPC_(SMD_type)_footprintwizard.py b/pcbnew/python/plugins/FPC_(SMD_type)_footprintwizard.py similarity index 100% rename from pcbnew/scripting/plugins/FPC_(SMD_type)_footprintwizard.py rename to pcbnew/python/plugins/FPC_(SMD_type)_footprintwizard.py diff --git a/pcbnew/scripting/plugins/FootprintWizardDrawingAids.py b/pcbnew/python/plugins/FootprintWizardDrawingAids.py similarity index 100% rename from pcbnew/scripting/plugins/FootprintWizardDrawingAids.py rename to pcbnew/python/plugins/FootprintWizardDrawingAids.py diff --git a/pcbnew/scripting/plugins/HelpfulFootprintWizardPlugin.py b/pcbnew/python/plugins/HelpfulFootprintWizardPlugin.py similarity index 100% rename from pcbnew/scripting/plugins/HelpfulFootprintWizardPlugin.py rename to pcbnew/python/plugins/HelpfulFootprintWizardPlugin.py diff --git a/pcbnew/scripting/plugins/PadArray.py b/pcbnew/python/plugins/PadArray.py similarity index 100% rename from pcbnew/scripting/plugins/PadArray.py rename to pcbnew/python/plugins/PadArray.py diff --git a/pcbnew/scripting/plugins/__init__.py b/pcbnew/python/plugins/__init__.py similarity index 100% rename from pcbnew/scripting/plugins/__init__.py rename to pcbnew/python/plugins/__init__.py diff --git a/pcbnew/scripting/plugins/bga_wizard.py b/pcbnew/python/plugins/bga_wizard.py similarity index 100% rename from pcbnew/scripting/plugins/bga_wizard.py rename to pcbnew/python/plugins/bga_wizard.py diff --git a/pcbnew/scripting/plugins/circular_pad_array_wizard.py b/pcbnew/python/plugins/circular_pad_array_wizard.py similarity index 100% rename from pcbnew/scripting/plugins/circular_pad_array_wizard.py rename to pcbnew/python/plugins/circular_pad_array_wizard.py diff --git a/pcbnew/scripting/plugins/qfn_wizard.py b/pcbnew/python/plugins/qfn_wizard.py similarity index 100% rename from pcbnew/scripting/plugins/qfn_wizard.py rename to pcbnew/python/plugins/qfn_wizard.py diff --git a/pcbnew/scripting/plugins/qfp_wizard.py b/pcbnew/python/plugins/qfp_wizard.py similarity index 100% rename from pcbnew/scripting/plugins/qfp_wizard.py rename to pcbnew/python/plugins/qfp_wizard.py diff --git a/pcbnew/scripting/plugins/sdip_wizard.py b/pcbnew/python/plugins/sdip_wizard.py similarity index 100% rename from pcbnew/scripting/plugins/sdip_wizard.py rename to pcbnew/python/plugins/sdip_wizard.py diff --git a/pcbnew/scripting/plugins/touch_slider_wizard.py b/pcbnew/python/plugins/touch_slider_wizard.py similarity index 100% rename from pcbnew/scripting/plugins/touch_slider_wizard.py rename to pcbnew/python/plugins/touch_slider_wizard.py diff --git a/pcbnew/scripting/plugins/uss39_barcode.py b/pcbnew/python/plugins/uss39_barcode.py similarity index 100% rename from pcbnew/scripting/plugins/uss39_barcode.py rename to pcbnew/python/plugins/uss39_barcode.py diff --git a/pcbnew/scripting/plugins/zip_wizard.py b/pcbnew/python/plugins/zip_wizard.py similarity index 100% rename from pcbnew/scripting/plugins/zip_wizard.py rename to pcbnew/python/plugins/zip_wizard.py diff --git a/pcbnew/scripting/TODO.txt b/pcbnew/swig/TODO.txt similarity index 100% rename from pcbnew/scripting/TODO.txt rename to pcbnew/swig/TODO.txt diff --git a/pcbnew/scripting/board.i b/pcbnew/swig/board.i similarity index 54% rename from pcbnew/scripting/board.i rename to pcbnew/swig/board.i index 2f6e4c8599..7d6955ca8b 100644 --- a/pcbnew/scripting/board.i +++ b/pcbnew/swig/board.i @@ -28,38 +28,123 @@ */ -%extend BOARD -{ - %pythoncode - %{ - def GetModules(self): return self.m_Modules - def GetDrawings(self): return self.m_Drawings - def GetTracks(self): return self.m_Track - def GetFullRatsnest(self): return self.m_FullRatsnest +/* - def Save(self,filename): - return SaveBoard(filename,self,IO_MGR.KICAD) +By default we do not translate exceptions for EVERY C++ function since not every +C++ function throws, and that would be unused and very bulky mapping code. +Therefore please help gather the subset of C++ functions for this class that do +throw and add them here, before the class declarations. - # - # add function, clears the thisown to avoid python from deleting - # the object in the garbage collector - # +*/ +HANDLE_EXCEPTIONS(BOARD::TracksInNetBetweenPoints) - def Add(self,item): - item.thisown=0 - self.AddChild(item) - %} -} +%{ +#include + +#include +#include + +%} + + +%import dlist.h + +// Organize the two forms of include side by side so that it is easier to +// migrate each grouping into a separate *.i file later. + + +%include class_board_item.h +%{ +#include +%} + +%include class_board_connected_item.h +%{ +#include +%} + +%include pad_shapes.h + +%include class_pad.h +%{ +#include +%} + +%include class_module.h +%{ +#include +%} + +%include class_track.h +%{ +#include +%} + +%include class_zone.h +%include zones.h +%{ +#include +#include +%} + + +%include layers_id_colors_and_visibility.h + +%include class_pcb_text.h +%{ +#include +%} + +%include class_dimension.h +%{ +#include +%} + + +%include class_drawsegment.h +%{ +#include +%} + +%include class_marker_pcb.h +%{ +#include +%} + + +%include class_mire.h +%{ +#include +%} + + +%include class_text_mod.h +%{ +#include +%} + +%include class_edge_mod.h +%{ +#include +%} + +%include class_zone_settings.h + +%include class_netinfo.h +%include class_netclass.h +%{ +#include +#include +%} + // this is to help python with the * accessor of DLIST templates - %rename(Get) operator BOARD_ITEM*; %rename(Get) operator TRACK*; %rename(Get) operator D_PAD*; %rename(Get) operator MODULE*; - // we must translate C++ templates to scripting languages %template(BOARD_ITEM_List) DLIST; @@ -73,10 +158,30 @@ %template(RATSNEST_Vector) std::vector; +%include class_board.h + + %extend BOARD { %pythoncode - { + %{ + + def GetModules(self): return self.m_Modules + def GetDrawings(self): return self.m_Drawings + def GetTracks(self): return self.m_Track + def GetFullRatsnest(self): return self.m_FullRatsnest + + def Save(self,filename): + return SaveBoard(filename,self,IO_MGR.KICAD) + + # + # add function, clears the thisown to avoid python from deleting + # the object in the garbage collector + # + def Add(self,item): + item.thisown=0 + self.AddNative(item) + def GetNetClasses(self): return self.GetDesignSettings().m_NetClasses @@ -88,23 +193,53 @@ def GetTrackWidthList(self): return self.GetDesignSettings().m_TrackWidthList - } + + def GetNetsByName(self): + """ + Return a dictionary like object with key:wxString netname and value:NETINFO_ITEM + """ + return self.GetNetInfo().NetsByName() + + def GetNetsByNetcode(self): + """ + Return a dictionary like object with key:int netcode and value:NETINFO_ITEM + """ + return self.GetNetInfo().NetsByNetcode() + + def GetNetcodeFromNetname(self,netname): + """ + Given a netname, return its netcode + """ + net = self.GetNetsByName()[netname] + return net.GetNet() + + def GetAllNetClasses(self): + """ + Return a dictionary like object with net_class_name as key and NETCLASSPRT as value + GetNetClasses(BOARD self) -> { wxString net_class_name : NETCLASSPTR } + Include the "Default" netclass also. + """ + netclassmap = self.GetNetClasses().NetClasses() + # add the Default one too + netclassmap[ NETCLASS.Default ] = self.GetNetClasses().GetDefault() + return netclassmap + %} } %extend DRAWSEGMENT { %pythoncode - { + %{ def GetShapeStr(self): return self.ShowShape(self.GetShape()) - } + %} } %extend BOARD_ITEM { %pythoncode - { + %{ def SetPos(self,p): self.SetPosition(p) self.SetPos0(p) @@ -114,7 +249,7 @@ self.SetStart0(start) self.SetEnd(end) self.SetEnd0(end) - } + %} } diff --git a/pcbnew/swig/board.i.orig b/pcbnew/swig/board.i.orig new file mode 100644 index 0000000000..e69de29bb2 diff --git a/pcbnew/swig/board.i.rej b/pcbnew/swig/board.i.rej new file mode 100644 index 0000000000..f994ba5ef9 --- /dev/null +++ b/pcbnew/swig/board.i.rej @@ -0,0 +1,147 @@ +--- pcbnew/scripting/board.i ++++ pcbnew/swig/board.i +@@ -28,38 +28,123 @@ + */ + + +-%extend BOARD +-{ +- %pythoncode +- %{ +- def GetModules(self): return self.m_Modules +- def GetDrawings(self): return self.m_Drawings +- def GetTracks(self): return self.m_Track +- def GetFullRatsnest(self): return self.m_FullRatsnest ++/* + +- def Save(self,filename): +- return SaveBoard(filename,self,IO_MGR.KICAD) ++By default we do not translate exceptions for EVERY C++ function since not every ++C++ function throws, and that would be unused and very bulky mapping code. ++Therefore please help gather the subset of C++ functions for this class that do ++throw and add them here, before the class declarations. + +- # +- # add function, clears the thisown to avoid python from deleting +- # the object in the garbage collector +- # ++*/ ++HANDLE_EXCEPTIONS(BOARD::TracksInNetBetweenPoints) + +- def Add(self,item): +- item.thisown=0 +- self.AddNative(item) +- %} + +-} ++%{ ++#include + +-// this is to help python with the * accessor of DLIST templates ++#include ++#include ++ ++%} ++ ++ ++%import dlist.h ++ ++// Organize the two forms of include side by side so that it is easier to ++// migrate each grouping into a separate *.i file later. ++ ++ ++%include class_board_item.h ++%{ ++#include ++%} ++ ++%include class_board_connected_item.h ++%{ ++#include ++%} ++ ++%include pad_shapes.h ++ ++%include class_pad.h ++%{ ++#include ++%} ++ ++%include class_module.h ++%{ ++#include ++%} ++ ++%include class_track.h ++%{ ++#include ++%} ++ ++%include class_zone.h ++%include zones.h ++%{ ++#include ++#include ++%} ++ ++ ++%include layers_id_colors_and_visibility.h ++ ++%include class_pcb_text.h ++%{ ++#include ++%} ++ ++%include class_dimension.h ++%{ ++#include ++%} + ++ ++%include class_drawsegment.h ++%{ ++#include ++%} ++ ++%include class_marker_pcb.h ++%{ ++#include ++%} ++ ++ ++%include class_mire.h ++%{ ++#include ++%} ++ ++ ++%include class_text_mod.h ++%{ ++#include ++%} ++ ++%include class_edge_mod.h ++%{ ++#include ++%} ++ ++%include class_zone_settings.h ++ ++%include class_netinfo.h ++%include class_netclass.h ++%{ ++#include ++#include ++%} ++ ++ ++// this is to help python with the * accessor of DLIST templates + %rename(Get) operator BOARD_ITEM*; + %rename(Get) operator TRACK*; + %rename(Get) operator D_PAD*; + %rename(Get) operator MODULE*; + +- + // we must translate C++ templates to scripting languages + + %template(BOARD_ITEM_List) DLIST; diff --git a/pcbnew/scripting/board_item.i b/pcbnew/swig/board_item.i similarity index 100% rename from pcbnew/scripting/board_item.i rename to pcbnew/swig/board_item.i diff --git a/pcbnew/scripting/module.i b/pcbnew/swig/module.i similarity index 100% rename from pcbnew/scripting/module.i rename to pcbnew/swig/module.i diff --git a/pcbnew/scripting/pcbnew.i b/pcbnew/swig/pcbnew.i similarity index 62% rename from pcbnew/scripting/pcbnew.i rename to pcbnew/swig/pcbnew.i index 8fbbccadd1..e77a93dec1 100644 --- a/pcbnew/scripting/pcbnew.i +++ b/pcbnew/swig/pcbnew.i @@ -36,10 +36,15 @@ #endif -%include "kicad.i" +%include kicad.i %include -%include + +%{ +#include +%} +%include fpid.h + // ignore a couple of items that generate warnings from swig built code %ignore BOARD_ITEM::ZeroOffset; @@ -54,59 +59,15 @@ class BASE_SET {}; %rename(AddNative) *::Add; // fix method names conflicts -%rename(AddChild) BOARD_ITEM_CONTAINER::Add; -%rename(RemoveChild) BOARD_ITEM_CONTAINER::Remove; -%rename(DeleteChild) BOARD_ITEM_CONTAINER::Delete; - -%exception { - try{ - $action - } - catch( IO_ERROR e ) - { - std::string str = TO_UTF8( e.errorText ); - str += '\n'; - PyErr_SetString( PyExc_IOError, str.c_str() ); - return NULL; - } - catch( std::exception &e ) - { - std::string str = e.what(); - str += '\n'; - PyErr_SetString( PyExc_IOError, str.c_str() ); - return NULL; - } - catch( ... ) - { - SWIG_fail; - } -} -%include exception.i +%rename(AddChild) MODULE::Add; +%rename(RemoveChild) MODULE::Remove; +%rename(DeleteChild) MODULE::Delete; // this is what it must be included in the wrapper .cxx code to compile %{ #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - - #include #include //#include @@ -117,8 +78,6 @@ class BASE_SET {}; #include #include - #include - BOARD *GetBoard(); /* get current editor board */ %} @@ -128,27 +87,6 @@ class BASE_SET {}; #include %} -%include -%include -%include -%include -%include -%include -%include -%include -%include -%include -%include -%include -%include -%include -%include -%include -%include -%include -%include -%include -%include %include %include @@ -157,10 +95,6 @@ class BASE_SET {}; %include %include -%include - -%include "board_item.i" - %include @@ -169,10 +103,10 @@ class BASE_SET {}; %include %include -%include "board.i" -%include "module.i" -%include "plugins.i" -%include "units.i" +%include board.i +%include module.i +%include plugins.i +%include units.i diff --git a/pcbnew/swig/pcbnew.i.orig b/pcbnew/swig/pcbnew.i.orig new file mode 100644 index 0000000000..e69de29bb2 diff --git a/pcbnew/swig/pcbnew.i.rej b/pcbnew/swig/pcbnew.i.rej new file mode 100644 index 0000000000..95e6fae83e --- /dev/null +++ b/pcbnew/swig/pcbnew.i.rej @@ -0,0 +1,29 @@ +--- pcbnew/scripting/pcbnew.i ++++ pcbnew/swig/pcbnew.i +@@ -87,26 +46,6 @@ class BASE_SET {}; + #include + %} + +-%include +-%include +-%include +-%include +-%include +-%include +-%include +-%include +-%include +-%include +-%include +-%include +-%include +-%include +-%include +-%include +-%include +-%include +-%include +-%include + + %include + %include diff --git a/pcbnew/scripting/pcbnew_footprint_wizards.cpp b/pcbnew/swig/pcbnew_footprint_wizards.cpp similarity index 100% rename from pcbnew/scripting/pcbnew_footprint_wizards.cpp rename to pcbnew/swig/pcbnew_footprint_wizards.cpp diff --git a/pcbnew/scripting/pcbnew_footprint_wizards.h b/pcbnew/swig/pcbnew_footprint_wizards.h similarity index 100% rename from pcbnew/scripting/pcbnew_footprint_wizards.h rename to pcbnew/swig/pcbnew_footprint_wizards.h diff --git a/pcbnew/scripting/pcbnew_scripting_helpers.cpp b/pcbnew/swig/pcbnew_scripting_helpers.cpp similarity index 100% rename from pcbnew/scripting/pcbnew_scripting_helpers.cpp rename to pcbnew/swig/pcbnew_scripting_helpers.cpp diff --git a/pcbnew/scripting/pcbnew_scripting_helpers.h b/pcbnew/swig/pcbnew_scripting_helpers.h similarity index 100% rename from pcbnew/scripting/pcbnew_scripting_helpers.h rename to pcbnew/swig/pcbnew_scripting_helpers.h diff --git a/pcbnew/scripting/plugins.i b/pcbnew/swig/plugins.i similarity index 88% rename from pcbnew/scripting/plugins.i rename to pcbnew/swig/plugins.i index 7e7dcb7a36..cff768b090 100644 --- a/pcbnew/scripting/plugins.i +++ b/pcbnew/swig/plugins.i @@ -23,13 +23,13 @@ */ %{ -#include +#include %} class PYTHON_FOOTPRINT_WIZARDS { public: - static void register_wizard(PyObject *wizard); - static void deregister_wizard(PyObject *wizard); + static void register_wizard( PyObject* wizard ); + static void deregister_wizard( PyObject* wizard ); }; diff --git a/scripting/python_scripting.cpp b/pcbnew/swig/python_scripting.cpp similarity index 100% rename from scripting/python_scripting.cpp rename to pcbnew/swig/python_scripting.cpp diff --git a/scripting/python_scripting.h b/pcbnew/swig/python_scripting.h similarity index 100% rename from scripting/python_scripting.h rename to pcbnew/swig/python_scripting.h diff --git a/pcbnew/scripting/tests/test1.py b/pcbnew/swig/tests/test1.py similarity index 100% rename from pcbnew/scripting/tests/test1.py rename to pcbnew/swig/tests/test1.py diff --git a/pcbnew/scripting/tests/test2.py b/pcbnew/swig/tests/test2.py similarity index 100% rename from pcbnew/scripting/tests/test2.py rename to pcbnew/swig/tests/test2.py diff --git a/pcbnew/scripting/units.i b/pcbnew/swig/units.i similarity index 58% rename from pcbnew/scripting/units.i rename to pcbnew/swig/units.i index 56ea213e3e..bae5edcbe7 100644 --- a/pcbnew/scripting/units.i +++ b/pcbnew/swig/units.i @@ -30,49 +30,48 @@ // Unit conversion, between internal units and mm or mils %pythoncode -{ - def ToMM(iu): - if type(iu) in [int,float]: - return float(iu) / float(IU_PER_MM) - elif type(iu) in [wxPoint,wxSize]: - return tuple(map(ToMM,iu)) +%{ + def ToMM(iu): + if type(iu) in [int,float]: + return float(iu) / float(IU_PER_MM) + elif type(iu) in [wxPoint,wxSize]: + return tuple(map(ToMM,iu)) - def FromMM(mm): - if type(mm) in [int,float]: - return int(float(mm) * float(IU_PER_MM)) - elif type(mm) in [wxPoint,wxSize]: - return tuple(map(FromMM,mm)) + def FromMM(mm): + if type(mm) in [int,float]: + return int(float(mm) * float(IU_PER_MM)) + elif type(mm) in [wxPoint,wxSize]: + return tuple(map(FromMM,mm)) - def ToMils(iu): - if type(iu) in [int,float]: - return float(iu) / float(IU_PER_MILS) - elif type(iu) in [wxPoint,wxSize]: - return tuple(map(ToMils,iu)) + def ToMils(iu): + if type(iu) in [int,float]: + return float(iu) / float(IU_PER_MILS) + elif type(iu) in [wxPoint,wxSize]: + return tuple(map(ToMils,iu)) - def FromMils(mils): - if type(mils) in [int,float]: - return int(float(mils)*float(IU_PER_MILS)) - elif type(mils) in [wxPoint,wxSize]: - return tuple(map(FromMils,mils)) + def FromMils(mils): + if type(mils) in [int,float]: + return int(float(mils)*float(IU_PER_MILS)) + elif type(mils) in [wxPoint,wxSize]: + return tuple(map(FromMils,mils)) - def wxSizeMM(mmx,mmy): return wxSize(FromMM(mmx),FromMM(mmy)) - def wxSizeMils(mmx,mmy): return wxSize(FromMils(mmx),FromMils(mmy)) + def wxSizeMM(mmx,mmy): return wxSize(FromMM(mmx),FromMM(mmy)) + def wxSizeMils(mmx,mmy): return wxSize(FromMils(mmx),FromMils(mmy)) - def wxPointMM(mmx,mmy): return wxPoint(FromMM(mmx),FromMM(mmy)) - def wxPointMils(mmx,mmy): return wxPoint(FromMils(mmx),FromMils(mmy)) + def wxPointMM(mmx,mmy): return wxPoint(FromMM(mmx),FromMM(mmy)) + def wxPointMils(mmx,mmy): return wxPoint(FromMils(mmx),FromMils(mmy)) - def wxRectMM(x,y,wx,wy): + def wxRectMM(x,y,wx,wy): x = int(FromMM(x)) y = int(FromMM(y)) wx = int(FromMM(wx)) wy = int (FromMM(wy)) return wxRect(x,y,wx,wy) - def wxRectMils(x,y,wx,wy): + def wxRectMils(x,y,wx,wy): x = int(FromMils(x)) y = int(FromMils(y)) wx = int(FromMils(wx)) wy = int (FromMils(wy)) return wxRect(x,y,wx,wy) - -} +%} diff --git a/plugins/3d/vrml/CMakeLists.txt b/plugins/3d/vrml/CMakeLists.txt index 3352417f6c..52f57846dc 100644 --- a/plugins/3d/vrml/CMakeLists.txt +++ b/plugins/3d/vrml/CMakeLists.txt @@ -25,6 +25,7 @@ include_directories( add_library( s3d_plugin_vrml MODULE ${CMAKE_SOURCE_DIR}/common/richio.cpp + ${CMAKE_SOURCE_DIR}/common/exceptions.cpp vrml.cpp x3d.cpp wrlproc.cpp