From 79bb9552da8ecdd7eab51f978cf132d77f92ef88 Mon Sep 17 00:00:00 2001 From: Amy Gale Ruth Bowersox Date: Sat, 7 Dec 2019 19:43:45 -0700 Subject: [PATCH] adding the embedded Python init/terminate code --- src/Makefile | 14 ++++--- src/config.c | 1 + src/config.h | 1 + src/ep_init.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/ep_init.h | 11 ++++++ src/ep_util.c | 44 +++++++++++++++++++++ src/ep_util.h | 11 ++++++ src/main.c | 5 ++- src/scode.h | 2 +- 9 files changed, 186 insertions(+), 7 deletions(-) create mode 100644 src/ep_init.c create mode 100644 src/ep_init.h create mode 100644 src/ep_util.c create mode 100644 src/ep_util.h diff --git a/src/Makefile b/src/Makefile index 902fc62..2d6dfaa 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,17 +1,21 @@ -OBJS=main.o sysinput.o fbinit.o fbprimitive.o log.o gpio.o msg_queue.o time_func.o config.o splash.o -LIBS=-lbcm2835 -lpthread -CFLAGS=-g -O -DDEBUG_ASSERT +OBJS=main.o sysinput.o ep_init.o ep_util.o fbinit.o fbprimitive.o log.o gpio.o msg_queue.o \ + time_func.o config.o splash.o +LIBS=-lpython3.7m -lcrypt -lbcm2835 -lpthread -ldl -lutil -lm +CFLAGS=-I/usr/include/python3.7m -Wall -fstack-protector -fwrapv -fno-PIE -g -O3 -DDEBUG_ASSERT +LDFLAGS=-L/usr/lib/python3.7/config-3.7m-arm-linux-gnueabihf -Xlinker -export-dynamic -Wl,-O1 \ + -Wl,-Bsymbolic-functions all: upiwin upiwin: $(OBJS) - gcc -o upiwin $(OBJS) $(LIBS) + gcc -o upiwin $(LDFLAGS) $(OBJS) $(LIBS) .c.o: gcc -c $(CFLAGS) $< splash.o: splash.bin - objcopy -I binary -O elf32-littlearm -B arm --rename-section .data=.rodata,alloc,load,readonly,data,contents splash.bin splash.o + objcopy -I binary -O elf32-littlearm -B arm --rename-section \ + .data=.rodata,alloc,load,readonly,data,contents splash.bin splash.o splash.bin: splash.png ../buildutils/mksplash ../buildutils/mksplash splash.png splash.bin diff --git a/src/config.c b/src/config.c index dbfcb1a..d9aa37a 100644 --- a/src/config.c +++ b/src/config.c @@ -66,6 +66,7 @@ static void init_defaults(void) memset(&Gconfig, 0, sizeof(GLOBAL_CONFIG)); Gconfig.framebuffer_device = "/dev/fb1"; Gconfig.touchscreen_device = "/dev/input/touchscreen"; + Gconfig.python_loc = "/usr/bin/python3"; Gconfig.button_debounce = 100; Gconfig.sys_mq_length = 64; } diff --git a/src/config.h b/src/config.h index e543bd4..1bb94e4 100644 --- a/src/config.h +++ b/src/config.h @@ -9,6 +9,7 @@ typedef void (*PEXITFUNC)(void); typedef struct tagGLOBAL_CONFIG { PCSTR framebuffer_device; /* name of frame buffer device */ PCSTR touchscreen_device; /* name of touchscreen device */ + PCSTR python_loc; /* location of the Python3 executable */ UINT32 button_debounce; /* minimum time between button up and next button down (ms) */ UINT32 sys_mq_length; /* length of system message queue */ } GLOBAL_CONFIG; diff --git a/src/ep_init.c b/src/ep_init.c new file mode 100644 index 0000000..a163039 --- /dev/null +++ b/src/ep_init.c @@ -0,0 +1,104 @@ +#define PY_SSIZE_T_CLEAN +#include +#include "scode.h" +#include "config.h" +#include "log.h" +#include "ep_init.h" +#include "ep_util.h" + +PCSTR Mod_UPIWIN = "upiwin"; /* name of the primary UPIWIN module */ +PCSTR Mod_UPIWIN_tmp = "upiwin_tmp"; /* name of the temporary UPIWIN module */ + +static wchar_t *python_name = NULL; /* location of the Python executable */ + +static PyObject *upiwin_module = NULL; +static PyObject *upiwin_tmp_module = NULL; + +static PyObject *init_upiwin_module(void) +{ +} + +static PyObject *init_upiwin_tmp_module(void) +{ +} + +/* used to link the two modules into Python's init table */ +static struct _inittab upiwin_inittab[] = { + { Mod_UPIWIN, init_upiwin_module }, + { Mod_UPIWIN_tmp, init_upiwin_tmp_module }, + { NULL, NULL } +}; + +static void epython_cleanup(void) +{ + Py_DECREF(upiwin_tmp_module); + upiwin_tmp_module = NULL; + Py_DECREF(upiwin_module); + upiwin_module = NULL; + if (!Py_FinalizeEx()) + Log(LWARN, "errors encountered when Python uninitialized itself"); + PyMem_RawFree(python_name); + python_name = NULL; +} + +HRESULT Epython_setup(void) +{ + HRESULT hr; + size_t size; + + python_name = Py_DecodeLocale(Gconfig.python_loc, &size); + if (!python_name) + { + if (size==(size_t)(-1)) + { + Log(LFATAL, "error allocating Python program location"); + return E_OUTOFMEMORY; + } + else + { + Log(LFATAL, "internal error in Py_DecodeLocale"); + return E_UNEXPECTED; + } + } + Py_SetProgramName(python_name); + + if (PyImport_ExtendInittab(upiwin_inittab)) + { + Log(LFATAL, "error allocating extended init table"); + hr = E_OUTOFMEMORY; + goto error_0; + } + + Py_Initialize(); + + /* Import the modules */ + upiwin_module = PyImport_ImportModule(Mod_UPIWIN); + if (!upiwin_module) + { + Log(LFATAL, "error importing the upiwin module"); + hr = Epython_trace_exception(); + goto error_1; + } + upiwin_tmp_module = PyImport_ImportModule(Mod_UPIWIN_tmp); + if (!upiwin_tmp_module) + { + Log(LFATAL, "error importing the upiwin_tmp module"); + hr = Epython_trace_exception(); + goto error_2; + } + + hr = Config_exitfunc(epython_cleanup); + if (FAILED(hr)) + epython_cleanup(); + return hr; + +error_2: + Py_DECREF(upiwin_module); + upiwin_module = NULL; +error_1: + Py_FinalizeEx(); +error_0: + PyMem_RawFree(python_name); + python_name = NULL; + return hr; +} diff --git a/src/ep_init.h b/src/ep_init.h new file mode 100644 index 0000000..bd376ab --- /dev/null +++ b/src/ep_init.h @@ -0,0 +1,11 @@ +#ifndef __EP_INIT_H_INCLUDED +#define __EP_INIT_H_INCLUDED + +#include "wintype.h" + +extern PCSTR Mod_UPIWIN; +extern PCSTR Mod_UPIWIN_tmp; + +extern HRESULT Epython_setup(void); + +#endif /* __EP_INIT_H_INCLUDED */ diff --git a/src/ep_util.c b/src/ep_util.c new file mode 100644 index 0000000..ee12f4a --- /dev/null +++ b/src/ep_util.c @@ -0,0 +1,44 @@ +#define PY_SSIZE_T_CLEAN +#include +#include "scode.h" +#include "ep_util.h" +#include "log.h" + +void Epython_log_object(int level, const char *label, PyObject *object) +{ + BOOL traced = FALSE; + PyObject *repr; + PCSTR pstr; + + repr = PyObject_Repr(object); + if (repr) + { + ASSERT(PyUnicode_Check(repr)); + pstr = PyUnicode_AsUTF8(repr); + Log(level, "object %s: %s", label, pstr); + traced = TRUE; + Py_DECREF(repr); + } + + if (!traced) + Log(level, "object %s: could not be logged (memory error)", label); +} + +HRESULT Epython_trace_exception(void) +{ + HRESULT hr = E_FAIL; + + PyObject *type, *value, *traceback; + PyErr_Fetch(&type, &value, &traceback); + if (!type) + return S_OK; + + Epython_log_object(LERROR, "exception type", type); + Epython_log_object(LERROR, "exception value", value); + Epython_log_object(LERROR, "exception traceback", value); + + Py_DECREF(type); + Py_DECREF(value); + Py_DECREF(traceback); + return hr; +} diff --git a/src/ep_util.h b/src/ep_util.h new file mode 100644 index 0000000..5644889 --- /dev/null +++ b/src/ep_util.h @@ -0,0 +1,11 @@ +#ifndef __EP_UTIL_H_INCLUDED +#define __EP_UTIL_H_INCLUDED + +#define PY_SSIZE_T_CLEAN +#include +#include "wintype.h" + +extern void Epython_log_object(int level, const char *label, PyObject *object); +extern HRESULT Epython_trace_exception(void); + +#endif /* __EP_UTIL_H_INCLUDED */ diff --git a/src/main.c b/src/main.c index bc91640..d683864 100644 --- a/src/main.c +++ b/src/main.c @@ -8,6 +8,7 @@ #include "fbinit.h" #include "fbprimitive.h" #include "time_func.h" +#include "ep_init.h" #include "sysinput.h" static void do_draw(void) @@ -46,10 +47,12 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; if (FAILED(Gpio_setup())) return EXIT_FAILURE; + if (FAILED(Epython_setup())) + return EXIT_FAILURE; if (FAILED(Sys_enable_input())) return EXIT_FAILURE; Log(LINFO, "Pausing at startup."); - sleep(3); /* wait to show off splash screen */ + sleep(2); /* wait to show off splash screen */ Fb_clear(); /* temporary drawing here */ diff --git a/src/scode.h b/src/scode.h index 6880804..2f97a69 100644 --- a/src/scode.h +++ b/src/scode.h @@ -64,6 +64,6 @@ #define E_UNEXPECTED SCODE_CAST(0x8000FFFF) /* unexpected error */ /* UPIWIN-specific errorcodes */ -#define UPIWIN_E_OUTOFRANGE SCODE_CAST(0x80060000) /* value out of range */ +#define UPIWIN_E_INVALIDSTRING SCODE_CAST(0x80060000) /* invalid string (decode error) */ #endif /* __SCODE_H_INCLUDED */