← Back to team overview

kicad-developers team mailing list archive

Re: Fwd: Python plugin for pcbnew

 

Hi,

For starting I had implement your b) option. For that I start from a copy
of guthub plugin. So I add options in all
needed files (CMakeLists.txt..), I had create a directory on pcbnew and put
the code inside and an example.

Out of this directory I had done some small changes:
scripting/python_scripting.h
=> Adding global value g_PythonMainTState as extern (needed for python
locks)
pcbnew/plugin.cpp
=> move python_footprint_plugin option to my plugin (as comment suggest). I
hope it's ok.
pcbnew/io_mgr.h
pcbnew/io_mgr.cpp
=> Declare my plugin on lists

On the new directory:

pcbnew/fppython/fppython_example.py
A plugin example.
It's a really basic:
 - 2 statics foot prints
 - footprint himself are hardcoded on the example
 - fake save/delete

pcbnew/fppython/fppython_plugin.(cpp|h)
The plugin himself

To use is:
- add a new footprint lib entry,
- specify the directory where the plugin is as library path
- specify python_footprint_plugin option as the plugin name (without .py,
for example fppython_example)

Some limitations I found inside the core to allow more feature for plugins:
- IsFootprintLibWritable don't have a PROPERTY parameter. So since the
plugin module name is inside this, I'm unable to load
the right python module to let it handle this method
- FootprintLibOptions: Same issue. So the plugin can't provide a list of
parameters needed for his own usage. To work arround this
I hard code 4 parameters (fppython_parameter[1-4]) but it is not
beautiful...

I hope it can help... After this, I plan to create a more advanced python
plugin


Tell me...

Regards


2014-03-08 17:08 GMT+01:00 Dick Hollenbeck <dick@xxxxxxxxxxx>:

> RE: FootprintLoad()
>
> There are two ways you could go:
>
> a) use swig functions on class MODULE and add features that way, one by
> one in python.
> Return the MODULE when you are done "loading" the footprint.
>
>
> b) construct a pretty string, return that to C++ land but still within
> your adapter, i.e.
> still inside ADAPTER::FootprintLoad(), before returning from that C++
> function.  Then
> while in there PCB_IO::Parse() the pretty string and return the
> constructed MODULE coming
> back from the Parse() function.
>
>
> This latter path, b) was what I was thinking for the SWEET support, and
> you can see that
> its API is different from PLUGIN.  It returned SWEET strings on part
> loading.  That was to
> support SWEET's inheritance model.
>
>
> Dick
>
>
> _______________________________________________
> Mailing list: https://launchpad.net/~kicad-developers
> Post to     : kicad-developers@xxxxxxxxxxxxxxxxxxx
> Unsubscribe : https://launchpad.net/~kicad-developers
> More help   : https://help.launchpad.net/ListHelp
>
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt	2014-02-24 01:02:41 +0000
+++ CMakeLists.txt	2014-03-09 08:19:50 +0000
@@ -83,6 +83,8 @@
 
 option( BUILD_GITHUB_PLUGIN "Build the GITHUB_PLUGIN for pcbnew." OFF )
 
+option( BUILD_FPPYTHON_PLUGIN "Build the FPPYTHON_PLUGIN for pcbnew." OFF )
+
 # This can be set to a custom name to brag about a particular branch in the "About" dialog:
 set( KICAD_REPO_NAME "product" CACHE STRING "Name of the tree from which this build came." )
 

=== modified file 'CMakeModules/config.h.cmake'
--- CMakeModules/config.h.cmake	2014-02-03 19:26:18 +0000
+++ CMakeModules/config.h.cmake	2014-03-08 08:51:17 +0000
@@ -67,6 +67,9 @@
 /// When defined, build the GITHUB_PLUGIN for pcbnew.
 #cmakedefine BUILD_GITHUB_PLUGIN
 
+/// When defined, build the FPPYTHON_PLUGIN for pcbnew.
+#cmakedefine BUILD_FPPYTHON_PLUGIN
+
 /// When defined, use KIWAY and KIFACE DSOs
 #cmakedefine USE_KIWAY_DLLS
 

