Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
K
kicad-source-mirror
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
Elphel
kicad-source-mirror
Commits
beec3236
Commit
beec3236
authored
Aug 01, 2012
by
Miguel Angel Ajo
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Double Python initialization fixed
parent
474128a4
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
304 additions
and
12 deletions
+304
-12
CMakeLists.txt
CMakeLists.txt
+10
-2
appl_wxstruct.h
include/appl_wxstruct.h
+16
-3
wxstruct.h
include/wxstruct.h
+3
-1
pcbnew.cpp
pcbnew/pcbnew.cpp
+248
-2
python_scripting.cpp
scripting/python_scripting.cpp
+26
-3
python_scripting.h
scripting/python_scripting.h
+1
-1
No files found.
CMakeLists.txt
View file @
beec3236
...
...
@@ -56,7 +56,10 @@ option(KICAD_SCRIPTING_MODULES
"set this option ON to build kicad modules that can be used from scripting languages"
)
option
(
KICAD_SCRIPTING_EXPERIMENT
"set this option ON to build Edwin's TEST code with linking to python and pycrust shell"
)
#Set version option (stable or testing)
...
...
@@ -136,7 +139,12 @@ endif(KICAD_SCRIPTING)
if
(
KICAD_SCRIPTING_MODULES
)
add_definitions
(
-DKICAD_SCRIPTING_MODULES
)
endif
(
KICAD_SCRIPTING_MODULES
)
if
(
KICAD_SCRIPTING_EXPERIMENT
)
add_definitions
(
-DKICAD_SCRIPTING_EXPERIMENT
)
endif
(
KICAD_SCRIPTING_EXPERIMENT
)
if
(
USE_WX_GRAPHICS_CONTEXT
)
add_definitions
(
-DUSE_WX_GRAPHICS_CONTEXT
)
...
...
include/appl_wxstruct.h
View file @
beec3236
...
...
@@ -36,7 +36,10 @@
#include <wx/config.h>
#include <wx/filename.h>
#include <param_config.h>
#ifdef KICAD_SCRIPTING_EXPERIMENT
#include <python2.7/Python.h>
#include <wx/wxPython/wxPython.h>
#endif
enum
EDA_APP_T
{
APP_UNKNOWN_T
,
...
...
@@ -59,6 +62,10 @@ class wxHtmlHelpController;
*/
class
EDA_APP
:
public
wxApp
{
#ifdef KICAD_SCRIPTING_EXPERIMENT
private
:
PyThreadState
*
m_mainTState
;
#endif
protected
:
/// Used mainly to handle default paths libs m_Id = APP_EESCHEMA_T, APP_PCBNEW_T ...
EDA_APP_T
m_Id
;
...
...
@@ -115,8 +122,14 @@ public:
* this is the first executed function (like main() )
* @return true if the application can be started.
*/
bool
OnInit
();
bool
OnInit
();
// should this be virtual
#ifdef KICAD_SCRIPTING_EXPERIMENT
bool
Init_wxPython
();
#endif
// This is only called if OnInit() returned true so it's a good place to do
// any cleanup matching the initializations done there.
//// virtual int OnExit() ;// { return(0) ; }; // TODO FIX THIS HACK MUST BE VIRTUAL
wxHtmlHelpController
*
GetHtmlHelpController
()
{
return
m_HtmlCtrl
;
}
void
SetHtmlHelpController
(
wxHtmlHelpController
*
aController
);
...
...
include/wxstruct.h
View file @
beec3236
...
...
@@ -470,7 +470,9 @@ public:
void
SetShowBorderAndTitleBlock
(
bool
aShow
)
{
m_showBorderAndTitleBlock
=
aShow
;
}
EDA_DRAW_PANEL
*
GetCanvas
()
{
return
m_canvas
;
}
// HACK
// EDA_MSG_PANEL* GetMessagePanel() { return m_messagePanel; }
// end hack
virtual
wxString
GetScreenDesc
();
/**
...
...
pcbnew/pcbnew.cpp
View file @
beec3236
...
...
@@ -57,6 +57,7 @@
#include <python_scripting.h>
#endif
// Colors for layers and items
COLORS_DESIGN_SETTINGS
g_ColorsSettings
;
...
...
@@ -87,6 +88,7 @@ wxString g_DocModulesFileName = wxT( "footprints_doc/footprints.pdf" );
wxArrayString
g_LibraryNames
;
// wxWindow* DoPythonStuff(wxWindow* parent); // declaration
IMPLEMENT_APP
(
EDA_APP
)
...
...
@@ -105,6 +107,33 @@ void EDA_APP::MacOpenFile( const wxString& fileName )
frame
->
LoadOnePcbFile
(
fileName
,
false
);
}
#ifdef KICAD_SCRIPTING_EXPERIMENT
class
MyFrame
:
public
wxFrame
{
public
:
MyFrame
(
const
wxString
&
title
,
const
wxPoint
&
pos
,
const
wxSize
&
size
);
void
RedirectStdio
();
wxWindow
*
DoPythonStuff
(
wxWindow
*
parent
);
void
OnExit
(
wxCommandEvent
&
event
);
void
OnPyFrame
(
wxCommandEvent
&
event
);
void
ScriptingSetPcbEditFrame
(
PCB_EDIT_FRAME
*
aPCBEdaFrame
);
private
:
DECLARE_EVENT_TABLE
()
PCB_EDIT_FRAME
*
PcbEditFrame
;
};
enum
{
ID_EXIT
=
1001
,
ID_PYFRAME
};
BEGIN_EVENT_TABLE
(
MyFrame
,
wxFrame
)
EVT_MENU
(
ID_EXIT
,
MyFrame
::
OnExit
)
EVT_MENU
(
ID_PYFRAME
,
MyFrame
::
OnPyFrame
)
END_EVENT_TABLE
()
#endif
bool
EDA_APP
::
OnInit
()
{
...
...
@@ -112,10 +141,16 @@ bool EDA_APP::OnInit()
PCB_EDIT_FRAME
*
frame
=
NULL
;
#ifdef KICAD_SCRIPTING
pcbnewInitPythonScripting
();
if
(
!
pcbnewInitPythonScripting
(
&
m_mainTState
)
)
{
return
false
;
}
#endif
#ifdef KICAD_SCRIPTING_EXPERIMENT
MyFrame
*
zz
=
new
MyFrame
(
_T
(
"Embedded wxPython Test"
),
wxDefaultPosition
,
wxSize
(
700
,
600
));
zz
->
Show
(
true
);
#endif
InitEDA_Appl
(
wxT
(
"Pcbnew"
),
APP_PCBNEW_T
);
if
(
m_Checker
&&
m_Checker
->
IsAnotherRunning
()
)
...
...
@@ -209,6 +244,217 @@ Changing extension to .brd." ), GetChars( fn.GetFullPath() ) );
*/
frame
->
SetFocus
();
frame
->
GetCanvas
()
->
SetFocus
();
#ifdef KICAD_SCRIPTING_EXPERIMENT
zz
->
ScriptingSetPcbEditFrame
(
frame
);
// make the frame available to my python thing
// now to find a way to use it for something useful
#endif
return
true
;
}
#if 0
// for some reason KiCad classes do not implement OnExit
// if I add it in the declaration, I need to fix it in every application
// so for now make a note TODO TODO
// we need to clean up python when the application exits
int EDA_APP::OnExit() {
// Restore the thread state and tell Python to cleanup after itself.
// wxPython will do its own cleanup as part of that process. This is done
// in OnExit instead of ~MyApp because OnExit is only called if OnInit is
// successful.
#if KICAD_SCRIPTING_EXPERIMENT
wxPyEndAllowThreads(m_mainTState);
Py_Finalize();
#endif
return 0;
}
#endif
#ifdef KICAD_SCRIPTING_EXPERIMENT
// stuff copied from WxPython examples
bool
EDA_APP
::
Init_wxPython
()
{
// Initialize Python
Py_Initialize
();
PyEval_InitThreads
();
// Load the wxPython core API. Imports the wx._core_ module and sets a
// local pointer to a function table located there. The pointer is used
// internally by the rest of the API functions.
if
(
!
wxPyCoreAPI_IMPORT
()
)
{
wxLogError
(
wxT
(
"***** Error importing the wxPython API! *****"
));
PyErr_Print
();
Py_Finalize
();
return
false
;
}
// Save the current Python thread state and release the
// Global Interpreter Lock.
m_mainTState
=
wxPyBeginAllowThreads
();
return
true
;
}
//
MyFrame
::
MyFrame
(
const
wxString
&
title
,
const
wxPoint
&
pos
,
const
wxSize
&
size
)
:
wxFrame
(
NULL
,
-
1
,
title
,
pos
,
size
,
wxDEFAULT_FRAME_STYLE
|
wxNO_FULL_REPAINT_ON_RESIZE
)
{
// SetIcon(wxICON(mondrian));
wxMenuBar
*
mbar
=
new
wxMenuBar
;
wxMenu
*
menu
=
new
wxMenu
;
menu
->
Append
(
ID_PYFRAME
,
_T
(
"Make wx&Python frame"
));
menu
->
AppendSeparator
();
menu
->
Append
(
ID_EXIT
,
_T
(
"&Close Frame
\t
Alt-X"
));
mbar
->
Append
(
menu
,
_T
(
"&File"
));
SetMenuBar
(
mbar
);
CreateStatusBar
();
RedirectStdio
();
// Make some child windows from C++
wxSplitterWindow
*
sp
=
new
wxSplitterWindow
(
this
,
-
1
);
wxPanel
*
p1
=
new
wxPanel
(
sp
,
-
1
,
wxDefaultPosition
,
wxDefaultSize
,
wxSUNKEN_BORDER
);
new
wxStaticText
(
p1
,
-
1
,
_T
(
"The frame, menu, splitter, this panel and this text were created in C++..."
),
wxPoint
(
10
,
10
));
// And get a panel from Python
wxWindow
*
p2
=
DoPythonStuff
(
sp
);
if
(
p2
)
sp
->
SplitHorizontally
(
p1
,
p2
,
GetClientSize
().
y
/
4
);
}
void
MyFrame
::
OnExit
(
wxCommandEvent
&
event
)
{
Close
();
}
void
MyFrame
::
ScriptingSetPcbEditFrame
(
PCB_EDIT_FRAME
*
aPCBEdaFrame
)
{
PcbEditFrame
=
aPCBEdaFrame
;
}
//----------------------------------------------------------------------
// This is where the fun begins...
const
char
*
python_code1
=
"\
import wx
\n
\
f = wx.Frame(None, -1, 'Hello from wxPython!', size=(250, 150))
\n
\
f.Show()
\n
\
"
;
void
MyFrame
::
OnPyFrame
(
wxCommandEvent
&
event
)
{
// For simple Python code that doesn't have to interact with the
// C++ code in any way, you can execute it with PyRun_SimpleString.
// First, whenever you do anything with Python objects or code, you
// *MUST* aquire the Global Interpreter Lock and block other
// Python threads from running.
wxPyBlock_t
blocked
=
wxPyBeginBlockThreads
();
// Execute the code in the __main__ module
PyRun_SimpleString
(
python_code1
);
// Finally, release the GIL and let other Python threads run.
wxPyEndBlockThreads
(
blocked
);
}
void
MyFrame
::
RedirectStdio
()
{
// This is a helpful little tidbit to help debugging and such. It
// redirects Python's stdout and stderr to a window that will popup
// only on demand when something is printed, like a traceback.
const
char
*
python_redirect
=
"import sys
\n
\
import wx
\n
\
output = wx.PyOnDemandOutputWindow()
\n
\
sys.stdin = sys.stderr = output
\n
"
;
wxPyBlock_t
blocked
=
wxPyBeginBlockThreads
();
PyRun_SimpleString
(
python_redirect
);
wxPyEndBlockThreads
(
blocked
);
}
const
char
*
python_code2
=
"\
import sys
\n
import os
\n
\
sys.path.append(os.path.expanduser('~/.kicad_plugins'))
\n
\
import embedded_sample
\n
\
\n
\
def makeWindow(parent):
\n
\
win = embedded_sample.MyPanel(parent)
\n
\
return win
\n
\
"
;
wxWindow
*
MyFrame
::
DoPythonStuff
(
wxWindow
*
parent
)
{
// More complex embedded situations will require passing C++ objects to
// Python and/or returning objects from Python to be used in C++. This
// sample shows one way to do it. NOTE: The above code could just have
// easily come from a file, or the whole thing could be in the Python
// module that is imported and manipulated directly in this C++ code. See
// the Python API for more details.
wxWindow
*
window
=
NULL
;
PyObject
*
result
;
// As always, first grab the GIL
wxPyBlock_t
blocked
=
wxPyBeginBlockThreads
();
// Now make a dictionary to serve as the global namespace when the code is
// executed. Put a reference to the builtins module in it. (Yes, the
// names are supposed to be different, I don't know why...)
PyObject
*
globals
=
PyDict_New
();
PyObject
*
builtins
=
PyImport_ImportModule
(
"__builtin__"
);
PyDict_SetItemString
(
globals
,
"__builtins__"
,
builtins
);
Py_DECREF
(
builtins
);
// Execute the code to make the makeWindow function
result
=
PyRun_String
(
python_code2
,
Py_file_input
,
globals
,
globals
);
// Was there an exception?
if
(
!
result
)
{
PyErr_Print
();
wxPyEndBlockThreads
(
blocked
);
return
NULL
;
}
Py_DECREF
(
result
);
// Now there should be an object named 'makeWindow' in the dictionary that
// we can grab a pointer to:
PyObject
*
func
=
PyDict_GetItemString
(
globals
,
"makeWindow"
);
wxASSERT
(
PyCallable_Check
(
func
));
// Now build an argument tuple and call the Python function. Notice the
// use of another wxPython API to take a wxWindows object and build a
// wxPython object that wraps it.
PyObject
*
arg
=
wxPyMake_wxObject
(
parent
,
false
);
wxASSERT
(
arg
!=
NULL
);
PyObject
*
tuple
=
PyTuple_New
(
1
);
PyTuple_SET_ITEM
(
tuple
,
0
,
arg
);
result
=
PyEval_CallObject
(
func
,
tuple
);
// Was there an exception?
if
(
!
result
)
PyErr_Print
();
else
{
// Otherwise, get the returned window out of Python-land and
// into C++-ville...
bool
success
=
wxPyConvertSwigPtr
(
result
,
(
void
**
)
&
window
,
_T
(
"wxWindow"
));
wxASSERT_MSG
(
success
,
_T
(
"Returned object was not a wxWindow!"
));
Py_DECREF
(
result
);
}
// Release the python objects we still have
Py_DECREF
(
globals
);
Py_DECREF
(
tuple
);
// Finally, after all Python stuff is done, release the GIL
wxPyEndBlockThreads
(
blocked
);
return
window
;
}
#endif
scripting/python_scripting.cpp
View file @
beec3236
...
...
@@ -28,6 +28,7 @@
*/
#include <python_scripting.h>
#include <wx/wxPython/wxPython.h>
#include <stdlib.h>
#include <string.h>
...
...
@@ -37,7 +38,7 @@ extern "C" void init_kicad( void );
extern
"C"
void
init_pcbnew
(
void
);
#define EXTRA_PYTHON_MODULES
2
// this is the number of python
#define EXTRA_PYTHON_MODULES
10
// this is the number of python
// modules that we want to add into the list
...
...
@@ -112,21 +113,43 @@ static void swigSwitchPythonBuiltin()
/* Function pcbnewInitPythonScripting
* Initializes all the python environment and publish our interface inside it
* initializes all the wxpython interface, and returns the python thread control structure
*
*/
void
pcbnewInitPythonScripting
(
)
bool
pcbnewInitPythonScripting
(
PyThreadState
**
aMainTState
)
{
swigAddBuiltin
();
// add builtin functions
swigAddModules
();
// add our own modules
swigSwitchPythonBuiltin
();
// switch the python builtin modules to our new list
Py_Initialize
();
// call the python library to get it initialized
Py_Initialize
();
PyEval_InitThreads
();
// Load the wxPython core API. Imports the wx._core_ module and sets a
// local pointer to a function table located there. The pointer is used
// internally by the rest of the API functions.
if
(
!
wxPyCoreAPI_IMPORT
()
)
{
wxLogError
(
wxT
(
"***** Error importing the wxPython API! *****"
));
PyErr_Print
();
Py_Finalize
();
return
false
;
}
// Save the current Python thread state and release the
// Global Interpreter Lock.
*
aMainTState
=
wxPyBeginAllowThreads
();
// load pcbnew inside python, and load all the user plugins, TODO: add system wide plugins
wxPyBlock_t
blocked
=
wxPyBeginBlockThreads
();
PyRun_SimpleString
(
"import sys
\n
"
"sys.path.append(
\"
.
\"
)
\n
"
"import pcbnew
\n
"
"pcbnew.LoadPlugins()"
);
wxPyEndBlockThreads
(
blocked
);
return
true
;
}
scripting/python_scripting.h
View file @
beec3236
...
...
@@ -7,6 +7,6 @@
* Initializes the Python engine inside pcbnew
*/
void
pcbnewInitPythonScripting
(
void
);
bool
pcbnewInitPythonScripting
(
PyThreadState
**
aMainTState
);
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment