Python: Preliminary, incomplete bindings

This commit is contained in:
Jeffrey Pfau 2016-10-11 13:13:44 -07:00
parent 4ac4733cfd
commit e5c61e0093
12 changed files with 134 additions and 3 deletions

View File

@ -28,6 +28,7 @@ set(BUILD_PERF OFF CACHE BOOL "Build performance profiling tool")
set(BUILD_TEST OFF CACHE BOOL "Build testing harness")
set(BUILD_SUITE OFF CACHE BOOL "Build test suite")
set(BUILD_EXAMPLE OFF CACHE BOOL "Build example frontends")
set(BUILD_PYTHON OFF CACHE BOOL "Build Python bindings")
set(BUILD_STATIC OFF CACHE BOOL "Build a static library")
set(BUILD_SHARED ON CACHE BOOL "Build a shared library")
set(SKIP_LIBRARY OFF CACHE BOOL "Skip building the library (useful for only building libretro or OpenEmu cores)")
@ -750,6 +751,11 @@ if(BUILD_SUITE)
add_test(${BINARY_NAME}-suite ${BINARY_NAME}-suite)
endif()
if(BUILD_PYTHON)
enable_testing()
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/platform/python ${CMAKE_CURRENT_BINARY_DIR}/python)
endif()
if(BUILD_EXAMPLE)
add_executable(${BINARY_NAME}-example-server ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/example/client-server/server.c)
target_link_libraries(${BINARY_NAME}-example-server ${BINARY_NAME})
@ -833,6 +839,7 @@ if(NOT QUIET)
message(STATUS " Profiling: ${BUILD_PERF}")
message(STATUS " Test harness: ${BUILD_TEST}")
message(STATUS " Test suite: ${BUILD_SUITE}")
message(STATUS " Python bindings: ${BUILD_PYTHON}")
message(STATUS " Examples: ${BUILD_EXAMPLE}")
message(STATUS "Cores:")
message(STATUS " Libretro core: ${BUILD_LIBRETRO}")

View File

