First tiny little steps towards a SWIG "hello world"

Config file handling and basic list handling is there.
This commit is contained in:
Joerg Wunsch
2024-03-03 21:37:08 +01:00
parent 5c61b9e770
commit 4f455c6043
4 changed files with 228 additions and 1 deletions

View File

@@ -246,6 +246,16 @@ if(HAVE_LINUXGPIO)
endif()
endif()
# -------------------------------------
# Find SWIG
find_package(SWIG 4.0 COMPONENTS python)
if(SWIG_FOUND)
find_package(PythonLibs REQUIRED)
if(PYTHONLIBS_FOUND)
set(HAVE_SWIG 1)
endif()
endif()
# =====================================
# Use external libraries if requested
# =====================================
@@ -424,4 +434,10 @@ else()
message(STATUS "DISABLED linuxspi")
endif()
if(HAVE_SWIG)
message(STATUS "DO HAVE swig")
else()
message(STATUS "DON'T HAVE swig")
endif()
message(STATUS "----------------------")

View File

@@ -141,7 +141,7 @@ add_custom_target(conf ALL DEPENDS avrdude.conf)
# Project
# =====================================
add_library(libavrdude
set(SOURCES
ac_cfg.h
arduino.h
arduino.c
@@ -276,6 +276,10 @@ add_library(libavrdude
${EXTRA_WINDOWS_SOURCES}
)
add_library(libavrdude
${SOURCES}
)
set_target_properties(libavrdude PROPERTIES
PREFIX ""
PUBLIC_HEADER "libavrdude.h;libavrdude-avrintel.h"
@@ -325,6 +329,30 @@ if(MINGW)
target_link_options(avrdude PRIVATE -static)
endif()
if(HAVE_SWIG)
include (UseSWIG)
INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH})
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/..)
swig_add_library(swig_avrdude LANGUAGE Python SOURCES libavrdude.i ${SOURCES})
target_link_libraries(swig_avrdude
PRIVATE
${LIB_MATH}
${LIB_LIBELF}
${LIB_LIBUSB}
${LIB_LIBUSB_1_0}
${LIB_LIBHID}
${LIB_LIBHIDAPI}
${LIB_LIBFTDI}
${LIB_LIBFTDI1}
${LIB_LIBREADLINE}
${LIB_LIBSERIALPORT}
${LIB_NCURSES}
${LIB_LIBGPIOD}
${EXTRA_WINDOWS_LIBRARIES}
)
endif()
# =====================================
# Install
# =====================================

122
src/libavrdude.i Normal file
View File

@@ -0,0 +1,122 @@
%module swig_avrdude
%{
#include "ac_cfg.h"
#include "libavrdude.h"
// global variables referenced by library
char * version = AVRDUDE_FULL_VERSION;
char * progname = "avrdude";
char progbuf[] = " ";
int verbose;
int quell_progress;
int ovsigck;
const char *partdesc = "";
const char *pgmid = "";
int avrdude_message(int msglvl, const char *format, ...)
{
int rc = 0;
va_list ap;
if (verbose >= msglvl) {
va_start(ap, format);
rc = vfprintf(stderr, format, ap);
va_end(ap);
}
return rc;
}
int avrdude_message2(FILE *fp, int lno, const char *file, const char *func, int msgmode, int msglvl, const char *format, ...) {
printf("avrdude_message2() called\n");
return 0;
}
PROGRAMMER *cast_programmer(LNODEID p) {
return (PROGRAMMER *)p;
}
AVRPART *cast_avrpart(LNODEID p) {
return (AVRPART *)p;
}
AVRMEM *cast_avrmem(LNODEID p) {
return (AVRMEM *)p;
}
const char *cast_string(LNODEID p) {
return (const char *)p;
}
%}
// globals from above are mapped to Python
char * version;
char * progname;
char progbuf[];
int verbose;
int quell_progress;
int ovsigck;
const char *partdesc;
const char *pgmid;
typedef void * LNODEID;
typedef void * LISTID;
typedef struct avrmem AVRMEM;
// These things are read from config file(s), and must be considered
// read-only by any program. Most internals are only relevant for
// libavrdude itself, so only map things to the Python level that are
// needed there.
%typemap(out) AVRPART* {
PyObject* dict = PyDict_New();
PyDict_SetItem(dict, PyUnicode_FromString("desc"),
PyUnicode_FromString($1->desc));
PyDict_SetItem(dict, PyUnicode_FromString("id"),
PyUnicode_FromString($1->id));
PyDict_SetItem(dict, PyUnicode_FromString("signature"),
PyBytes_FromStringAndSize((const char *)($1->signature), 3));
PyDict_SetItem(dict, PyUnicode_FromString("mem"),
SWIG_NewPointerObj($1->mem, SWIGTYPE_p_avrmem, 0));
$result = dict;
}
%typemap(out) AVRMEM* {
PyObject* dict = PyDict_New();
PyDict_SetItem(dict, PyUnicode_FromString("desc"),
PyUnicode_FromString($1->desc));
PyDict_SetItem(dict, PyUnicode_FromString("paged"),
PyBool_FromLong($1->paged));
PyDict_SetItem(dict, PyUnicode_FromString("size"),
PyLong_FromLong($1->size));
PyDict_SetItem(dict, PyUnicode_FromString("page_size"),
PyLong_FromLong($1->page_size));
$result = dict;
}
// Config file handling
int init_config(void);
void cleanup_config(void);
int read_config(const char * file);
// Lists must not be manipulated from the Python level, so
// only map access functions.
extern LISTID part_list;
extern LISTID programmers;
LNODEID lfirst ( LISTID ); /* head of the list */
LNODEID llast ( LISTID ); /* tail of the list */
LNODEID lnext ( LNODEID ); /* next item in the list */
LNODEID lprev ( LNODEID ); /* previous item in the list */
void * ldata ( LNODEID ); /* data at the current position */
int lsize ( LISTID ); /* number of elements in the list */
// Typecast helpers to interpret LNODEID
PROGRAMMER *cast_programmer(LNODEID);
AVRPART *cast_avrpart(LNODEID);
AVRMEM *cast_avrmem(LNODEID);
const char *cast_string(LNODEID);

61
src/swigtest.py Normal file
View File

@@ -0,0 +1,61 @@
#!/usr/bin/env python
#
# Simple test program for testing the SWIG interface.
#
# Best call this as "python -i src/swigtest.py",
# then run the interactive interpreter.
# Example:
# a=search_avrpart('m328')
# print(a)
# show_avrmem(a['mem'])
import sys
import os
import pathlib
sysname = os.uname()[0].lower()
builddir = f'build_{sysname}/src'
sys.path.append(builddir)
import swig_avrdude as ad
ad.init_config()
found = False
for d in [builddir, "/etc", "/usr/local/etc"]:
p = pathlib.Path(d + "/avrdude.conf")
if p.is_file():
print(f"Found avrdude.conf in {d}")
ad.read_config(d + "/avrdude.conf")
found = True
break
if not found:
print("Sorry, no avrdude.conf could be found.")
sys.exit(1)
def search_avrpart(name):
'''Search list of AVR parts from config for matching "desc" or "id"'''
partlist = ad.cvar.part_list
part = ad.lfirst(partlist)
while part:
d = ad.ldata(part)
avrpart = ad.cast_avrpart(d)
if avrpart['desc'] == name or avrpart['id'] == name:
return avrpart
part = ad.lnext(part)
return None
def show_avrmem(mem):
'''List all memories defined at avrpart["mem"]'''
m = ad.lfirst(mem)
while m:
d = ad.ldata(m)
print(ad.cast_avrmem(d))
m = ad.lnext(m)