mirror of
https://github.com/pocketpy/pocketpy
synced 2026-02-15 03:50:18 +00:00
Compare commits
4 Commits
64ec1ed313
...
13594f9bfe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
13594f9bfe | ||
|
|
671ea14c4f | ||
|
|
05c47f1023 | ||
|
|
c21d73738c |
BIN
backup/vfs.zip
BIN
backup/vfs.zip
Binary file not shown.
@ -4,5 +4,6 @@
|
|||||||
-std=c11
|
-std=c11
|
||||||
-Iinclude/
|
-Iinclude/
|
||||||
-I3rd/lz4/
|
-I3rd/lz4/
|
||||||
|
-I3rd/periphery/
|
||||||
-I3rd/cute_png/include/
|
-I3rd/cute_png/include/
|
||||||
-I3rd/msgpack/include/
|
-I3rd/msgpack/include/
|
||||||
|
|||||||
@ -155,13 +155,18 @@ def is_vmath_type(T: str) -> bool:
|
|||||||
return False
|
return False
|
||||||
return isinstance(cvt, BuiltinVMathConverter)
|
return isinstance(cvt, BuiltinVMathConverter)
|
||||||
|
|
||||||
|
_has_vmath_converter = False
|
||||||
def set_vmath_converter(T: str, py_T: str):
|
def set_vmath_converter(T: str, py_T: str):
|
||||||
|
global _has_vmath_converter
|
||||||
assert py_T in VMATH_TYPES
|
assert py_T in VMATH_TYPES
|
||||||
_CONVERTERS[T] = BuiltinVMathConverter(T, py_T)
|
_CONVERTERS[T] = BuiltinVMathConverter(T, py_T)
|
||||||
|
_has_vmath_converter = True
|
||||||
|
|
||||||
def set_enum_converters(enums: list[str]):
|
def has_vmath_converter() -> bool:
|
||||||
for T in enums:
|
return _has_vmath_converter
|
||||||
_CONVERTERS[T] = EnumConverter(T)
|
|
||||||
|
def set_enum_converter(T: str):
|
||||||
|
_CONVERTERS[T] = EnumConverter(T)
|
||||||
|
|
||||||
def get_converter(T: str) -> Converter:
|
def get_converter(T: str) -> Converter:
|
||||||
if T in _CONVERTERS:
|
if T in _CONVERTERS:
|
||||||
@ -40,12 +40,12 @@ def gen_function(w: Writer, pyi_w: Writer, function: Function):
|
|||||||
|
|
||||||
# pyi
|
# pyi
|
||||||
py_args = []
|
py_args = []
|
||||||
# arg_names = [f'_{i}' for i in range(len(args_cvt))]
|
|
||||||
arg_names = [sanitize_name(arg.name) for arg in function.params]
|
arg_names = [sanitize_name(arg.name) for arg in function.params]
|
||||||
for i in range(len(args_cvt)):
|
for i in range(len(args_cvt)):
|
||||||
py_args.append(f'{arg_names[i]}: {args_cvt[i].py_T}')
|
py_args.append(f'{arg_names[i]}: {args_cvt[i].py_T}')
|
||||||
|
|
||||||
py_args.append('/')
|
if len(py_args) > 0:
|
||||||
|
py_args.append('/')
|
||||||
pyi_w.write(f'def {name}({", ".join(py_args)}) -> {ret_cvt.py_T}:')
|
pyi_w.write(f'def {name}({", ".join(py_args)}) -> {ret_cvt.py_T}:')
|
||||||
if function.desc:
|
if function.desc:
|
||||||
pyi_w.write(f' """Wraps `{function.signature()}`\n\n {function.desc}"""')
|
pyi_w.write(f' """Wraps `{function.signature()}`\n\n {function.desc}"""')
|
||||||
@ -3,7 +3,7 @@ from .writer import Writer
|
|||||||
from .enum import gen_enum
|
from .enum import gen_enum
|
||||||
from .struct import gen_struct
|
from .struct import gen_struct
|
||||||
from .function import gen_function
|
from .function import gen_function
|
||||||
from .converters import is_vmath_type
|
from .converters import is_vmath_type, has_vmath_converter, set_enum_converter
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@ -14,23 +14,39 @@ class Library:
|
|||||||
self.name = name
|
self.name = name
|
||||||
# ['defines', 'structs', 'aliases', 'enums', 'callbacks', 'functions']
|
# ['defines', 'structs', 'aliases', 'enums', 'callbacks', 'functions']
|
||||||
self.structs = [] # type: list[Struct]
|
self.structs = [] # type: list[Struct]
|
||||||
self.aliases = [] # type: list[Alias]
|
self.aliases = {} # type: dict[str, str | c_ast.Node]
|
||||||
self.enums = [] # type: list[Enum]
|
self.enums = [] # type: list[Enum]
|
||||||
self.functions = [] # type: list[Function]
|
self.functions = [] # type: list[Function]
|
||||||
self.callbacks = set() # type: set[str]
|
self.callbacks = set() # type: set[str]
|
||||||
|
|
||||||
|
def unalias(self, name: str) -> c_ast.Node:
|
||||||
|
while name in self.aliases:
|
||||||
|
node = self.aliases[name]
|
||||||
|
if isinstance(node, str):
|
||||||
|
name = node
|
||||||
|
else:
|
||||||
|
return node
|
||||||
|
assert False, f'alias {name} not found'
|
||||||
|
|
||||||
def build(self, *, glue_dir='.', stub_dir='.', includes: list[str] | None = None):
|
def build(self, *, glue_dir='.', stub_dir='.', includes: list[str] | None = None):
|
||||||
self.remove_unsupported()
|
self.remove_unsupported()
|
||||||
|
|
||||||
|
for k in self.aliases.keys():
|
||||||
|
node = self.unalias(k)
|
||||||
|
if isinstance(node, c_ast.Enum):
|
||||||
|
set_enum_converter(k)
|
||||||
|
|
||||||
w, pyi_w = Writer(), Writer()
|
w, pyi_w = Writer(), Writer()
|
||||||
|
|
||||||
pyi_w.write('from vmath import vec2, vec3, vec2i, vec3i, mat3x3, color32')
|
if has_vmath_converter():
|
||||||
|
pyi_w.write('from vmath import vec2, vec3, vec2i, vec3i, mat3x3, color32')
|
||||||
pyi_w.write('from typing import overload')
|
pyi_w.write('from typing import overload')
|
||||||
pyi_w.write('intptr = int')
|
pyi_w.write('from stdc import intptr')
|
||||||
pyi_w.write('')
|
pyi_w.write('')
|
||||||
|
|
||||||
w.write('#include "pocketpy.h"')
|
w.write('#include "pocketpy.h"')
|
||||||
w.write(f'#include "string.h"')
|
w.write(f'#include <string.h>')
|
||||||
|
w.write(f'#include <stdint.h>')
|
||||||
|
|
||||||
if includes:
|
if includes:
|
||||||
for include in includes:
|
for include in includes:
|
||||||
@ -39,18 +55,11 @@ class Library:
|
|||||||
w.write('')
|
w.write('')
|
||||||
w.write('#define ADD_ENUM(name) py_newint(py_emplacedict(mod, py_name(#name)), name)')
|
w.write('#define ADD_ENUM(name) py_newint(py_emplacedict(mod, py_name(#name)), name)')
|
||||||
w.write('')
|
w.write('')
|
||||||
w.write('static bool struct__address__(int argc, py_Ref argv) {')
|
|
||||||
w.indent()
|
|
||||||
w.write('PY_CHECK_ARGC(1);')
|
|
||||||
w.write('void* ud = py_touserdata(argv);')
|
|
||||||
w.write('py_newint(py_retval(), (py_i64)ud);')
|
|
||||||
w.write('return true;')
|
|
||||||
w.dedent()
|
|
||||||
w.write('}')
|
|
||||||
w.write('')
|
|
||||||
|
|
||||||
for alias in self.aliases:
|
for k in self.aliases.keys():
|
||||||
w.write(f'#define tp_user_{alias.name} tp_user_{alias.type}')
|
node = self.unalias(k)
|
||||||
|
if isinstance(node, str):
|
||||||
|
w.write(f'#define tp_user_{k} tp_user_{node}')
|
||||||
w.write('')
|
w.write('')
|
||||||
|
|
||||||
reg_exprs = [
|
reg_exprs = [
|
||||||
@ -73,9 +82,14 @@ class Library:
|
|||||||
|
|
||||||
w.write('/* aliases */')
|
w.write('/* aliases */')
|
||||||
pyi_w.write('# aliases')
|
pyi_w.write('# aliases')
|
||||||
for alias in self.aliases:
|
for k in self.aliases.keys():
|
||||||
w.write(f'py_setdict(mod, py_name("{alias.name}"), py_getdict(mod, py_name("{alias.type}")));')
|
node = self.unalias(k)
|
||||||
pyi_w.write(f'{alias.name} = {alias.type}')
|
if isinstance(node, str):
|
||||||
|
w.write(f'py_setdict(mod, py_name("{k}"), py_getdict(mod, py_name("{node}")));')
|
||||||
|
pyi_w.write(f'{k} = {node}')
|
||||||
|
elif isinstance(node, c_ast.Enum):
|
||||||
|
w.write(f'py_setdict(mod, py_name("{k}"), py_tpobject(tp_int));')
|
||||||
|
pyi_w.write(f'{k} = int')
|
||||||
|
|
||||||
w.write('/* functions */')
|
w.write('/* functions */')
|
||||||
for function in self.functions:
|
for function in self.functions:
|
||||||
@ -117,6 +131,7 @@ class Library:
|
|||||||
continue
|
continue
|
||||||
self.structs.append(Struct(
|
self.structs.append(Struct(
|
||||||
name=struct['name'],
|
name=struct['name'],
|
||||||
|
typedef_name=struct['name'],
|
||||||
desc=struct['description'],
|
desc=struct['description'],
|
||||||
fields=[StructField(
|
fields=[StructField(
|
||||||
type=field['type'],
|
type=field['type'],
|
||||||
@ -125,11 +140,7 @@ class Library:
|
|||||||
) for field in struct['fields']]
|
) for field in struct['fields']]
|
||||||
))
|
))
|
||||||
for alias in data['aliases']:
|
for alias in data['aliases']:
|
||||||
self.aliases.append(Alias(
|
self.aliases[alias['name']] = str(alias['type'])
|
||||||
type=alias['type'],
|
|
||||||
name=alias['name'],
|
|
||||||
desc=alias['description']
|
|
||||||
))
|
|
||||||
for enum in data['enums']:
|
for enum in data['enums']:
|
||||||
self.enums.append(Enum(
|
self.enums.append(Enum(
|
||||||
name=enum['name'],
|
name=enum['name'],
|
||||||
@ -157,7 +168,7 @@ class Library:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_header(name: str, header: 'Header'):
|
def from_header(name: str, header: 'Header'):
|
||||||
from c_bind.meta import schema
|
from ffigen.meta import schema
|
||||||
self = Library(name)
|
self = Library(name)
|
||||||
for type in header.types:
|
for type in header.types:
|
||||||
if isinstance(type, schema.NamedFields):
|
if isinstance(type, schema.NamedFields):
|
||||||
@ -168,6 +179,7 @@ class Library:
|
|||||||
assert fields is not None
|
assert fields is not None
|
||||||
self.structs.append(Struct(
|
self.structs.append(Struct(
|
||||||
name=type.name,
|
name=type.name,
|
||||||
|
typedef_name=type.typedef_name,
|
||||||
fields=[StructField(
|
fields=[StructField(
|
||||||
type=field_type,
|
type=field_type,
|
||||||
name=field_name
|
name=field_name
|
||||||
@ -182,10 +194,7 @@ class Library:
|
|||||||
) for value in type.values]
|
) for value in type.values]
|
||||||
))
|
))
|
||||||
for k, v in header.type_aliases.items():
|
for k, v in header.type_aliases.items():
|
||||||
self.aliases.append(Alias(
|
self.aliases[k] = v
|
||||||
name=k,
|
|
||||||
type=v
|
|
||||||
))
|
|
||||||
|
|
||||||
for function in header.functions:
|
for function in header.functions:
|
||||||
self.functions.append(Function(
|
self.functions.append(Function(
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
from typing import Literal
|
||||||
from .schema import *
|
from .schema import *
|
||||||
|
|
||||||
class UnsupportedNode(Exception):
|
class UnsupportedNode(Exception):
|
||||||
@ -11,7 +12,12 @@ class UnsupportedNode(Exception):
|
|||||||
class Header:
|
class Header:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.types = [] # type: list
|
self.types = [] # type: list
|
||||||
self.type_aliases = {} # type: dict[str, str]
|
self.type_aliases = {} # type: dict[str, str | c_ast.Node]
|
||||||
|
self.builtin_aliases = {
|
||||||
|
'size_t', 'bool',
|
||||||
|
'int8_t', 'int16_t', 'int32_t', 'int64_t',
|
||||||
|
'uint8_t', 'uint16_t', 'uint32_t', 'uint64_t',
|
||||||
|
}
|
||||||
self.functions = [] # type: list[Function]
|
self.functions = [] # type: list[Function]
|
||||||
|
|
||||||
def remove_types(self, names: set):
|
def remove_types(self, names: set):
|
||||||
@ -20,18 +26,18 @@ class Header:
|
|||||||
def remove_functions(self, names: set):
|
def remove_functions(self, names: set):
|
||||||
self.functions = [f for f in self.functions if f.name not in names]
|
self.functions = [f for f in self.functions if f.name not in names]
|
||||||
|
|
||||||
def build_enum(self, node: c_ast.Enum):
|
def add_type_alias(self, k: str, v: str | c_ast.Node):
|
||||||
|
if k in self.builtin_aliases:
|
||||||
|
return
|
||||||
|
self.type_aliases[k] = v
|
||||||
|
|
||||||
|
def build_enum(self, node: c_ast.Enum, alias_name: str | None = None):
|
||||||
enum = Enum(node.name)
|
enum = Enum(node.name)
|
||||||
for item in node.values.enumerators:
|
for item in node.values.enumerators:
|
||||||
enum.values.append(item.name)
|
enum.values.append(item.name)
|
||||||
self.types.append(enum)
|
self.types.append(enum)
|
||||||
|
|
||||||
def unalias(self, name: str):
|
def build_struct(self, node: c_ast.Struct | c_ast.Union, alias_name: str | None = None):
|
||||||
while name in self.type_aliases:
|
|
||||||
name = self.type_aliases[name]
|
|
||||||
return name
|
|
||||||
|
|
||||||
def build_struct(self, node):
|
|
||||||
if isinstance(node, c_ast.Struct):
|
if isinstance(node, c_ast.Struct):
|
||||||
cls = Struct
|
cls = Struct
|
||||||
elif isinstance(node, c_ast.Union):
|
elif isinstance(node, c_ast.Union):
|
||||||
@ -47,18 +53,23 @@ class Header:
|
|||||||
fields[name] = type
|
fields[name] = type
|
||||||
except UnsupportedNode:
|
except UnsupportedNode:
|
||||||
pass
|
pass
|
||||||
self.types.append(cls(node.name, fields))
|
self.types.append(cls(node.name, fields, alias_name))
|
||||||
else:
|
else:
|
||||||
self.types.append(cls(node.name, None))
|
self.types.append(cls(node.name, None, alias_name))
|
||||||
|
|
||||||
def build_type(self, name, node):
|
def build_type(self, node, alias_name):
|
||||||
if isinstance(node, c_ast.Enum):
|
if isinstance(node, c_ast.Enum):
|
||||||
self.build_enum(node)
|
self.build_enum(node, alias_name)
|
||||||
|
if alias_name:
|
||||||
|
self.add_type_alias(alias_name, node)
|
||||||
elif isinstance(node, (c_ast.Struct, c_ast.Union)):
|
elif isinstance(node, (c_ast.Struct, c_ast.Union)):
|
||||||
self.build_struct(node)
|
self.build_struct(node, alias_name)
|
||||||
|
if alias_name:
|
||||||
|
self.add_type_alias(alias_name, node)
|
||||||
elif isinstance(node, c_ast.IdentifierType):
|
elif isinstance(node, c_ast.IdentifierType):
|
||||||
assert name
|
assert alias_name
|
||||||
self.type_aliases[name] = node.names[0]
|
assert node.names[0]
|
||||||
|
self.add_type_alias(alias_name, node.names[0])
|
||||||
else:
|
else:
|
||||||
raise UnsupportedNode(node)
|
raise UnsupportedNode(node)
|
||||||
|
|
||||||
@ -121,6 +132,9 @@ class Header:
|
|||||||
assert isinstance(node, c_ast.TypeDecl), type(node)
|
assert isinstance(node, c_ast.TypeDecl), type(node)
|
||||||
name = node.declname
|
name = node.declname
|
||||||
ret = node.type.names[0]
|
ret = node.type.names[0]
|
||||||
|
is_const = node.quals and 'const' in node.quals
|
||||||
|
if is_const:
|
||||||
|
ret = 'const ' + ret
|
||||||
func = Function(name, ret + '*' * level)
|
func = Function(name, ret + '*' * level)
|
||||||
if args is not None:
|
if args is not None:
|
||||||
for param in args.params:
|
for param in args.params:
|
||||||
@ -137,23 +151,18 @@ class Header:
|
|||||||
if isinstance(node, c_ast.Typedef):
|
if isinstance(node, c_ast.Typedef):
|
||||||
name, node = node.name, node.type
|
name, node = node.name, node.type
|
||||||
if isinstance(node, c_ast.TypeDecl):
|
if isinstance(node, c_ast.TypeDecl):
|
||||||
self.build_type(name, node.type)
|
self.build_type(node.type, name)
|
||||||
elif isinstance(node, c_ast.PtrDecl):
|
elif isinstance(node, c_ast.PtrDecl):
|
||||||
type_name = self.get_type_name(node)
|
self.add_type_alias(name, node)
|
||||||
self.type_aliases[name] = type_name
|
|
||||||
else:
|
else:
|
||||||
# raise UnsupportedNode(node.type)
|
raise UnsupportedNode(node.type)
|
||||||
# print(f"Unsupported typedef: {type(node)}")
|
|
||||||
continue
|
|
||||||
elif isinstance(node, c_ast.Decl):
|
elif isinstance(node, c_ast.Decl):
|
||||||
if isinstance(node.type, c_ast.FuncDecl):
|
if isinstance(node.type, c_ast.FuncDecl):
|
||||||
self.build_function(node.type)
|
self.build_function(node.type)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
self.build_type(None, node.type)
|
self.build_type(node.type, None)
|
||||||
except UnsupportedNode:
|
except UnsupportedNode:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
# raise UnsupportedNode(node.type)
|
raise UnsupportedNode(node.type)
|
||||||
# print(f"Unsupported typedef: {type(node)}")
|
|
||||||
continue
|
|
||||||
@ -2,14 +2,15 @@ from pycparser import c_ast
|
|||||||
|
|
||||||
class Pointer:
|
class Pointer:
|
||||||
def __init__(self, base: str, level: int):
|
def __init__(self, base: str, level: int):
|
||||||
super().__init__(f'{base}' + '*' * level)
|
# super().__init__(f'{base}' + '*' * level)
|
||||||
self.base = base
|
self.base = base
|
||||||
self.level = level
|
self.level = level
|
||||||
|
|
||||||
class NamedFields:
|
class NamedFields:
|
||||||
def __init__(self, name: str, fields: dict[str, str] | None):
|
def __init__(self, name: str, fields: dict[str, str] | None, typedef_name: str | None = None):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.fields = fields
|
self.fields = fields
|
||||||
|
self.typedef_name = typedef_name
|
||||||
|
|
||||||
def is_opaque(self):
|
def is_opaque(self):
|
||||||
return self.fields is None
|
return self.fields is None
|
||||||
57
ffigen/ffigen/schema.py
Normal file
57
ffigen/ffigen/schema.py
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
from pycparser import c_ast
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class StructField:
|
||||||
|
type: str
|
||||||
|
name: str
|
||||||
|
desc: str | None = None
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class EnumValue:
|
||||||
|
name: str
|
||||||
|
value: int | None
|
||||||
|
desc: str | None = None
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Struct:
|
||||||
|
name: str | None = None
|
||||||
|
typedef_name: str | None = None
|
||||||
|
desc: str | None = None
|
||||||
|
fields: list[StructField] | None = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def code_name(self):
|
||||||
|
if self.typedef_name:
|
||||||
|
return self.typedef_name
|
||||||
|
assert self.name is not None
|
||||||
|
return f'struct {self.name}'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def identifier(self):
|
||||||
|
if self.name:
|
||||||
|
return self.name
|
||||||
|
assert self.typedef_name is not None
|
||||||
|
return self.typedef_name
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Enum:
|
||||||
|
name: str
|
||||||
|
values: list[EnumValue]
|
||||||
|
desc: str | None = None
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class FunctionParam:
|
||||||
|
type: str
|
||||||
|
name: str
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Function:
|
||||||
|
name: str
|
||||||
|
params: list[FunctionParam]
|
||||||
|
ret_type: str
|
||||||
|
desc: str | None = None
|
||||||
|
|
||||||
|
def signature(self) -> str:
|
||||||
|
return f'{self.ret_type} {self.name}({", ".join([f"{param.type} {param.name}" for param in self.params])})'
|
||||||
|
|
||||||
@ -2,21 +2,21 @@ from .writer import Writer
|
|||||||
from .converters import get_converter, Converter
|
from .converters import get_converter, Converter
|
||||||
from .schema import Struct, StructField
|
from .schema import Struct, StructField
|
||||||
|
|
||||||
def gen_getter(w: Writer, name: str, cvt: Converter, field: StructField):
|
def gen_getter(w: Writer, struct: Struct, cvt: Converter, field: StructField):
|
||||||
w.write(f'static bool {name}__get_{field.name}(int argc, py_Ref argv) {{')
|
w.write(f'static bool {struct.identifier}__get_{field.name}(int argc, py_Ref argv) {{')
|
||||||
w.indent()
|
w.indent()
|
||||||
w.write(f'PY_CHECK_ARGC(1);')
|
w.write(f'PY_CHECK_ARGC(1);')
|
||||||
w.write(f'{name}* self = py_touserdata(argv);')
|
w.write(f'{struct.code_name}* self = py_touserdata(argv);')
|
||||||
cvt.c2py(w, 'py_retval()', f'self->{field.name}')
|
cvt.c2py(w, 'py_retval()', f'self->{field.name}')
|
||||||
w.write('return true;')
|
w.write('return true;')
|
||||||
w.dedent()
|
w.dedent()
|
||||||
w.write('}')
|
w.write('}')
|
||||||
|
|
||||||
def gen_setter(w: Writer, name: str, cvt: Converter, field: StructField):
|
def gen_setter(w: Writer, struct: Struct, cvt: Converter, field: StructField):
|
||||||
w.write(f'static bool {name}__set_{field.name}(int argc, py_Ref argv) {{')
|
w.write(f'static bool {struct.identifier}__set_{field.name}(int argc, py_Ref argv) {{')
|
||||||
w.indent()
|
w.indent()
|
||||||
w.write(f'PY_CHECK_ARGC(2);')
|
w.write(f'PY_CHECK_ARGC(2);')
|
||||||
w.write(f'{name}* self = py_touserdata(argv);')
|
w.write(f'{struct.code_name}* self = py_touserdata(argv);')
|
||||||
cvt.py2c(w, f'self->{field.name}', 'py_arg(1)')
|
cvt.py2c(w, f'self->{field.name}', 'py_arg(1)')
|
||||||
w.write('py_newnone(py_retval());')
|
w.write('py_newnone(py_retval());')
|
||||||
w.write('return true;')
|
w.write('return true;')
|
||||||
@ -24,10 +24,11 @@ def gen_setter(w: Writer, name: str, cvt: Converter, field: StructField):
|
|||||||
w.write('}')
|
w.write('}')
|
||||||
|
|
||||||
def gen_struct(w: Writer, pyi_w: Writer, struct: Struct):
|
def gen_struct(w: Writer, pyi_w: Writer, struct: Struct):
|
||||||
name = struct.name
|
name = struct.code_name
|
||||||
converters = [get_converter(field.type) for field in struct.fields]
|
identifier = struct.identifier
|
||||||
|
converters = [get_converter(field.type) for field in struct.fields or []]
|
||||||
# default __new__
|
# default __new__
|
||||||
w.write(f'static bool {name}__new__(int argc, py_Ref argv) {{')
|
w.write(f'static bool {identifier}__new__(int argc, py_Ref argv) {{')
|
||||||
w.indent()
|
w.indent()
|
||||||
w.write(f'py_Type cls = py_totype(argv);')
|
w.write(f'py_Type cls = py_totype(argv);')
|
||||||
w.write(f'py_newobject(py_retval(), cls, 0, sizeof({name}));')
|
w.write(f'py_newobject(py_retval(), cls, 0, sizeof({name}));')
|
||||||
@ -36,7 +37,7 @@ def gen_struct(w: Writer, pyi_w: Writer, struct: Struct):
|
|||||||
w.write('}')
|
w.write('}')
|
||||||
|
|
||||||
# default __init__
|
# default __init__
|
||||||
w.write(f'static bool {name}__init__(int argc, py_Ref argv) {{')
|
w.write(f'static bool {identifier}__init__(int argc, py_Ref argv) {{')
|
||||||
w.indent()
|
w.indent()
|
||||||
w.write(f'{name}* self = py_touserdata(argv);')
|
w.write(f'{name}* self = py_touserdata(argv);')
|
||||||
w.write(f'if(argc == 1) {{')
|
w.write(f'if(argc == 1) {{')
|
||||||
@ -62,51 +63,38 @@ def gen_struct(w: Writer, pyi_w: Writer, struct: Struct):
|
|||||||
w.dedent()
|
w.dedent()
|
||||||
w.write('}')
|
w.write('}')
|
||||||
|
|
||||||
# default __copy__
|
for i, field in enumerate(struct.fields):
|
||||||
w.write(f'static bool {name}__copy__(int argc, py_Ref argv) {{')
|
cvt = converters[i]
|
||||||
w.indent()
|
gen_getter(w, struct, cvt, field)
|
||||||
w.write(f'PY_CHECK_ARGC(1);')
|
|
||||||
w.write(f'{name}* self = py_touserdata(argv);')
|
|
||||||
w.write(f'{name}* res = py_newobject(py_retval(), py_typeof(argv), 0, sizeof({name}));')
|
|
||||||
w.write(f'*res = *self;')
|
|
||||||
w.write('return true;')
|
|
||||||
w.dedent()
|
|
||||||
w.write('}')
|
|
||||||
|
|
||||||
for field in struct.fields:
|
|
||||||
cvt = get_converter(field.type)
|
|
||||||
gen_getter(w, name, cvt, field)
|
|
||||||
if not cvt.is_const():
|
if not cvt.is_const():
|
||||||
gen_setter(w, name, cvt, field)
|
gen_setter(w, struct, cvt, field)
|
||||||
|
|
||||||
w.write(f'static py_Type register__{name}(py_GlobalRef mod) {{')
|
w.write(f'static py_Type register__{identifier}(py_GlobalRef mod) {{')
|
||||||
w.indent()
|
w.indent()
|
||||||
w.write(f'py_Type type = py_newtype("{name}", tp_object, mod, NULL);')
|
w.write(f'py_Type type = py_newtype("{identifier}", tp_object, mod, NULL);')
|
||||||
|
|
||||||
w.write(f'py_bindmagic(type, __new__, {name}__new__);')
|
w.write(f'py_bindmethod(type, "__new__", {identifier}__new__);')
|
||||||
w.write(f'py_bindmagic(type, __init__, {name}__init__);')
|
w.write(f'py_bindmethod(type, "__init__", {identifier}__init__);')
|
||||||
w.write(f'py_bindmethod(type, "__address__", struct__address__);')
|
|
||||||
w.write(f'py_bindmethod(type, "copy", {name}__copy__);')
|
|
||||||
|
|
||||||
for field in struct.fields:
|
for i, field in enumerate(struct.fields):
|
||||||
cvt = get_converter(field.type)
|
cvt = converters[i]
|
||||||
if cvt.is_const():
|
if cvt.is_const():
|
||||||
setter = 'NULL'
|
setter = 'NULL'
|
||||||
else:
|
else:
|
||||||
setter = f'{name}__set_{field.name}'
|
setter = f'{identifier}__set_{field.name}'
|
||||||
w.write(f'py_bindproperty(type, "{field.name}", {name}__get_{field.name}, {setter});')
|
w.write(f'py_bindproperty(type, "{field.name}", {identifier}__get_{field.name}, {setter});')
|
||||||
|
|
||||||
w.write(f'return type;')
|
w.write(f'return type;')
|
||||||
w.dedent()
|
w.dedent()
|
||||||
w.write('}')
|
w.write('}')
|
||||||
|
|
||||||
# pyi
|
# pyi
|
||||||
pyi_w.write(f'class {name}:')
|
pyi_w.write(f'class {identifier}:')
|
||||||
pyi_w.indent()
|
pyi_w.indent()
|
||||||
|
|
||||||
py_args = []
|
py_args = []
|
||||||
for field in struct.fields:
|
for i, field in enumerate(struct.fields):
|
||||||
cvt = get_converter(field.type)
|
cvt = converters[i]
|
||||||
desc = (field.desc or '') + f' ({field.type})'
|
desc = (field.desc or '') + f' ({field.type})'
|
||||||
py_args.append(f"{field.name}: {cvt.py_T}")
|
py_args.append(f"{field.name}: {cvt.py_T}")
|
||||||
pyi_w.write(f"{py_args[-1]} # {desc}")
|
pyi_w.write(f"{py_args[-1]} # {desc}")
|
||||||
@ -116,10 +104,8 @@ def gen_struct(w: Writer, pyi_w: Writer, struct: Struct):
|
|||||||
pyi_w.write(f'def __init__(self): ...')
|
pyi_w.write(f'def __init__(self): ...')
|
||||||
pyi_w.write(f'@overload')
|
pyi_w.write(f'@overload')
|
||||||
pyi_w.write(f'def __init__(self, {", ".join(py_args)}): ...')
|
pyi_w.write(f'def __init__(self, {", ".join(py_args)}): ...')
|
||||||
pyi_w.write(f'def __address__(self) -> int: ...')
|
|
||||||
pyi_w.write(f"def copy(self) -> '{name}': ...")
|
|
||||||
pyi_w.write('')
|
pyi_w.write('')
|
||||||
pyi_w.dedent()
|
pyi_w.dedent()
|
||||||
|
|
||||||
w.write(f'static py_Type tp_user_{name};')
|
w.write(f'static py_Type tp_user_{identifier};')
|
||||||
return f'tp_user_{name} = register__{name}(mod);'
|
return f'tp_user_{identifier} = register__{identifier}(mod);'
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import pcpp
|
import pcpp
|
||||||
import pycparser
|
import pycparser
|
||||||
from c_bind import Library, set_vmath_converter, set_enum_converters
|
from ffigen import Library, set_vmath_converter, set_enum_converters
|
||||||
from c_bind.meta import Header
|
from ffigen.meta import Header
|
||||||
import os
|
import os
|
||||||
|
|
||||||
path = '../3rd/box2d/include/box2d/box2d.h'
|
path = '../3rd/box2d/include/box2d/box2d.h'
|
||||||
@ -1,7 +1,8 @@
|
|||||||
import pcpp
|
import pcpp
|
||||||
import pycparser
|
import pycparser
|
||||||
from c_bind import Library, set_vmath_converter, set_enum_converters
|
from ffigen.library import Library
|
||||||
from c_bind.meta import Header
|
from ffigen.converters import set_vmath_converter, set_enum_converter
|
||||||
|
from ffigen.meta import Header
|
||||||
import os
|
import os
|
||||||
|
|
||||||
file_dir = os.path.dirname(os.path.abspath(__file__))
|
file_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
@ -17,10 +18,8 @@ header.build(ast)
|
|||||||
|
|
||||||
lib = Library.from_header('periphery', header)
|
lib = Library.from_header('periphery', header)
|
||||||
|
|
||||||
set_enum_converters([enum.name for enum in lib.enums])
|
|
||||||
|
|
||||||
lib.build(
|
lib.build(
|
||||||
includes=['c-periphery/gpio.h'],
|
includes=['c-periphery/src/gpio.h'],
|
||||||
glue_dir='3rd/periphery/src',
|
glue_dir='3rd/periphery/src',
|
||||||
stub_dir='include/typings'
|
stub_dir='include/typings'
|
||||||
)
|
)
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import json
|
import json
|
||||||
from c_bind import Library, set_vmath_converter
|
from ffigen import Library, set_vmath_converter
|
||||||
|
|
||||||
with open('../3rd/raylib/parser/output/raylib_api.json') as f:
|
with open('../3rd/raylib/parser/output/raylib_api.json') as f:
|
||||||
data = json.load(f)
|
data = json.load(f)
|
||||||
1
ffigen/libc_include/stdarg.h
Normal file
1
ffigen/libc_include/stdarg.h
Normal file
@ -0,0 +1 @@
|
|||||||
|
typedef int va_list;
|
||||||
1
ffigen/libc_include/stdbool.h
Normal file
1
ffigen/libc_include/stdbool.h
Normal file
@ -0,0 +1 @@
|
|||||||
|
typedef _Bool bool;
|
||||||
3
ffigen/libc_include/stddef.h
Normal file
3
ffigen/libc_include/stddef.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#define NULL ((void*)0)
|
||||||
|
|
||||||
|
typedef unsigned size_t;
|
||||||
9
ffigen/libc_include/stdint.h
Normal file
9
ffigen/libc_include/stdint.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
typedef int int8_t;
|
||||||
|
typedef int int16_t;
|
||||||
|
typedef int int32_t;
|
||||||
|
typedef int int64_t;
|
||||||
|
|
||||||
|
typedef unsigned uint8_t;
|
||||||
|
typedef unsigned uint16_t;
|
||||||
|
typedef unsigned uint32_t;
|
||||||
|
typedef unsigned uint64_t;
|
||||||
@ -46,14 +46,15 @@ class Double(_BuiltinMemory[float]): ...
|
|||||||
class Pointer(_BuiltinMemory[intptr]): ...
|
class Pointer(_BuiltinMemory[intptr]): ...
|
||||||
class Bool(_BuiltinMemory[bool]): ...
|
class Bool(_BuiltinMemory[bool]): ...
|
||||||
|
|
||||||
INT8: _BuiltinMemory[int] = ...
|
Int8: _BuiltinMemory[int]
|
||||||
UINT8: _BuiltinMemory[int] = ...
|
UInt8: _BuiltinMemory[int]
|
||||||
INT16: _BuiltinMemory[int] = ...
|
Int16: _BuiltinMemory[int]
|
||||||
UINT16: _BuiltinMemory[int] = ...
|
UInt16: _BuiltinMemory[int]
|
||||||
INT32: _BuiltinMemory[int] = ...
|
Int32: _BuiltinMemory[int]
|
||||||
UINT32: _BuiltinMemory[int] = ...
|
UInt32: _BuiltinMemory[int]
|
||||||
INT64: _BuiltinMemory[int] = ...
|
Int64: _BuiltinMemory[int]
|
||||||
UINT64: _BuiltinMemory[int] = ...
|
UInt64: _BuiltinMemory[int]
|
||||||
|
SizeT: _BuiltinMemory[int]
|
||||||
|
|
||||||
def addressof(obj: Memory) -> intptr: ...
|
def addressof(obj: Memory) -> intptr: ...
|
||||||
def sizeof(obj: type[Memory]) -> int: ...
|
def sizeof(obj: type[Memory]) -> int: ...
|
||||||
|
|||||||
@ -1,7 +0,0 @@
|
|||||||
from .function import gen_function
|
|
||||||
from .converters import get_converter, set_vmath_converter, set_enum_converters
|
|
||||||
from .writer import Writer
|
|
||||||
from .struct import gen_struct
|
|
||||||
from .enum import gen_enum
|
|
||||||
|
|
||||||
from .library import Library
|
|
||||||
@ -1,47 +0,0 @@
|
|||||||
from dataclasses import dataclass
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class StructField:
|
|
||||||
type: str
|
|
||||||
name: str
|
|
||||||
desc: str = None
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class EnumValue:
|
|
||||||
name: str
|
|
||||||
value: int | None
|
|
||||||
desc: str = None
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Struct:
|
|
||||||
name: str
|
|
||||||
desc: str = None
|
|
||||||
fields: list[StructField] = None
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Alias:
|
|
||||||
type: str
|
|
||||||
name: str
|
|
||||||
desc: str = None
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Enum:
|
|
||||||
name: str
|
|
||||||
values: list[EnumValue]
|
|
||||||
desc: str = None
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class FunctionParam:
|
|
||||||
type: str
|
|
||||||
name: str
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Function:
|
|
||||||
name: str
|
|
||||||
params: list[FunctionParam]
|
|
||||||
ret_type: str
|
|
||||||
desc: str = None
|
|
||||||
|
|
||||||
def signature(self) -> str:
|
|
||||||
return f'{self.ret_type} {self.name}({", ".join([f"{param.type} {param.name}" for param in self.params])})'
|
|
||||||
|
|
||||||
@ -1 +0,0 @@
|
|||||||
#define va_list int
|
|
||||||
@ -1 +0,0 @@
|
|||||||
#define bool _Bool
|
|
||||||
@ -1 +0,0 @@
|
|||||||
#define NULL ((void*)0)
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
#define size_t int
|
|
||||||
|
|
||||||
#define int8_t int
|
|
||||||
#define int16_t int
|
|
||||||
#define int32_t int
|
|
||||||
#define int64_t int
|
|
||||||
|
|
||||||
#define uint8_t unsigned
|
|
||||||
#define uint16_t unsigned
|
|
||||||
#define uint32_t unsigned
|
|
||||||
#define uint64_t unsigned
|
|
||||||
@ -267,6 +267,13 @@ void pk__add_module_stdc() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for(py_Type t = tp_stdc_Char; t <= tp_stdc_ULongLong; t += 2) {
|
||||||
|
py_Ref size_var = py_getdict(py_tpobject(t), py_name("size"));
|
||||||
|
if(py_toint(size_var) == sizeof(size_t)) {
|
||||||
|
py_setdict(mod, py_name("SizeT"), py_tpobject(t + 1));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pk__bind_stdc_Float(mod);
|
pk__bind_stdc_Float(mod);
|
||||||
pk__bind_stdc_Double(mod);
|
pk__bind_stdc_Double(mod);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user