=== modified file 'Documentation/compiling/build-config.txt'
--- Documentation/compiling/build-config.txt	2014-02-22 23:17:36 +0000
+++ Documentation/compiling/build-config.txt	2014-03-09 09:28:13 +0000
@@ -212,6 +212,13 @@
 This option enables or disables building KiCad with a pcbnew plugin for loading
 footprints from a GitHub repository.
 
+BUILD_FPPYTHON_PLUGIN (ON/OFF)
+----------------------------
+Default: OFF
+
+This option enables or disables building KiCad with a pcbnew plugin for loading
+footprints from a python module.
+
 
 KICAD_REPO_NAME (STRING)
 ------------------------

=== modified file 'pcbnew/CMakeLists.txt'
--- pcbnew/CMakeLists.txt	2014-02-27 22:56:16 +0000
+++ pcbnew/CMakeLists.txt	2014-03-09 08:23:14 +0000
@@ -364,6 +364,10 @@
     set( GITHUB_PLUGIN_LIBRARIES github_plugin )
 endif()
 
+if( BUILD_FPPYTHON_PLUGIN )
+    set( FPPYTHON_PLUGIN_LIBRARIES fppython_plugin )
+endif()
+
 if( ( KICAD_SCRIPTING OR KICAD_SCRIPTING_MODULES ) AND NOT WIN32 AND NOT APPLE )
     list( APPEND PCBNEW_EXTRA_LIBS rt )
 endif()
@@ -384,6 +388,7 @@
         pcad2kicadpcb
         lib_dxf
         ${GITHUB_PLUGIN_LIBRARIES}
+        ${FPPYTHON_PLUGIN_LIBRARIES}
         polygon
         bitmaps
         gal
@@ -520,6 +525,11 @@
     add_dependencies( github_plugin lib-dependencies )
 endif()
 
+if( BUILD_FPPYTHON_PLUGIN )
+    add_subdirectory( fppython )
+    add_dependencies( fppython_plugin lib-dependencies )
+endif()
+
 
 ###
 # Create the pcbnew executable
@@ -554,6 +564,7 @@
     gal
     lib_dxf
     ${GITHUB_PLUGIN_LIBRARIES}
+    ${FPPYTHON_PLUGIN_LIBRARIES}
     ${wxWidgets_LIBRARIES}
     ${OPENGL_LIBRARIES}
     ${GDI_PLUS_LIBRARIES}

=== added directory 'pcbnew/fppython'
=== added file 'pcbnew/fppython/CMakeLists.txt'
--- pcbnew/fppython/CMakeLists.txt	1970-01-01 00:00:00 +0000
+++ pcbnew/fppython/CMakeLists.txt	2014-03-07 16:38:44 +0000
@@ -0,0 +1,50 @@
+#  This program source code file is part of KICAD, a free EDA CAD application.
+#
+#  Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@xxxxxxxxxxx>
+#  Copyright (C) 2013 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
+
+
+
+# tone down the compiler warnings for avhttp header library:
+set( FPPYTHON_PLUGIN_SRCS
+    fppython_plugin.cpp
+    )
+
+add_library( fppython_plugin
+    fppython_plugin.cpp
+    )
+
+include_directories( . ${OPENSSL_INCLUDE_DIR} ${AVHTTP_INCLUDE_DIR} )
+
+# No, you don't get fppython without boost and openssl. Boost_LIBRARIES now moved up
+# into CMakeLists.txt for pcbnew and cvpcb:
+target_link_libraries( fppython_plugin
+    ${OPENSSL_LIBRARIES}
+    )
+
+if( MINGW )
+    target_link_libraries( fppython_plugin
+        ${wxWidgets_LIBRARIES}
+        ws2_32
+        )
+endif()
+
+add_dependencies( fppython_plugin boost )
+

