mirror of https://github.com/KLayout/klayout.git
WIP: added sample lib with bridging code
This commit is contained in:
parent
2737e14b13
commit
9418185771
|
|
@ -0,0 +1,123 @@
|
|||
|
||||
#include <Python.h>
|
||||
|
||||
#include "pyaConvert.h"
|
||||
#include "pyaRefs.h"
|
||||
#include "dbPolygon.h"
|
||||
|
||||
static PyObject *BridgeError;
|
||||
|
||||
static PyObject *
|
||||
bridge_a2p (PyObject * /*self*/, PyObject *args)
|
||||
{
|
||||
PyObject *a = NULL;
|
||||
if (! PyArg_ParseTuple (args, "O", &a)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Iterate over the array elements
|
||||
pya::PythonRef iterator (PyObject_GetIter (a));
|
||||
if (! iterator) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Prepare a vector of points we can create the polygon from later
|
||||
std::vector<db::DPoint> points;
|
||||
|
||||
PyObject *item;
|
||||
while ((item = PyIter_Next (iterator.get ())) != NULL) {
|
||||
|
||||
// Iterate over the x/y pair
|
||||
pya::PythonRef xy_iterator (PyObject_GetIter (item));
|
||||
if (! xy_iterator) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
double c[2] = { 0.0, 0.0 };
|
||||
|
||||
// Gets the x and y value
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
pya::PythonRef xy_item (PyIter_Next (xy_iterator.get ()));
|
||||
if (! xy_item) {
|
||||
return NULL;
|
||||
}
|
||||
if (pya::test_type<double> (xy_item.get ())) {
|
||||
c[i] = pya::python2c<double> (xy_item.get ());
|
||||
}
|
||||
}
|
||||
|
||||
points.push_back (db::DPoint (c[0], c[1]));
|
||||
|
||||
}
|
||||
|
||||
// Handle iteration errors
|
||||
if (PyErr_Occurred()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create and return a new object of db::DSimplePolygon type
|
||||
db::DSimplePolygon *poly = new db::DSimplePolygon ();
|
||||
poly->assign_hull (points.begin (), points.end ());
|
||||
return pya::c2python_new<db::DSimplePolygon> (poly);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
bridge_p2a (PyObject * /*self*/, PyObject *args)
|
||||
{
|
||||
// Parse the command line arguments
|
||||
PyObject *p = NULL;
|
||||
if (! PyArg_ParseTuple (args, "O", &p)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Report an error if the input isn't a db::DSimplePolygon
|
||||
if (! pya::test_type<const db::DSimplePolygon &> (p)) {
|
||||
PyErr_SetString (BridgeError, "Expected a db::DSimplePolygon type");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Obtain the db::DSimplePolygon
|
||||
const db::DSimplePolygon &poly = pya::python2c<const db::DSimplePolygon &> (p);
|
||||
|
||||
// Prepare an array for the points
|
||||
PyObject *array = PyList_New (poly.hull ().size ());
|
||||
Py_INCREF (array);
|
||||
|
||||
// Iterate over the points and fill the array with x/y tuples
|
||||
int i = 0;
|
||||
for (db::DSimplePolygon::polygon_contour_iterator pt = poly.hull ().begin (); pt != poly.hull ().end (); ++pt, ++i) {
|
||||
PyObject *point = PyTuple_New (2);
|
||||
PyTuple_SET_ITEM (point, 0, pya::c2python ((*pt).x ()));
|
||||
PyTuple_SET_ITEM (point, 1, pya::c2python ((*pt).y ()));
|
||||
PyList_SetItem (array, i, point);
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
static PyMethodDef BridgeMethods[] = {
|
||||
{
|
||||
"p2a", bridge_p2a, METH_VARARGS,
|
||||
"Converts a DSimplePolygon to an array."
|
||||
},
|
||||
{
|
||||
"a2p", bridge_a2p, METH_VARARGS,
|
||||
"Converts an array to a DSimplePolygon."
|
||||
},
|
||||
{ NULL, NULL, 0, NULL } // terminal
|
||||
};
|
||||
|
||||
PyMODINIT_FUNC
|
||||
initbridge ()
|
||||
{
|
||||
PyObject *m;
|
||||
|
||||
m = Py_InitModule ("bridge", BridgeMethods);
|
||||
if (m == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
BridgeError = PyErr_NewException ((char *) "bridge.error", NULL, NULL);
|
||||
Py_INCREF (BridgeError);
|
||||
PyModule_AddObject (m, "error", BridgeError);
|
||||
}
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
|
||||
# The "bridge" library is a sample library illustrating how to access
|
||||
# KLayout data from PyObject and vice versa.
|
||||
#
|
||||
# It demonstrates how to translate a db::SimplePolygon object to an
|
||||
# array of x/y floating point pairs and back.
|
||||
#
|
||||
# To build this module externally you'll need to supply these variables in
|
||||
# qmake:
|
||||
# - KLAYOUTINCLUDE: path to the KLayout sources
|
||||
# - KLAYOUTLIBDIR: path to the KLayout libraries (.so/.dll)
|
||||
# - PYTHONINCLUDE: path to the Python include file
|
||||
# - PYTHONLIBFILE: path to the Python library file
|
||||
#
|
||||
# Normally, these paths are set by the build script.
|
||||
#
|
||||
# To use the bridge library, ...
|
||||
|
||||
!isEmpty(KLAYOUTINCLUDE) {
|
||||
INC = $$KLAYOUTINCLUDE
|
||||
} else {
|
||||
INC = $$PWD/../..
|
||||
}
|
||||
|
||||
!isEmpty(KLAYOUTLIBDIR) {
|
||||
LIBDIR = $$KLAYOUTLIBDIR
|
||||
} else {
|
||||
LIBDIR = $$OUT_PWD/../..
|
||||
}
|
||||
|
||||
# That's were we are going to put our Python module to
|
||||
DESTDIR = $$OUT_PWD/../..
|
||||
|
||||
# We're going to build a library
|
||||
TEMPLATE = lib
|
||||
|
||||
# That's how we name our library
|
||||
TARGET = bridge
|
||||
|
||||
# The only source
|
||||
SOURCES = bridge.cc
|
||||
|
||||
# Include QtCore required for some includes
|
||||
QT = core
|
||||
|
||||
# Further dependencies include:
|
||||
# - Python (of course)
|
||||
# - GSI (generic scripting interface)
|
||||
# - TL (basic toolkit)
|
||||
# - PYA (Python binding for GSI)
|
||||
INCLUDEPATH += $$PYTHONINCLUDE $$INC/tl/tl $$INC/gsi/gsi $$INC/pya/pya
|
||||
DEPENDPATH += $$PYTHONINCLUDE $$INC/tl/tl $$INC/gsi/gsi $$INC/pya/pya
|
||||
LIBS += $$PYTHONLIBFILE -L$$LIBDIR -lklayout_tl -lklayout_gsi -lklayout_pya
|
||||
|
||||
# Also include DB as this is our sample
|
||||
INCLUDEPATH += $$INC/db/db
|
||||
DEPENDPATH += $$INC/db/db
|
||||
LIBS += -L$$LIBDIR -lklayout_db
|
||||
|
||||
# Pull in RPATH
|
||||
!isEmpty(RPATH) {
|
||||
QMAKE_RPATHDIR += $$RPATH
|
||||
}
|
||||
|
||||
# Some standard compiler warnings on
|
||||
QMAKE_CXXFLAGS_WARN_ON += \
|
||||
-pedantic \
|
||||
-Woverloaded-virtual \
|
||||
-Wsign-promo \
|
||||
-Wsynth \
|
||||
-Wno-deprecated \
|
||||
-Wno-long-long \
|
||||
-Wno-strict-aliasing \
|
||||
-Wno-deprecated-declarations \
|
||||
-Wno-reserved-user-defined-literal \
|
||||
|
||||
# Python is somewhat sloppy and relies on the compiler initializing fields
|
||||
# of strucs to 0:
|
||||
QMAKE_CXXFLAGS_WARN_ON += \
|
||||
-Wno-missing-field-initializers
|
||||
|
||||
win32 {
|
||||
# to avoid the major version being appended to the dll name - in this case -lxyz won't link it again
|
||||
# because the library is called xyx0.dll.
|
||||
CONFIG += skip_target_version_ext
|
||||
} else {
|
||||
# Make the target library without the "lib" prefix on Linux
|
||||
QMAKE_POST_LINK += $(COPY) $(DESTDIR)$(TARGET) $$DESTDIR/$${TARGET}.so
|
||||
}
|
||||
|
||||
# nothing to install as we're building a test library
|
||||
INSTALLS =
|
||||
Loading…
Reference in New Issue