all repos — mgba @ 1dff579ad4a6e5ccb1152b8cddd74975b970b0b3

mGBA Game Boy Advance Emulator

Python: Add basic logging interface
Jeffrey Pfau jeffrey@endrift.com
Sat, 15 Oct 2016 11:54:01 -0700
commit

1dff579ad4a6e5ccb1152b8cddd74975b970b0b3

parent

33295b129779e8e5e6d8b15829b5fdc0b07e421f

M src/platform/python/_builder.hsrc/platform/python/_builder.h

@@ -15,10 +15,13 @@ typedef ...* png_structp;

typedef ...* png_infop; typedef ...* png_unknown_chunkp; +void free(void*); + #include <limits.h> #include "core/core.h" #include "platform/python/vfs-py.h" +#include "platform/python/log.h" #ifdef USE_PNG #include "util/png-io.h"
M src/platform/python/_builder.pysrc/platform/python/_builder.py

@@ -9,6 +9,7 @@

ffi.set_source("mgba._pylib", """ #include "util/common.h" #include "core/core.h" +#include "core/log.h" #include "arm/arm.h" #include "gba/gba.h" #include "lr35902/lr35902.h"

@@ -22,11 +23,18 @@ struct VFilePy {

struct VFile d; void* fileobj; }; + +struct mLogger* mLoggerPythonCreate(void* pyobj); + +struct mLoggerPy { + struct mLogger d; + void* pyobj; +}; """, include_dirs=[src], extra_compile_args=sys.argv[1:], libraries=["mgba"], library_dirs=[os.path.join(os.getcwd(), "..")], - sources=[os.path.join(os.path.dirname(__file__), path) for path in ["vfs-py.c"]]) + sources=[os.path.join(os.path.dirname(__file__), path) for path in ["vfs-py.c", "log.c"]]) with open(os.path.join(os.getcwd(), "_builder.h")) as core: lines = []
A src/platform/python/log.c

@@ -0,0 +1,27 @@

+/* Copyright (c) 2013-2016 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "core/log.h" + +struct mLoggerPy { + struct mLogger d; + void* pyobj; +}; + +void _pyLog(void* logger, int category, enum mLogLevel level, const char* message); + +static void _pyLogShim(struct mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args) { + struct mLoggerPy* pylogger = (struct mLoggerPy*) logger; + char message[256] = {0}; + vsnprintf(message, sizeof(message) - 1, format, args); + _pyLog(pylogger, category, level, message); +} + +struct mLogger* mLoggerPythonCreate(void* pyobj) { + struct mLoggerPy* logger = malloc(sizeof(*logger)); + logger->d.log = _pyLogShim; + logger->pyobj = pyobj; + return &logger->d; +}
A src/platform/python/log.h

@@ -0,0 +1,15 @@

+/* Copyright (c) 2013-2016 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "core/log.h" + +struct mLoggerPy { + struct mLogger d; + void* pyobj; +}; + +struct mLogger* mLoggerPythonCreate(void* pyobj); + +extern "Python+C" void _pyLog(void* logger, int category, enum mLogLevel level, const char* message);
A src/platform/python/mgba/log.py

@@ -0,0 +1,34 @@

+# Copyright (c) 2013-2016 Jeffrey Pfau +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +from ._pylib import ffi, lib + +@ffi.def_extern() +def _pyLog(logger, category, level, message): + l = ffi.cast("struct mLoggerPy*", logger) + ffi.from_handle(l.pyobj).log(category, level, ffi.string(message).decode('UTF-8')) + +def installDefault(logger): + lib.mLogSetDefaultLogger(logger._native) + +class Logger(object): + FATAL = lib.mLOG_FATAL + DEBUG = lib.mLOG_DEBUG + INFO = lib.mLOG_INFO + WARN = lib.mLOG_WARN + ERROR = lib.mLOG_ERROR + STUB = lib.mLOG_STUB + GAME_ERROR = lib.mLOG_GAME_ERROR + + def __init__(self): + self._handle = ffi.new_handle(self) + self._native = ffi.gc(lib.mLoggerPythonCreate(self._handle), lib.free) + + @staticmethod + def categoryName(category): + return ffi.string(lib.mLogCategoryName(category)).decode('UTF-8') + + def log(self, category, level, message): + print("{}: {}".format(self.categoryName(category), message))