=== added file 'pcbnew/fppython/fppython_example.py'
--- pcbnew/fppython/fppython_example.py	1970-01-01 00:00:00 +0000
+++ pcbnew/fppython/fppython_example.py	2014-03-09 09:54:27 +0000
@@ -0,0 +1,80 @@
+#!/usr/bin/python
+#
+# Example for a basic python library plugin
+#
+#
+
+#
+# Enumerate available footprint
+#
+# Must be implemented. Return a python list of strings corresponding
+# to the footprint name
+#
+# @param params parameters of the plugin. It's a dict type
+# @return python string list of footprint name
+def FootprintEnumerate(params):
+    print "toto"
+    print params
+    return ['testfp1','testfp2']
+
+
+#
+# Load a footprint
+#
+# Must be implemented. Return a string test corresponding to the s-expression
+# of the footprint (the pretty format)
+#
+# @param fp_name is the name of footprint
+# @param params parameters of the plugin. It's a dict type
+# @return the footprint (string in s-expression)
+def FootprintLoad(fp_name,params):
+    a = """
+(module Relay_SSOP4 (layer F.Cu)
+  (fp_text reference OC1 (at -0.65024 2.54762) (layer F.SilkS)
+    (effects (font (thickness 0.3048)))
+  )
+  (fp_text value PS2801-1-K (at 0 4.8006) (layer F.SilkS) hide
+    (effects (font (thickness 0.3048)))
+  )
+  (fp_circle (center -1.99898 -0.89916) (end -1.95072 -0.89916) (layer F.SilkS) (width 0.20066))
+  (fp_line (start -2.4003 -1.30048) (end 2.4003 -1.30048) (layer F.SilkS) (width 0.20066))
+  (fp_line (start 2.4003 -1.30048) (end 2.4003 1.30048) (layer F.SilkS) (width 0.20066))
+  (fp_line (start 2.4003 1.30048) (end -2.3495 1.30048) (layer F.SilkS) (width 0.20066))
+  (fp_line (start -2.3495 1.30048) (end -2.4003 1.30048) (layer F.SilkS) (width 0.20066))
+  (fp_line (start -2.4003 1.30048) (end -2.4003 -1.30048) (layer F.SilkS) (width 0.20066))
+  (pad 1 smd rect (at -3.2512 -0.65024) (size 1.50114 0.59944) (layers F.Cu F.Paste F.Mask))
+  (pad 2 smd rect (at -3.2512 0.65024) (size 1.50114 0.59944) (layers F.Cu F.Paste F.Mask))
+  (pad 3 smd rect (at 3.2512 0.65024) (size 1.50114 0.59944) (layers F.Cu F.Paste F.Mask))
+  (pad 4 smd rect (at 3.2512 -0.65024) (size 1.50114 0.59944) (layers F.Cu F.Paste F.Mask))
+)
+"""
+    return a
+
+
+#
+# Delete a footprint
+#
+# Should be implemented.
+#
+# @param fp_name is the name of footprint
+# @param params parameters of the plugin. It's a dict type
+# @return boolean for success operation
+def FootprintDelete(fp_name,params):
+    print "Try to delete %s\n"%(fp_name)
+    if 'testfp1' == fp_name:
+        return True
+    else:
+        return False
+
+#
+# Save a footprint
+#
+# Should be implemented.
+#
+# @param fp_name is the name of footprint
+# @param module_txt a string already formatted as a footprint (s-expression)
+# @param params parameters of the plugin. It's a dict type
+# @return boolean for success operation
+def FootprintSave(fp_name,module_txt,params):
+    print "Try to save %s (%s)\n"%(fp_name,module_txt)
+    return True

