Python: Add VFS bindings

This commit is contained in:
Jeffrey Pfau 2016-10-14 15:30:40 -07:00
parent 0d1d5c988e
commit 606d35ba6c
8 changed files with 238 additions and 7 deletions

View File

@ -1,14 +1,15 @@
#define COMMON_H
#define extern
#define _TIME_H_
#define _SYS_TIME_H_
#define ATTRIBUTE_FORMAT(X, Y, Z)
#define DECL_BITFIELD(newtype, oldtype) typedef oldtype newtype
#define DECL_BIT(type, name, bit)
#define DECL_BITS(type, name, bit, nbits)
typedef long time_t;
typedef int... time_t;
typedef int... off_t;
typedef ... va_list;
#include <limits.h>
#include "platform/python/vfs-py.h"
#include "core/core.h"
#ifdef M_CORE_GBA
#include "arm/arm.h"

View File

@ -13,10 +13,19 @@ ffi.set_source("mgba._pylib", """
#include "gba/gba.h"
#include "lr35902/lr35902.h"
#include "gb/gb.h"
#include "util/vfs.h"
struct VFile* VFileFromPython(void* fileobj);
struct VFilePy {
struct VFile d;
void* fileobj;
};
""", include_dirs=[src],
extra_compile_args=sys.argv[1:],
libraries=["mgba"],
library_dirs=[os.path.join(os.getcwd(), "..")])
library_dirs=[os.path.join(os.getcwd(), "..")],
sources=[os.path.join(os.path.dirname(__file__), path) for path in ["vfs-py.c"]])
with open(os.path.join(os.getcwd(), "_builder.h")) as core:
lines = []

View File

@ -6,12 +6,24 @@ def find(path):
return None
return Core(core)
def findVF(vf):
core = lib.mCoreFindVF(vf.handle())
if core == ffi.NULL:
return None
return Core(core)
def loadPath(path):
core = find(path)
if not core or not core.loadFile(path):
return None
return core
def loadVF(vf):
core = findVF(vf)
if not core or not core.loadROM(vf):
return None
return core
class Core:
def __init__(self, native):
self._core = ffi.gc(native, self._deinit)
@ -32,6 +44,12 @@ class Core:
def loadFile(self, path):
return bool(lib.mCoreLoadFile(self._core, path.encode('UTF-8')))
def isROM(self, vf):
return bool(self._core.isROM(vf.handle()))
def loadROM(self, vf):
return bool(self._core.loadROM(self._core, vf.handle()))
def autoloadSave(self):
return bool(lib.mCoreAutoloadSave(self._core))

View File

@ -0,0 +1,126 @@
from _pylib import ffi, lib
import mmap
import os
@ffi.def_extern()
def _vfpClose(vf):
vfp = ffi.cast("struct VFilePy*", vf)
ffi.from_handle(vfp.fileobj).close()
@ffi.def_extern()
def _vfpSeek(vf, offset, whence):
vfp = ffi.cast("struct VFilePy*", vf)
f = ffi.from_handle(vfp.fileobj)
f.seek(offset, whence)
return f.tell()
@ffi.def_extern()
def _vfpRead(vf, buffer, size):
vfp = ffi.cast("struct VFilePy*", vf)
pybuf = ffi.buffer(buffer, size)
return ffi.from_handle(vfp.fileobj).readinto(pybuf)
@ffi.def_extern()
def _vfpWrite(vf, buffer, size):
vfp = ffi.cast("struct VFilePy*", vf)
pybuf = ffi.buffer(buffer, size)
return ffi.from_handle(vfp.fileobj).write(pybuf)
@ffi.def_extern()
def _vfpMap(vf, size, flags):
pass
@ffi.def_extern()
def _vfpUnmap(vf, memory, size):
pass
@ffi.def_extern()
def _vfpTruncate(vf, size):
vfp = ffi.cast("struct VFilePy*", vf)
ffi.from_handle(vfp.fileobj).truncate(size)
@ffi.def_extern()
def _vfpSize(vf):
vfp = ffi.cast("struct VFilePy*", vf)
f = ffi.from_handle(vfp.fileobj)
pos = f.tell()
f.seek(0, os.SEEK_END)
size = f.tell()
f.seek(pos, os.SEEK_SET)
return size
@ffi.def_extern()
def _vfpSync(vf, buffer, size):
vfp = ffi.cast("struct VFilePy*", vf)
f = ffi.from_handle(vfp.fileobj)
if buffer and size:
pos = f.tell()
f.seek(0, os.SEEK_SET)
_vfpWrite(vf, buffer, size)
f.seek(pos, os.SEEK_SET)
f.flush()
os.fsync()
return True
def open(f):
handle = ffi.new_handle(f)
vf = VFile(lib.VFileFromPython(handle))
# Prevent garbage collection
vf._fileobj = f
vf._handle = handle
return vf
def openPath(path, mode="r"):
flags = 0
if mode.startswith("r"):
flags |= os.O_RDONLY
elif mode.startswith("w"):
flags |= os.O_WRONLY | os.O_CREAT | os.O_TRUNC
elif mode.startswith("a"):
flags |= os.O_WRONLY | os.O_CREAT | os.O_APPEND
else:
return None
if "+" in mode[1:]:
flags |= os.O_RDWR
if "x" in mode[1:]:
flags |= os.O_EXCL
return VFile(lib.VFileOpen(path.encode("UTF-8"), flags))
class VFile:
def __init__(self, vf):
self._vf = vf
def handle(self):
return self._vf
def close(self):
return self._vf.close(self._vf)
def seek(self, offset, whence):
return self._vf.seek(self._vf, offset, whence)
def read(self, buffer, size):
return self._vf.read(self._vf, buffer, size)
def readline(self, buffer, size):
return self._vf.readline(self._vf, buffer, size)
def write(self, buffer, size):
return self._vf.write(self._vf, buffer, size)
def map(self, size, flags):
return self._vf.map(self._vf, size, flags)
def unmap(self, memory, size):
self._vf.unmap(self._vf, memory, size)
def truncate(self, size):
self._vf.truncate(self._vf, size)
def size(self):
return self._vf.size(self._vf)
def sync(self, buffer, size):
return self._vf.sync(self._vf, buffer, size)

