Affix

 view release on metacpan or  search on metacpan

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

    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.
 * @{
 */

/**
 * @brief A function pointer for a direct marshalling forward trampoline.
 *
 * This is the callable code generated by `infix_forward_create_direct`. It takes
 * an array of `void*` pointers that point directly to the language-specific
 * objects (e.g., `SV*` in Perl, `PyObject*` in Python).
 *
 * @param return_value_ptr A pointer to a buffer to receive the C function's return value.
 * @param lang_objects_array An array of `void*` pointers to the original language objects.
 */
typedef void (*infix_direct_cif_func)(void *, void **);

/**
 * @brief A union to hold any primitive value returned by a scalar marshaller.
 *
 * Since a C function can only have one return type, a marshaller for primitive
 * types (`infix_marshaller_fn`) returns this union. The JIT-compiled code will
 * know which member of the union to access based on the argument's C type.
 */
typedef union {
    uint64_t u64;  ///< Used for all unsigned integer types up to 64 bits.
    int64_t i64;   ///< Used for all signed integer types up to 64 bits.
    double f64;    ///< Used for `float` and `double`.
    void * ptr;    ///< Used for all pointer types.
} infix_direct_value_t;

/**
 * @brief A function pointer for a custom marshaller for scalar types.
 *
 * A language binding provides a function of this type to convert a language object
 * into a native C primitive value (integer, float, pointer, etc.).
 *
 * @param source_object A generic `void*` pointer to the language's native object.
 * @return An `infix_direct_value_t` union containing the converted C value.
 */
typedef infix_direct_value_t (*infix_marshaller_fn)(void * source_object);

/**
 * @brief A function pointer for a custom marshaller for aggregate types (structs/unions).
 *
 * A language binding provides a function of this type to populate a C struct/union
 * from a language object (e.g., a hash or dictionary).
 *
 * @param source_object A `void*` pointer to the language's native object.
 * @param dest_buffer A pointer to a block of memory, allocated by the JIT trampoline,
 *                    that is the exact size of the C aggregate. The function must
 *                    fill this buffer with the native C data.
 * @param type A pointer to the `infix_type` object describing the C aggregate. The
 *             marshaller can introspect this type to determine field names, offsets,
 *             and member types.
 */
typedef void (*infix_aggregate_marshaller_fn)(void * source_object, void * dest_buffer, const infix_type * type);

/**
 * @brief A function pointer for a "write-back" handler for out/in-out parameters.
 *
 * This function is called by the JIT trampoline *after* the native C function has
 * returned. Its purpose is to update the original language object with any changes
 * made to the C data by the function.
 *
 * @param source_object A `void*` pointer to the original language object that was passed in.
 * @param c_data_ptr A pointer to the (potentially modified) C data buffer that was passed
 *                   to the C function.
 * @param type A pointer to the `infix_type` object describing the C data.
 */
typedef void (*infix_writeback_fn)(void * source_object, void * c_data_ptr, const infix_type * type);

/**
 * @brief A struct containing all the necessary handlers for a single function argument.
 *
 * For each argument, a language binding provides an instance of this struct. Based on
 * the argument's type, one or more of the function pointers will be non-NULL.
 */
typedef struct {
    /** @brief For "in" parameters of a scalar type (int, float, pointer). */
    infix_marshaller_fn scalar_marshaller;
    /** @brief For "in" parameters of an aggregate type (struct, union). */
    infix_aggregate_marshaller_fn aggregate_marshaller;
    /** @brief For "out" or "in-out" parameters. Called after the C function returns. */
    infix_writeback_fn writeback_handler;
} infix_direct_arg_handler_t;

/**
 * @brief Creates a forward trampoline with direct, JIT-bound marshalling.
 *
 * This advanced function generates a highly optimized trampoline that calls user-provided
 * marshaller functions directly from the JIT-compiled code to convert language-specific
 * objects into native C arguments. This avoids intermediate copying and provides the
 * highest performance for forward calls.
 *
 * @param[out] out_trampoline Receives the created trampoline handle upon success.
 * @param[in] signature The C signature of the target function (e.g., `"(int, *char)->void"`).
 * @param[in] target_function The address of the C function to be called.
 * @param[in] handlers An array of `infix_direct_arg_handler_t` structs, one for each
 *              argument of the C function. The array must have exactly as many
 *              elements as the function has arguments.
 * @param[in] registry An optional type registry for resolving named types (`@Name`)
 *              used within the signature. Can be `nullptr`.
 * @return `INFIX_SUCCESS` on success, or an error code on failure.
 */
INFIX_API INFIX_NODISCARD infix_status infix_forward_create_direct(infix_forward_t ** out_trampoline,
                                                                   const char * signature,
                                                                   void * target_function,
                                                                   infix_direct_arg_handler_t * handlers,
                                                                   infix_registry_t * registry);
/**
 * @brief Gets the callable function pointer from a direct marshalling trampoline.
 *
 * @param[in] trampoline The `infix_forward_t` handle created with `infix_forward_create_direct`.
 * @return A callable `infix_direct_cif_func` pointer on success, or `nullptr` if the
 *         trampoline is `nullptr` or is not a direct marshalling trampoline.
 */
INFIX_API INFIX_NODISCARD infix_direct_cif_func infix_forward_get_direct_code(infix_forward_t * trampoline);
/** @} */  // end of direct_marshalling_api group
#ifdef __cplusplus
}
#endif



( run in 1.174 second using v1.01-cache-2.11-cpan-437f7b0c052 )