Source code for libretro.api.proc

"""
Types for retrieving core functions beyond
the standard ``retro_*`` API functions exposed by :class:`.Core`.
"""

from ctypes import Structure
from dataclasses import dataclass

from libretro.ctypes import CStringArg, TypedFunctionPointer

retro_proc_address_t = TypedFunctionPointer[None, []]
"""
Opaque function pointer returned by :c:type:`retro_get_proc_address_t`.

Despite this declaration, the underlying function may have any signature;
use :func:`ctypes.cast` to convert it to a :class:`~ctypes.CFUNCTYPE`
or :class:`~libretro.ctypes.TypedFunctionPointer` with the correct prototype before invoking it.

.. danger::

    When calling a function pointer obtained from :c:type:`retro_get_proc_address_t`,
    ensure that the signature matches the expected function prototype
    and that it follows the C ABI (e.g. with ``extern "C"`` in C++).
    Mismatched signatures or calling conventions can lead to undefined behavior.

Corresponds to :c:type:`retro_proc_address_t` in ``libretro.h``.
"""

retro_get_proc_address_t = TypedFunctionPointer[retro_proc_address_t, [CStringArg]]
"""
Look up an exported function pointer in the core by symbol name.

Registered by the :term:`core` and called by the :term:`frontend`
to access libretro extensions implemented by the core.

:param sym: The symbol name to look up, as a :obj:`bytes`-like object.
:return: A :class:`~libretro.ctypes.c_void_ptr` to the matching :c:type:`retro_proc_address_t`,
    or :obj:`None` if the core does not export a function with that name.

.. note::
    The returned pointer must be cast to the correct function signature before use.

Corresponds to :c:type:`retro_get_proc_address_t` in ``libretro.h``.
"""


[docs] @dataclass(init=False, slots=True) class retro_get_proc_address_interface(Structure): """ An interface to get function pointers directly from a :class:`.Core`. Corresponds to :c:type:`retro_get_proc_address_interface` in ``libretro.h``. """ get_proc_address: retro_get_proc_address_t | None """Retrieves a function pointer by symbol name.""" _fields_ = (("get_proc_address", retro_get_proc_address_t),)
[docs] def __call__(self, sym: str | bytes) -> retro_proc_address_t | None: """ Call :attr:`get_proc_address` with the given symbol name. :param sym: Symbol name as a string or bytes. :returns: The function pointer, or :obj:`None` if not found. :raises ValueError: If :attr:`get_proc_address` is :obj:`None`. :raises TypeError: If ``sym`` is not :class:`str` or :class:`bytes`. """ if not self.get_proc_address: raise ValueError("get_proc_address is NULL") match sym: case str(): sym_bytes = sym.encode("utf-8") case bytes(): sym_bytes = sym case _: raise TypeError(f"sym must be str or bytes, got {type(sym).__name__}") return self.get_proc_address(sym_bytes)
[docs] def __deepcopy__(self, _): """ Return a copy of this object. Intended for use with :func:`copy.deepcopy`. """ return retro_get_proc_address_interface(self.get_proc_address)
__all__ = [ "retro_get_proc_address_interface", "retro_proc_address_t", "retro_get_proc_address_t", ]