Affix

 view release on metacpan or  search on metacpan

infix/include/infix/infix.h  view on Meta::CPAN

 *       this will not free the user-provided arena itself.
 */
INFIX_API INFIX_NODISCARD infix_registry_t * infix_registry_create_in_arena(infix_arena_t * arena);
/** @} */  // end of registry_introspection_api group
/**
 * @brief Creates a "bound" forward trampoline from a signature string.
 *
 * @details A bound trampoline is a highly optimized JIT-compiled function where the
 * target C function's address is compiled directly into the executable code. This
 * provides the best performance for forward calls, as it involves a direct `call`
 * instruction to a known address. It is ideal for situations where you will call
 * the same C function repeatedly.
 *
 * The returned handle contains a callable function pointer of type `infix_cif_func`,
 * which you can retrieve with `infix_forward_get_code`.
 *
 * @param[out] out_trampoline A pointer to an `infix_forward_t*` that will receive the
 *             created trampoline handle upon success.
 * @param[in] signature The signature string of the target function (e.g., `"(int, int)->int"`).
 * @param[in] target_function The address of the C function to be called.
 * @param[in] registry An optional type registry for resolving named types (`@Name`)
 *             used within the signature. Can be `nullptr` if no named types are used.
 * @return `INFIX_SUCCESS` on success, or an `INFIX_ERROR_...` code on failure.
 * @note The caller is responsible for destroying the handle with `infix_forward_destroy`.
 *
 * @code
 * // C function to call
 * int add(int a, int b) { return a + b; }
 *
 * infix_forward_t* trampoline = NULL;
 * const char* signature = "(int, int) -> int";
 *
 * // Create a trampoline bound to the `add` function.
 * infix_status status = infix_forward_create(&trampoline, signature, (void*)add, NULL);
 * if (status != INFIX_SUCCESS) {
 *     // Handle error...
 * }
 *
 * // Get the callable JIT-compiled function pointer.
 * infix_cif_func cif = infix_forward_get_code(trampoline);
 *
 * // Prepare arguments and return buffer.
 * int a = 10, b = 32;
 * void* args[] = { &a, &b };
 * int result;
 *
 * // Call the C function through the FFI.
 * cif(&result, args); // result is now 42
 *
 * infix_forward_destroy(trampoline);
 * @endcode
 */
INFIX_API INFIX_NODISCARD infix_status infix_forward_create(infix_forward_t **,
                                                            const char *,
                                                            void *,
                                                            infix_registry_t *);
/**
 * @brief Creates a "safe" bound forward trampoline that catches native exceptions.
 * @details This is identical to `infix_forward_create`, but the generated trampoline
 *          is wrapped in a platform-specific exception handler (e.g., SEH on Windows).
 *          If the target function throws an exception, the trampoline will catch it
 *          and set the thread-local error to `INFIX_CODE_NATIVE_EXCEPTION`.
 *
 * @param[out] out_trampoline Receives the created handle.
 * @param[in] signature The function signature.
 * @param[in] target_function The address of the C function.
 * @param[in] registry An optional type registry.
 * @return `INFIX_SUCCESS` on success.
 */
INFIX_API INFIX_NODISCARD infix_status infix_forward_create_safe(infix_forward_t **,
                                                                 const char *,
                                                                 void *,
                                                                 infix_registry_t *);
/**
 * @brief Creates an "unbound" forward trampoline from a signature string.
 *
 * @details An unbound trampoline is more flexible than a bound one. The target function
 * address is not compiled in; instead, it is provided as the first argument at
 * call time. This is useful for calling multiple C functions that share the same
 * signature without needing to generate a separate trampoline for each one.
 *
 * The returned handle contains a callable function pointer of type `infix_unbound_cif_func`,
 * which you can retrieve with `infix_forward_get_unbound_code`.
 *
 * @param[out] out_trampoline A pointer to an `infix_forward_t*` that will receive the
 *             created trampoline handle upon success.
 * @param[in] signature The signature string of the target function.
 * @param[in] registry An optional type registry for resolving named types. Can be `nullptr`.
 * @return `INFIX_SUCCESS` on success.
 * @note The caller is responsible for destroying the handle with `infix_forward_destroy`.
 *
 * @code
 * int add(int a, int b) { return a + b; }
 * int subtract(int a, int b) { return a - b; }
 *
 * infix_forward_t* trampoline = NULL;
 * const char* signature = "(int, int) -> int";
 *
 * // Create one unbound trampoline for the signature.
 * infix_forward_create_unbound(&trampoline, signature, NULL);
 *
 * infix_unbound_cif_func cif = infix_forward_get_unbound_code(trampoline);
 *
 * int a = 10, b = 5;
 * void* args[] = { &a, &b };
 * int result;
 *
 * // Call `add` by passing its address at call time.
 * cif((void*)add, &result, args); // result is 15
 *
 * // Reuse the same trampoline to call `subtract`.
 * cif((void*)subtract, &result, args); // result is 5
 *
 * infix_forward_destroy(trampoline);
 * @endcode
 */