@ -73,7 +73,7 @@ union PSR {
unsigned z : 1;
unsigned c : 1;
unsigned v : 1;
unsigned : 20;
unsigned unused : 20;
unsigned i : 1;
unsigned f : 1;
unsigned t : 1;
@ -83,7 +83,7 @@ union PSR {
unsigned t : 1;
unsigned f : 1;
unsigned i : 1;
unsigned : 20;
unsigned unused : 20;
unsigned v : 1;
unsigned c : 1;
unsigned z : 1;

View File

@ -44,4 +44,18 @@ const char* mLogCategoryName(int category) {
return 0;
}
void mLog(int category, enum mLogLevel level, const char* format, ...) {
struct mLogger* context = mLogGetContext();
va_list args;
va_start(args, format);
if (context) {
context->log(context, category, level, format, args);
} else {
printf("%s: ", mLogCategoryName(category));
vprintf(format, args);
printf("\n");
}
va_end(args);
}
mLOG_DEFINE_CATEGORY(STATUS, "Status")

View File

@ -30,6 +30,7 @@ int mLogGenerateCategory(const char*);
const char* mLogCategoryName(int);
ATTRIBUTE_FORMAT(printf, 3, 4)
#ifndef __NO_INLINE__
static inline void mLog(int category, enum mLogLevel level, const char* format, ...) {
struct mLogger* context = mLogGetContext();
va_list args;
@ -43,6 +44,9 @@ static inline void mLog(int category, enum mLogLevel level, const char* format,
}
va_end(args);
}
#else
void mLog(int category, enum mLogLevel level, const char* format, ...);
#endif
#define mLOG(CATEGORY, LEVEL, ...) mLog(_mLOG_CAT_ ## CATEGORY (), mLOG_ ## LEVEL, __VA_ARGS__)

View File

@ -35,7 +35,7 @@ enum mDebuggerState {
enum mWatchpointType {
WATCHPOINT_WRITE = 1,
WATCHPOINT_READ = 2,
WATCHPOINT_RW = WATCHPOINT_WRITE | WATCHPOINT_READ
WATCHPOINT_RW = 3
};
enum mBreakpointType {

View File

@ -0,0 +1,20 @@
set(PY_INCLUDE_DIRS -I${CMAKE_SOURCE_DIR}/src)
get_property(INCLUDE_DIRECTORIES DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES)
get_property(COMPILE_DEFINITIONS DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY COMPILE_DEFINITIONS)
foreach(INCLUDE_DIR IN LISTS INCLUDE_DIRECTORIES)
list(APPEND PY_INCLUDE_DIRS -I${INCLUDE_DIR})
endforeach()
foreach(COMPILE_DEF IN LISTS COMPILE_DEFINITIONS)
list(APPEND PY_COMPILE_DEFS -D${COMPILE_DEF})
endforeach()
add_custom_command(OUTPUT _builder.h
COMMAND ${CMAKE_C_COMPILER} ${PY_COMPILE_DEFS} ${PY_INCLUDE_DIRS} -fno-inline -E -P -c ${CMAKE_CURRENT_SOURCE_DIR}/_builder.h -o _builder.h
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/_builder.h)
add_custom_target(_builder.h ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/_builder.h)
add_custom_command(OUTPUT ${BINARY_NAME}/_pylib.so
COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/_builder.py ${PY_COMPILE_DEFS} ${PY_INCLUDE_DIRS}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/_builder.py
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/_builder.h)
add_custom_target(_pylib.so ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME}/_pylib.so)

View File

View File

@ -0,0 +1,6 @@
#define COMMON_H
#define ATTRIBUTE_FORMAT(X, Y, Z)
typedef long time_t;
typedef ... va_list;
#include <limits.h>
#include "core/core.h"

View File

@ -0,0 +1,20 @@
import cffi
import os.path
import subprocess
import sys
ffi = cffi.FFI()
src = os.path.join(os.path.dirname(__file__), "..", "..")
ffi.set_source("mgba._pylib", """
#include "util/common.h"
#include "core/core.h"
""", include_dirs=[src],
extra_compile_args=sys.argv[1:],
libraries=["mgba"],
library_dirs=[os.path.join(os.getcwd(), "..")])
with open(os.path.join(os.getcwd(), "_builder.h")) as core:
ffi.cdef(core.read())
ffi.compile()

View File

@ -0,0 +1,47 @@
from _pylib import ffi, lib
def find(path):
core = lib.mCoreFind(path.encode('UTF-8'))
if core == ffi.NULL:
return None
return mCore(core)
class mCore:
def __init__(self, native):
self._core = ffi.gc(native, self._deinit)
def init(self):
return bool(self._core.init(self._core))
def _deinit(self):
self._core.deinit(self._core)
def loadFile(self, path):
return bool(lib.mCoreLoadFile(self._core, path.encode('UTF-8')))
def autoloadSave(self):
return bool(lib.mCoreAutoloadSave(self._core))
def autoloadPatch(self):
return bool(lib.mCoreAutoloadPatch(self._core))
def platform(self):
return self._core.platform(self._core)
def desiredVideoDimensions(self):
width = ffi.new("unsigned*")
height = ffi.new("unsigned*")
self._core.desiredVideoDimensions(self._core, width, height)
return width[0], height[0]
def reset(self):
self._core.reset(self._core)
def runFrame(self):
self._core.runFrame(self._core)
def runLoop(self):
self._core.runLoop(self._core)
def step(self):
self._core.step(self._core)

View File

@ -163,6 +163,14 @@ size_t TableSize(const struct Table* table) {
return table->size;
}
void HashTableInit(struct Table* table, size_t initialSize, void (deinitializer(void*))) {
TableInit(table, initialSize, deinitializer);
}
void HashTableDeinit(struct Table* table) {
TableDeinit(table);
}
void* HashTableLookup(const struct Table* table, const char* key) {
uint32_t hash = hash32(key, strlen(key), 0);
const struct TableList* list;

View File

@ -29,6 +29,7 @@ void TableClear(struct Table*);
void TableEnumerate(const struct Table*, void (handler(uint32_t key, void* value, void* user)), void* user);
size_t TableSize(const struct Table*);
#ifndef __NO_INLINE__
static inline void HashTableInit(struct Table* table, size_t initialSize, void (deinitializer(void*))) {
TableInit(table, initialSize, deinitializer);
}
@ -36,6 +37,10 @@ static inline void HashTableInit(struct Table* table, size_t initialSize, void (
static inline void HashTableDeinit(struct Table* table) {
TableDeinit(table);
}
#else
void HashTableInit(struct Table* table, size_t initialSize, void (deinitializer(void*)));
void HashTableDeinit(struct Table* table);
#endif
void* HashTableLookup(const struct Table*, const char* key);
void HashTableInsert(struct Table*, const char* key, void* value);