Skip to content

Commit 849f02a

Browse files
committed
feat(ctypes): support ABI-compatible symbol aliases
- Allow ctypes_function_for_shared_library to accept either a single symbol name or an ordered iterable of ABI-compatible aliases. - Resolve aliases in order and bind the first exported symbol found while preserving the selected symbol name for runtime diagnostics. Also improve error reporting for empty alias lists and missing symbols. Signed-off-by: JamePeng <jame_peng@sina.com>
1 parent 859a99d commit 849f02a

1 file changed

Lines changed: 48 additions & 7 deletions

File tree

llama_cpp/_ctypes_extensions.py

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from typing import (
1010
Any,
1111
Callable,
12+
Iterable,
1213
List,
1314
Union,
1415
Optional,
@@ -201,20 +202,60 @@ class CtypesRef(Generic[CtypesCData]):
201202

202203

203204
def ctypes_function_for_shared_library(lib: ctypes.CDLL):
204-
"""Decorator for defining ctypes functions with type hints"""
205+
"""Create a decorator used to bind typed Python declarations to C symbols.
206+
207+
The returned decorator accepts either a single exported symbol name or an
208+
iterable of ABI-compatible aliases. When aliases are provided, they are
209+
checked in order and the first available symbol is selected.
210+
"""
205211

206212
def ctypes_function(
207-
name: str, argtypes: List[Any], restype: Any, enabled: bool = True
213+
name: Union[str, Iterable[str]],
214+
argtypes: List[Any],
215+
restype: Any,
216+
enabled: bool = True,
208217
):
218+
"""Bind a Python declaration to one of the requested C symbols.
219+
220+
Args:
221+
name: A symbol name or an ordered iterable of compatible aliases.
222+
argtypes: The ctypes argument types assigned to the C function.
223+
restype: The ctypes return type assigned to the C function.
224+
enabled: Return the original Python declaration when disabled.
225+
226+
Raises:
227+
ValueError: If no symbol names are provided.
228+
AttributeError: If none of the requested symbols exist in the
229+
shared library.
230+
"""
231+
symbol_names = (name,) if isinstance(name, str) else tuple(name)
232+
233+
if not symbol_names:
234+
raise ValueError("At least one shared library symbol name is required")
235+
209236
def decorator(f: F) -> F:
210-
if enabled:
211-
func = getattr(lib, name)
237+
if not enabled:
238+
return f
239+
240+
for symbol_name in symbol_names:
241+
try:
242+
func = getattr(lib, symbol_name)
243+
except AttributeError:
244+
continue
245+
212246
func.argtypes = argtypes
213247
func.restype = restype
214-
functools.wraps(f)(func)
248+
functools.update_wrapper(func, f)
249+
250+
# Preserve the actual exported symbol selected at runtime for
251+
# diagnostics, especially when ABI aliases are being used.
252+
func.__ctypes_symbol_name__ = symbol_name
215253
return func
216-
else:
217-
return f
254+
255+
raise AttributeError(
256+
"None of the shared library symbols were found: "
257+
+ ", ".join(symbol_names)
258+
)
218259

219260
return decorator
220261

0 commit comments

Comments
 (0)