INFIX_API INFIX_NODISCARD infix_status infix_forward_create_unbound(infix_forward_t **,
                                                                    const char *,
                                                                    infix_registry_t *);
/**
 * @brief Creates a "bound" forward trampoline within a user-provided arena.

infix/include/infix/infix.h  view on Meta::CPAN

INFIX_API INFIX_NODISCARD size_t infix_type_get_size(const infix_type *);
/**
 * @brief Gets the alignment requirement of a type in bytes.
 * @param[in] type The type object to inspect.
 * @return The alignment in bytes.
 */
INFIX_API INFIX_NODISCARD size_t infix_type_get_alignment(const infix_type *);
/**
 * @brief Gets the number of members in a struct or union type.
 * @param[in] type The aggregate type object to inspect.
 * @return The number of members, or 0 if the type is not a struct or union.
 */
INFIX_API INFIX_NODISCARD size_t infix_type_get_member_count(const infix_type *);
/**
 * @brief Gets a specific member from a struct or union type.
 * @param[in] type The aggregate type object to inspect.
 * @param[in] index The zero-based index of the member.
 * @return A pointer to the `infix_struct_member`, or `nullptr` if the index is out of bounds.
 */
INFIX_API INFIX_NODISCARD const infix_struct_member * infix_type_get_member(const infix_type *, size_t);
/**
 * @brief Gets the name of a specific argument from a function type.
 * @param[in] func_type The function type object to inspect (`INFIX_TYPE_REVERSE_TRAMPOLINE`).
 * @param[in] index The zero-based index of the argument.
 * @return The name of the argument, or `nullptr` if anonymous or out of bounds.
 */
INFIX_API INFIX_NODISCARD const char * infix_type_get_arg_name(const infix_type *, size_t);
/**
 * @brief Gets the type of a specific argument from a function type.
 * @param[in] func_type The function type object to inspect.
 * @param[in] index The zero-based index of the argument.
 * @return A pointer to the `infix_type`, or `nullptr` if the index is out of bounds.
 */
INFIX_API INFIX_NODISCARD const infix_type * infix_type_get_arg_type(const infix_type *, size_t);
/** @} */  // end addtogroup type_system
/** @} */  // end of introspection_api group
/**
 * @defgroup error_api Error Handling API
 * @brief Functions and types for detailed, thread-safe error reporting.
 * @{
 */
/**
 * @brief Enumerates the high-level categories of errors that can occur.
 */
typedef enum {
    INFIX_CATEGORY_NONE,       /**< No error. */
    INFIX_CATEGORY_GENERAL,    /**< A general or miscellaneous error. */
    INFIX_CATEGORY_ALLOCATION, /**< A memory allocation error. */
    INFIX_CATEGORY_PARSER,     /**< A syntax error in a signature string. */
    INFIX_CATEGORY_ABI         /**< An error related to ABI classification or layout. */
} infix_error_category_t;
/**
 * @brief Enumerates specific error codes.
 */