=== added file 'pcbnew/fppython/fppython_plugin.cpp'
--- pcbnew/fppython/fppython_plugin.cpp	1970-01-01 00:00:00 +0000
+++ pcbnew/fppython/fppython_plugin.cpp	2014-03-09 09:55:27 +0000
@@ -0,0 +1,371 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@xxxxxxxxxxx>
+ * Copyright (C) 2013 KiCad Developers, see CHANGELOG.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
+ */
+
+#include <Python.h>
+#include <io_mgr.h>
+#include <fppython_plugin.h>
+#include <pcb_parser.h>
+#include <macros.h>
+#include <class_module.h>
+
+#include <python_scripting.h>
+
+using namespace std;
+
+
+FPPYTHON_PLUGIN::FPPYTHON_PLUGIN()
+{
+    m_parser =  new PCB_PARSER();
+    // init todo
+}
+
+
+FPPYTHON_PLUGIN::~FPPYTHON_PLUGIN()
+{
+    delete m_parser;
+}
+
+
+const wxString FPPYTHON_PLUGIN::PluginName() const
+{
+    return wxT( "FpPython" );
+}
+
+
+const wxString FPPYTHON_PLUGIN::GetFileExtension() const
+{
+    return wxEmptyString;
+}
+
+
+PyObject *FPPYTHON_PLUGIN::buildParams(const PROPERTIES* aProperties )
+{
+    PyObject *pArgs = NULL;
+    if (aProperties != NULL) {
+        pArgs = PyDict_New();
+        for( PROPERTIES::const_iterator it = aProperties->begin();  it != aProperties->end();  ++it )
+            {
+                PyDict_SetItem(pArgs,
+                               PyString_FromString(it->first.c_str()),
+                               PyString_FromString(it->second.c_str()));
+            }
+    }
+    return pArgs;
+}
+
+PyObject *FPPYTHON_PLUGIN::prepareCall(const char *aFunctionName,
+                                       const wxString& aLibraryPath,
+                                       const PROPERTIES* aProperties)
+{
+    PyObject *pName, *pModule, *pFunc;
+
+    UTF8 fpName;
+    if (aProperties == NULL || !(aProperties->Value("python_footprint_plugin",&fpName)))
+    {
+        THROW_IO_ERROR( _("Configuration error: missing python_footprint_plugin option (module name)") );
+        return NULL; // NOP...
+    }
+
+    PyEval_AcquireThread(g_PythonMainTState);
+    wxString cmd;
+    cmd.Append(UTF8("import sys; sys.path.append(\""));
+    cmd.Append(aLibraryPath);
+    cmd.Append(UTF8("\")\n"));
+    PyRun_SimpleString(UTF8(cmd));
+    pName = PyString_FromString(UTF8(fpName));
+    if( pName == NULL )
+    {
+        PyEval_ReleaseThread(g_PythonMainTState);
+        THROW_IO_ERROR( _("Error on string...") );
+        return NULL;// NOP...
+    }
+
+    pModule = PyImport_Import(pName);
+    Py_DECREF(pName);
+    if( pModule == NULL )
+    {
+        PyEval_ReleaseThread(g_PythonMainTState);
+        THROW_IO_ERROR( _("Unable to find module") );
+    }
+    pFunc = PyObject_GetAttrString(pModule, aFunctionName);
+    if( !(pFunc && PyCallable_Check(pFunc)) )
+    {
+        Py_XDECREF(pFunc);
+        Py_DECREF(pModule);
+        PyEval_ReleaseThread(g_PythonMainTState);
+        THROW_IO_ERROR( _("Unable to find Footprint function"));
+    }
+
+    Py_DECREF(pModule);
+
+    return pFunc;
+}
+
+wxArrayString FPPYTHON_PLUGIN::FootprintEnumerate(
+        const wxString& aLibraryPath, const PROPERTIES* aProperties )
+{
+    PyObject *pArgs;
+    PyObject *pValue;
+
+#ifdef KICAD_SCRIPTING
+
+    PyObject *pFunc = prepareCall("FootprintEnumerate",aLibraryPath,aProperties);
+
+    pArgs = PyTuple_New(1);
+    PyTuple_SetItem(pArgs, 0, buildParams(aProperties));
+    pValue = PyObject_CallObject(pFunc,pArgs); // pArgs
+    Py_DECREF(pArgs);
+    Py_DECREF(pFunc);
+    if( pValue != NULL )
+    {
+        if( PyObject_TypeCheck(pValue,&PyList_Type) )
+        {
+            wxArrayString ret = PyArrayStringToWx(pValue );
+            Py_DECREF(pValue);
+            PyEval_ReleaseThread(g_PythonMainTState);
+            return ret;
+        }
+        else
+        {
+            Py_DECREF(pValue);
+            PyEval_ReleaseThread(g_PythonMainTState);
+            THROW_IO_ERROR( _("Invalid return type for FootprintEnumerate") );
+        }
+    }
+    else
+    {
+        PyEval_ReleaseThread(g_PythonMainTState);
+        THROW_IO_ERROR( _("Null type for FootprintEnumerate: invalid function") );
+    }
+
+#endif
+    wxArrayString ret;
+    return ret;
+}
+
+
+MODULE* FPPYTHON_PLUGIN::FootprintLoad( const wxString& aLibraryPath,
+        const wxString& aFootprintName, const PROPERTIES* aProperties )
+{
+    PyObject *pArgs, *pValue;
+
+#ifdef KICAD_SCRIPTING
+    // Getting python module name to use
+
+
+    PyObject *pFunc = prepareCall("FootprintLoad",aLibraryPath,aProperties);
+
+    pArgs = PyTuple_New(2);
+    PyTuple_SetItem(pArgs, 0, PyString_FromString(TO_UTF8(aFootprintName)));
+    PyTuple_SetItem(pArgs, 1, buildParams(aProperties));
+
+    pValue = PyObject_CallObject(pFunc,pArgs); // pArgs
+    Py_DECREF(pArgs);
+    Py_DECREF(pFunc);
+    if( pValue != NULL )
+    {
+        if( PyObject_TypeCheck(pValue,&PyString_Type))
+        {
+            STRING_LINE_READER  reader( PyString_AsString(pValue), wxT( "clipboard" ) );
+            m_parser->SetLineReader( &reader );
+            MODULE*     footprint = (MODULE*) m_parser->Parse();
+            Py_DECREF(pValue);
+            PyEval_ReleaseThread(g_PythonMainTState);
+            return footprint;
+        }
+        else
+        {
+            Py_DECREF(pValue);
+            PyEval_ReleaseThread(g_PythonMainTState);
+            THROW_IO_ERROR( _("Invalid return type for FootprintLoad") );
+        }
+    }
+    else
+    {
+        PyEval_ReleaseThread(g_PythonMainTState);
+        THROW_IO_ERROR( _("Null type for FootprintLoad") );
+    }
+
+
+#endif
+    return NULL;
+}
+
+
+bool FPPYTHON_PLUGIN::IsFootprintLibWritable( const wxString& aLibraryPath )
+{
+    // Alway return true since we don't have aProperties to know the module name...
+    // The module should manage himself on save/delete functions...
+    return true;
+}
+
+
+void FPPYTHON_PLUGIN::FootprintSave( const wxString& aLibraryPath,
+        const MODULE* aFootprint, const PROPERTIES* aProperties )
+{
+
+    PyObject *pArgs, *pValue;
+
+#ifdef KICAD_SCRIPTING
+    // Getting python module name to use
+
+
+    PyObject *pFunc = prepareCall("FootprintSave",aLibraryPath,aProperties);
+
+    STRING_FORMATTER stf;
+    SetOutputFormatter((OUTPUTFORMATTER*) &stf);
+    Format((BOARD_ITEM*) aFootprint,1);
+
+    pArgs = PyTuple_New(3);
+    PyTuple_SetItem(pArgs, 0, PyString_FromString(((aFootprint->GetFPID()).Format() ).c_str()));
+    PyTuple_SetItem(pArgs, 1, PyString_FromString(stf.GetString().c_str()));
+    PyTuple_SetItem(pArgs, 2, buildParams(aProperties));
+
+
+    pValue = PyObject_CallObject(pFunc,pArgs); // pArgs
+    Py_DECREF(pArgs);
+    Py_DECREF(pFunc);
+    if( pValue != NULL )
+    {
+        if( PyObject_TypeCheck(pValue,&PyBool_Type))
+        {
+            if( PyInt_AsLong(pValue) )
+            {
+                Py_DECREF(pValue);
+                PyEval_ReleaseThread(g_PythonMainTState);
+                return ;
+            }
+            else
+            {
+                Py_DECREF(pValue);
+                PyEval_ReleaseThread(g_PythonMainTState);
+                THROW_IO_ERROR( _("Unable to save footprint") );
+            }
+        }
+        else
+        {
+            Py_DECREF(pValue);
+            PyEval_ReleaseThread(g_PythonMainTState);
+            THROW_IO_ERROR( _("Invalid return type for FootprintSave") );
+        }
+    }
+    else
+    {
+        PyEval_ReleaseThread(g_PythonMainTState);
+        THROW_IO_ERROR( _("Null type for FootprintSave") );
+    }
+
+
+#endif
+
+}
+
+
+void FPPYTHON_PLUGIN::FootprintDelete( const wxString& aLibraryPath,
+                                       const wxString& aFootprintName,
+                                       const PROPERTIES* aProperties )
+{
+    PyObject *pArgs, *pValue;
+
+#ifdef KICAD_SCRIPTING
+    // Getting python module name to use
+
+
+    PyObject *pFunc = prepareCall("FootprintDelete",aLibraryPath,aProperties);
+
+    pArgs = PyTuple_New(2);
+    PyTuple_SetItem(pArgs, 0, PyString_FromString(TO_UTF8(aFootprintName)));
+    PyTuple_SetItem(pArgs, 1, buildParams(aProperties));
+
+    pValue = PyObject_CallObject(pFunc,pArgs); // pArgs
+    Py_DECREF(pArgs);
+    Py_DECREF(pFunc);
+    if( pValue != NULL )
+    {
+        if( PyObject_TypeCheck(pValue,&PyBool_Type))
+        {
+            if( PyInt_AsLong(pValue) )
+            {
+                Py_DECREF(pValue);
+                PyEval_ReleaseThread(g_PythonMainTState);
+                return ;
+            } else
+            {
+                Py_DECREF(pValue);
+                PyEval_ReleaseThread(g_PythonMainTState);
+                THROW_IO_ERROR( _("Unable to delete footprint") );
+            }
+        }
+        else
+        {
+            Py_DECREF(pValue);
+            PyEval_ReleaseThread(g_PythonMainTState);
+            THROW_IO_ERROR( _("Invalid return type for FootprintDelete") );
+        }
+    }
+    else
+    {
+        PyEval_ReleaseThread(g_PythonMainTState);
+        THROW_IO_ERROR( _("Null type for FootprintDelete") );
+    }
+
+
+#endif
+
+}
+
+
+
+void FPPYTHON_PLUGIN::FootprintLibOptions( PROPERTIES* aListToAppendTo ) const
+{
+
+    // inherit options supported by all PLUGINs.
+    PLUGIN::FootprintLibOptions( aListToAppendTo );
+
+    // Suitable for a C++ to python PLUGIN::Footprint*() adapter, moved to the adapter...
+    (*aListToAppendTo)["python_footprint_plugin"] = UTF8( _(
+        "Enter the python module which implements the PLUGIN::Footprint*() functions."
+        ));
+
+    (*aListToAppendTo)["fppython_parameter1"] = UTF8( _(
+        "Parameter 1 for python plugin"
+        ));
+    (*aListToAppendTo)["fppython_parameter2"] = UTF8( _(
+        "Parameter 2 for python plugin"
+        ));
+    (*aListToAppendTo)["fppython_parameter3"] = UTF8( _(
+        "Parameter 3 for python plugin"
+        ));
+    (*aListToAppendTo)["fppython_parameter4"] = UTF8( _(
+        "Parameter 4 for python plugin"
+        ));
+}
+
+
+
+
+
+
+
+