View File

@ -1,4 +1,5 @@
from setuptools import setup
import re
classifiers = [
"Programming Language :: Python :: 2",
@ -6,9 +7,8 @@ classifiers = [
"License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)"
]
setup(name="${BINARY_NAME}",
version="${VERSION_STRING}",
version=re.sub("/", "-", "${VERSION_STRING}"),
author="Jeffrey Pfau",
author_email="jeffrey@endrift.com",
url="http://github.com/mgba-emu/mgba/",

View File

@ -0,0 +1,46 @@
/* 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 "util/vfs.h"
struct VFilePy {
struct VFile d;
void* fileobj;
};
bool _vfpClose(struct VFile* vf);
off_t _vfpSeek(struct VFile* vf, off_t offset, int whence);
ssize_t _vfpRead(struct VFile* vf, void* buffer, size_t size);
ssize_t _vfpWrite(struct VFile* vf, const void* buffer, size_t size);
void* _vfpMap(struct VFile* vf, size_t size, int flags);
void _vfpUnmap(struct VFile* vf, void* memory, size_t size);
void _vfpTruncate(struct VFile* vf, size_t size);
ssize_t _vfpSize(struct VFile* vf);
bool _vfpSync(struct VFile* vf, const void* buffer, size_t size);
struct VFile* VFileFromPython(void* fileobj) {
if (!fileobj) {
return 0;
}
struct VFilePy* vfp = malloc(sizeof(struct VFilePy));
if (!vfp) {
return 0;
}
vfp->fileobj = fileobj;
vfp->d.close = _vfpClose;
vfp->d.seek = _vfpSeek;
vfp->d.read = _vfpRead;
vfp->d.readline = VFileReadline;
vfp->d.write = _vfpWrite;
vfp->d.map = _vfpMap;
vfp->d.unmap = _vfpUnmap;
vfp->d.truncate = _vfpTruncate;
vfp->d.size = _vfpSize;
vfp->d.sync = _vfpSync;
return &vfp->d;
}

View File

@ -0,0 +1,28 @@
/* 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 "util/vfs.h"
struct VFilePy {
struct VFile d;
void* fileobj;
};
struct VFile* VFileFromPython(void* fileobj);
extern "Python+C" {
bool _vfpClose(struct VFile* vf);
off_t _vfpSeek(struct VFile* vf, off_t offset, int whence);
ssize_t _vfpRead(struct VFile* vf, void* buffer, size_t size);
ssize_t _vfpWrite(struct VFile* vf, const void* buffer, size_t size);
void* _vfpMap(struct VFile* vf, size_t size, int flags);
void _vfpUnmap(struct VFile* vf, void* memory, size_t size);
void _vfpTruncate(struct VFile* vf, size_t size);
ssize_t _vfpSize(struct VFile* vf);
bool _vfpSync(struct VFile* vf, const void* buffer, size_t size);
}

View File

@ -65,12 +65,11 @@ struct VDir {
struct VFile* VFileOpen(const char* path, int flags);
struct VFile* VFileOpenFD(const char* path, int flags);
struct VFile* VFileFOpen(const char* path, const char* mode);
struct VFile* VFileFromFD(int fd);
struct VFile* VFileFromMemory(void* mem, size_t size);
struct VFile* VFileFromConstMemory(const void* mem, size_t size);
struct VFile* VFileMemChunk(const void* mem, size_t size);
struct VFile* VFileFromFILE(FILE* file);
struct VDir* VDirOpen(const char* path);
struct VDir* VDirOpenArchive(const char* path);
@ -83,7 +82,11 @@ struct VDir* VDirOpenZip(const char* path, int flags);
struct VDir* VDirOpen7z(const char* path, int flags);
#endif
#if defined(WII) || defined(_3DS)
struct VFile* VFileFOpen(const char* path, const char* mode);
struct VFile* VFileFromFILE(FILE* file);
struct VDir* VDeviceList(void);
#endif
void separatePath(const char* path, char* dirname, char* basename, char* extension);