typedef enum {
    // General Codes (0-99)
    INFIX_CODE_SUCCESS = 0,      /**< No error occurred. */
    INFIX_CODE_UNKNOWN,          /**< An unspecified error occurred. */
    INFIX_CODE_NULL_POINTER,     /**< A required pointer argument was NULL. */
    INFIX_CODE_MISSING_REGISTRY, /**< A type registry was required but not provided. */
    INFIX_CODE_NATIVE_EXCEPTION, /**< A native exception (C++/SEH) was thrown during execution. */

    // Allocation Codes (100-199)
    INFIX_CODE_OUT_OF_MEMORY = 100,       /**< A call to `malloc`, `calloc`, etc. failed. */
    INFIX_CODE_EXECUTABLE_MEMORY_FAILURE, /**< Failed to allocate executable memory from the OS. */
    INFIX_CODE_PROTECTION_FAILURE,        /**< Failed to change memory protection flags (e.g., `mprotect`). */
    INFIX_CODE_INVALID_ALIGNMENT,         /**< An invalid alignment (0 or not power-of-two) was requested. */

    // Parser Codes (200-299)
    INFIX_CODE_UNEXPECTED_TOKEN = 200,   /**< Encountered an unexpected character or token. */
    INFIX_CODE_UNTERMINATED_AGGREGATE,   /**< A struct, union, or array was not properly closed. */
    INFIX_CODE_INVALID_KEYWORD,          /**< An unknown or misspelled type keyword was used. */
    INFIX_CODE_MISSING_RETURN_TYPE,      /**< A function signature was missing the '->' and return type. */
    INFIX_CODE_INTEGER_OVERFLOW,         /**< An integer overflow occurred during layout calculation. */
    INFIX_CODE_RECURSION_DEPTH_EXCEEDED, /**< A type definition was too deeply nested. */
    INFIX_CODE_EMPTY_MEMBER_NAME,        /**< A named member was declared with an empty name. */
    INFIX_CODE_EMPTY_SIGNATURE,          /**< The provided signature string was empty. */

    // ABI/Layout Codes (300-399)
    INFIX_CODE_UNSUPPORTED_ABI = 300, /**< The current platform's ABI is not supported by `infix`. */
    INFIX_CODE_TYPE_TOO_LARGE,        /**< A data type exceeded the ABI's size limits. */
    INFIX_CODE_UNRESOLVED_NAMED_TYPE, /**< A named type (`@Name`) was not found in the provided registry. */
    INFIX_CODE_INVALID_MEMBER_TYPE,   /**< An aggregate contained an illegal member type (e.g., `void`). */
    INFIX_CODE_LAYOUT_FAILED,         /**< The ABI layer failed to calculate a valid memory layout for a type. */

    // Library Loading Codes (400-499)
    INFIX_CODE_LIBRARY_NOT_FOUND = 400, /**< The requested dynamic library could not be found. */
    INFIX_CODE_SYMBOL_NOT_FOUND,        /**< The requested symbol was not found in the library. */
    INFIX_CODE_LIBRARY_LOAD_FAILED      /**< The dynamic library failed to load for other reasons. */
} infix_error_code_t;
/**
 * @struct infix_error_details_t
 * @brief Provides detailed, thread-local information about the last error that occurred.
 */
typedef struct {
    infix_error_category_t category; /**< The general category of the error. */
    infix_error_code_t code;         /**< The specific error code. */
    size_t position;                 /**< For parser errors, the byte offset into the signature string. */
    long system_error_code;          /**< The OS-specific error code (e.g., from `GetLastError()` or `errno`). */
    char message[256]; /**< A human-readable description of the error. For parser errors, this includes a code snippet.
                        */
} infix_error_details_t;
/**
 * @brief Retrieves detailed information about the last error that occurred on the current thread.
 * @return A copy of the last error details structure. This function is thread-safe.
 */
INFIX_API infix_error_details_t infix_get_last_error(void);
/** @} */  // end of error_api group
/**
 * @defgroup direct_marshalling_api Direct Marshalling API
 * @brief An advanced, high-performance API for language bindings.
 * @ingroup high_level_api
 *
 * This API provides a way to create highly optimized forward trampolines that
 * bypass the standard `void**` argument array. Instead, the JIT-compiled code
 * directly calls user-provided "marshaller" functions to convert language-specific
 * objects into native C arguments just-in-time. This reduces memory indirection
 * and copying, yielding significant performance gains for FFI calls in tight loops.
 * @{
 */



( run in 2.777 seconds using v1.01-cache-2.11-cpan-5511b514fd6 )