=== added file 'pcbnew/fppython/fppython_plugin.h'
--- pcbnew/fppython/fppython_plugin.h	1970-01-01 00:00:00 +0000
+++ pcbnew/fppython/fppython_plugin.h	2014-03-09 09:29:38 +0000
@@ -0,0 +1,81 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@xxxxxxxxxxx>
+ * Copyright (C) 2013 KiCad Developers, see CHANGELOG.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
+ */
+
+#ifndef FPPYTHON_PLUGIN_H_
+#define FPPYTHON_PLUGIN_H_
+
+#include <kicad_plugin.h>
+#include <Python.h>
+
+/**
+ * Class FPPYTHON_PLUGIN
+ * is a plugin for loading python plugins
+ *
+ * Extend @PLUGIN class and implement a wrapper to a footprint library manager
+ * written in python. A python class example is in fppython_example.py
+ *
+ *
+ */
+
+class FPPYTHON_PLUGIN : public PCB_IO
+{
+public:
+    //-----<PLUGIN API>----------------------------------------------------------
+    const wxString PluginName() const;
+
+    const wxString GetFileExtension() const;
+
+    wxArrayString FootprintEnumerate( const wxString& aLibraryPath,
+            const PROPERTIES* aProperties = NULL );
+
+    MODULE* FootprintLoad( const wxString& aLibraryPath,
+            const wxString& aFootprintName, const PROPERTIES* aProperties );
+
+    void FootprintSave( const wxString& aLibraryPath, const MODULE* aFootprint,
+            const PROPERTIES* aProperties = NULL );
+
+    void FootprintDelete( const wxString& aLibraryPath, const wxString& aFootprintName,
+            const PROPERTIES* aProperties = NULL );
+
+    bool IsFootprintLibWritable( const wxString& aLibraryPath );
+
+    void FootprintLibOptions( PROPERTIES* aListToAppendTo ) const;
+
+    //-----</PLUGIN API>---------------------------------------------------------
+
+    FPPYTHON_PLUGIN();        // constructor, if any, must be zero arg
+    ~FPPYTHON_PLUGIN();
+ private:
+    PCB_PARSER*   m_parser;
+
+    /// build parameters of the lib as expected format for python
+    PyObject *buildParams(const PROPERTIES* aProperties );
+
+    /// prepare the call of a python function (various checks, loading of python module...)
+    PyObject *prepareCall(const char *aFunctionName,const wxString& aLibraryPath, const PROPERTIES* aProperties);
+
+};
+
+
+#endif // fppython_PLUGIN_H_

