1
0

feat: finish pybmap

This commit is contained in:
2026-02-09 22:28:46 +08:00
parent 9917db0399
commit 30f7201a07
3 changed files with 84 additions and 24 deletions

View File

@@ -11,30 +11,68 @@ class BMapException(Exception):
"""
pass
# YYC MARK:
# Due to the shitty type hints support for Python ctypes module,
# I have to use typing.TYPE_CHECKING to write these shit code for type hint.
# And the more disgusting thing is that these code is still not perfect.
bm_CKSTRING = ctypes.c_char_p
if typing.TYPE_CHECKING:
bm_CKSTRING_p = ctypes._Pointer[bm_CKSTRING]
else:
bm_CKSTRING_p = ctypes.POINTER(bm_CKSTRING)
bm_CKDWORD = ctypes.c_uint32
if typing.TYPE_CHECKING:
bm_CKDWORD_p = ctypes._Pointer[bm_CKDWORD]
bm_CKDWORD_pp = ctypes._Pointer[bm_CKDWORD_p]
else:
bm_CKDWORD_p = ctypes.POINTER(bm_CKDWORD)
bm_CKDWORD_pp = ctypes.POINTER(bm_CKDWORD_p)
bm_CKWORD = ctypes.c_uint16
if typing.TYPE_CHECKING:
bm_CKWORD_p = ctypes._Pointer[bm_CKWORD]
bm_CKWORD_pp = ctypes._Pointer[bm_CKWORD_p]
else:
bm_CKWORD_p = ctypes.POINTER(bm_CKWORD)
bm_CKWORD_pp = ctypes.POINTER(bm_CKWORD_p)
bm_CKID = ctypes.c_uint32
if typing.TYPE_CHECKING:
bm_CKID_p = ctypes._Pointer[bm_CKID]
bm_CKID_pp = ctypes._Pointer[bm_CKID_p]
else:
bm_CKID_p = ctypes.POINTER(bm_CKID)
bm_CKID_pp = ctypes.POINTER(bm_CKID_p)
bm_CKFLOAT = ctypes.c_float
if typing.TYPE_CHECKING:
bm_CKFLOAT_p = ctypes._Pointer[bm_CKFLOAT]
else:
bm_CKFLOAT_p = ctypes.POINTER(bm_CKFLOAT)
bm_CKINT = ctypes.c_int32
bm_CKBYTE = ctypes.c_uint8
if typing.TYPE_CHECKING:
bm_CKBYTE_p = ctypes._Pointer[bm_CKBYTE]
else:
bm_CKBYTE_p = ctypes.POINTER(bm_CKBYTE)
bm_enum = bm_CKDWORD
if typing.TYPE_CHECKING:
bm_enum_p = ctypes._Pointer[bm_enum]
else:
bm_enum_p = ctypes.POINTER(bm_enum)
bm_bool = ctypes.c_bool
if typing.TYPE_CHECKING:
bm_bool_p = ctypes._Pointer[bm_bool]
else:
bm_bool_p = ctypes.POINTER(bm_bool)
bm_void_p = ctypes.c_void_p
if typing.TYPE_CHECKING:
bm_void_pp = ctypes._Pointer[bm_void_p]
else:
bm_void_pp = ctypes.POINTER(ctypes.c_void_p)
# YYC MARK:
# I can't find any viable solution for type hint of C callbakc function type.
# So I give up. I leave original code here.
bm_callback = ctypes.CFUNCTYPE(None, bm_CKSTRING)
class bm_VxVector2(ctypes.Structure):
@@ -42,6 +80,10 @@ class bm_VxVector2(ctypes.Structure):
('x', bm_CKFLOAT),
('y', bm_CKFLOAT),
]
if typing.TYPE_CHECKING:
bm_VxVector2_p = ctypes._Pointer[bm_VxVector2]
bm_VxVector2_pp = ctypes._Pointer[bm_VxVector2_p]
else:
bm_VxVector2_p = ctypes.POINTER(bm_VxVector2)
bm_VxVector2_pp = ctypes.POINTER(bm_VxVector2_p)
class bm_VxVector3(ctypes.Structure):
@@ -50,6 +92,10 @@ class bm_VxVector3(ctypes.Structure):
('y', bm_CKFLOAT),
('z', bm_CKFLOAT),
]
if typing.TYPE_CHECKING:
bm_VxVector3_p = ctypes._Pointer[bm_VxVector3]
bm_VxVector3_pp = ctypes._Pointer[bm_VxVector3_p]
else:
bm_VxVector3_p = ctypes.POINTER(bm_VxVector3)
bm_VxVector3_pp = ctypes.POINTER(bm_VxVector3_p)
class bm_VxColor(ctypes.Structure):
@@ -59,11 +105,17 @@ class bm_VxColor(ctypes.Structure):
('b', bm_CKFLOAT),
('a', bm_CKFLOAT),
]
if typing.TYPE_CHECKING:
bm_VxColor_p = ctypes._Pointer[bm_VxColor]
else:
bm_VxColor_p = ctypes.POINTER(bm_VxColor)
class bm_VxMatrix(ctypes.Structure):
_fields_ = list(
(f'i{idx}', bm_CKFLOAT) for idx in range(16)
)
if typing.TYPE_CHECKING:
bm_VxMatrix_p = ctypes._Pointer[bm_VxMatrix]
else:
bm_VxMatrix_p = ctypes.POINTER(bm_VxMatrix)
#endregion
@@ -98,6 +150,9 @@ def is_bmap_available() -> bool:
return _BMAP_MODULE is not None
def _bmap_error_checker(result: bool, func, args) -> bool:
# YYC MARK:
# It seems that Python do reveal the underlying type of bm_bool
# and pass Python bool as the first argument for this function at runtime.
if not result:
raise BMapException("BMap operation failed.")
return result
@@ -109,11 +164,15 @@ def _create_bmap_func(fct_name: str, fct_params: tuple[*Ts]) -> typing.Callable[
raise BMapException(f'Fail to load native BMap dynamic library file "{_BMAP_DLL_PATH}".')
# Reference: https://docs.python.org/3.11/library/ctypes.html#foreign-functions
cache: typing.Any = getattr(_BMAP_MODULE, fct_name)
cache.argtypes = fct_params
cache.restype = bm_bool
cache.errcheck = _bmap_error_checker
return cache
fct = _BMAP_MODULE.__getattr__(fct_name)
# YYC MARK:
# Idk why these type hints for the members of non-public ctypes._NamedFuncPointer
# are so weired that can not accept my correct parameters.
# I've had enough. I use typing.cast and typing.Any to bury my head in the sand.
fct.argtypes = typing.cast(typing.Any, fct_params)
fct.restype = bm_bool
fct.errcheck = typing.cast(typing.Any, _bmap_error_checker)
return fct
#endregion

View File

@@ -24,7 +24,7 @@ def _python_callback(strl: bytes):
if strl is not None:
print(f'[pybmap] {strl.decode(BMAP_ENCODING)}')
RAW_CALLBACK = bmap.bm_callback(_python_callback)
RAW_CALLBACK: bmap.bm_callback = bmap.bm_callback(_python_callback)
#endregion

View File

@@ -2,6 +2,7 @@ use std::ffi::{CStr, CString};
use std::os::raw::{c_float, c_void};
//use std::ptr;
#[rustfmt::skip]
#[link(name = "BMap", kind = "dylib")]
unsafe extern "C" {
pub unsafe fn BMInit() -> bool;