=== modified file 'pcbnew/io_mgr.cpp'
--- pcbnew/io_mgr.cpp	2014-01-02 02:17:07 +0000
+++ pcbnew/io_mgr.cpp	2014-03-07 17:53:17 +0000
@@ -37,6 +37,10 @@
  #include <github/github_plugin.h>
 #endif
 
+#if defined(BUILD_FPPYTHON_PLUGIN)
+ #include <fppython/fppython_plugin.h>
+#endif
+
 #include <wildcards_and_files_ext.h>
 
 #define FMT_UNIMPLEMENTED   _( "Plugin '%s' does not implement the '%s' function." )
@@ -98,6 +102,13 @@
 #else
         THROW_IO_ERROR( "BUILD_GITHUB_PLUGIN not enabled in cmake build environment" );
 #endif
+    case FPPYTHON:
+#if defined(BUILD_FPPYTHON_PLUGIN)
+        return new FPPYTHON_PLUGIN();
+#else
+#error "ici"
+        THROW_IO_ERROR( "BUILD_FPPYTHON_PLUGIN not enabled in cmake build environment" );
+#endif
     }
 
     return NULL;
@@ -142,6 +153,9 @@
 
     case GITHUB:
         return wxString( wxT( "Github" ) );
+
+    case FPPYTHON:
+        return wxString( wxT( "Fppython" ) );
     }
 }
 
@@ -170,6 +184,9 @@
     if( aType == wxT( "Github" ) )
         return GITHUB;
 
+    if( aType == wxT( "Fppython" ) )
+        return FPPYTHON;
+
     // wxASSERT( blow up here )
 
     return PCB_FILE_T( -1 );

=== modified file 'pcbnew/io_mgr.h'
--- pcbnew/io_mgr.h	2014-01-02 02:17:07 +0000
+++ pcbnew/io_mgr.h	2014-03-07 17:45:53 +0000
@@ -78,6 +78,7 @@
         PCAD,
         GEDA_PCB,       ///< Geda PCB file formats.
         GITHUB,         ///< Read only http://github.com repo holding pretty footprints
+        FPPYTHON,         ///< Fppython plugin
 
         // add your type here.
 

=== modified file 'pcbnew/plugin.cpp'
--- pcbnew/plugin.cpp	2014-01-19 13:12:57 +0000
+++ pcbnew/plugin.cpp	2014-03-09 08:16:46 +0000
@@ -136,12 +136,5 @@
         ));
 #endif
 
-#if 1
-    // Suitable for a C++ to python PLUGIN::Footprint*() adapter, move it to the adapter
-    // if and when implemented.
-    (*aListToAppendTo)["python_footprint_plugin"] = UTF8( _(
-        "Enter the python module which implements the PLUGIN::Footprint*() functions."
-        ));
-#endif
 }
 

=== modified file 'scripting/python_scripting.h'
--- scripting/python_scripting.h	2013-07-19 18:27:22 +0000
+++ scripting/python_scripting.h	2014-03-08 22:02:03 +0000
@@ -27,6 +27,7 @@
 bool        pcbnewInitPythonScripting( const char * aUserPluginsPath );
 void        pcbnewFinishPythonScripting();
 
+extern PyThreadState* g_PythonMainTState;
 
 #ifdef KICAD_SCRIPTING_WXPYTHON
 


Follow ups

References