Affix
view release on metacpan or search on metacpan
infix/src/core/loader.c view on Meta::CPAN
* that check and does not set the `infix` error state, as its primary callers
* (`infix_read_global`, etc.) will set a more specific `INFIX_CODE_SYMBOL_NOT_FOUND`
* error if the lookup fails.
*
* @param[in] lib The library handle.
* @param[in] symbol_name The name of the symbol to look up (e.g., `"my_function"`).
* @return A `void*` pointer to the symbol's address, or `nullptr` if not found.
*/
INFIX_API INFIX_NODISCARD void * infix_library_get_symbol(infix_library_t * lib, const char * symbol_name) {
if (lib == nullptr || lib->handle == nullptr || symbol_name == nullptr)
return nullptr;
#if defined(INFIX_OS_WINDOWS)
return (void *)GetProcAddress((HMODULE)lib->handle, symbol_name);
#else
return dlsym(lib->handle, symbol_name);
#endif
}
/**
* @brief Reads the value of an exported global variable from a library into a buffer.
*
* This function first looks up the symbol's address. It then uses the `infix`
* signature parser (`infix_type_from_signature`) to determine the size of the
* variable. This ensures that the correct number of bytes are copied from the
* library's data segment into the user's buffer, preventing buffer overflows.
*
* @param[in] lib The library handle.
* @param[in] symbol_name The name of the global variable.
* @param[in] type_signature The `infix` signature string describing the variable's type (e.g., `"int32"`,
* `"{double,double}"`).
* @param[out] buffer A pointer to the destination buffer to receive the data. This buffer must be large enough to hold
* the type described by the signature.
* @param[in] registry An optional registry for resolving named types in the signature.
* @return `INFIX_SUCCESS` on success, or an error code on failure (e.g., symbol not found, invalid signature).
*/
INFIX_API INFIX_NODISCARD infix_status infix_read_global(infix_library_t * lib,
const char * symbol_name,
const char * type_signature,
void * buffer,
infix_registry_t * registry) {
if (buffer == nullptr)
return INFIX_ERROR_INVALID_ARGUMENT;
void * symbol_addr = infix_library_get_symbol(lib, symbol_name);
if (symbol_addr == nullptr) {
_infix_set_error(INFIX_CATEGORY_GENERAL, INFIX_CODE_SYMBOL_NOT_FOUND, 0);
return INFIX_ERROR_INVALID_ARGUMENT;
}
// Parse the signature to get the type's size.
infix_type * type = nullptr;
infix_arena_t * arena = nullptr;
infix_status status = infix_type_from_signature(&type, &arena, type_signature, registry);
if (status != INFIX_SUCCESS)
return status;
// Safely copy the data using the parsed size.
infix_memcpy(buffer, symbol_addr, type->size);
infix_arena_destroy(arena);
return INFIX_SUCCESS;
}
/**
* @brief Writes data from a buffer into an exported global variable in a library.
*
* @details This function is analogous to `infix_read_global`. It finds the symbol's
* address and uses the signature string to determine the correct number of bytes
* to copy from the source buffer to the library's memory.
*
* @note This operation assumes that the memory page containing the global variable
* is writable. This is typical for `.data` or `.bss` segments but may fail
* if the variable is in a read-only segment (e.g., a `const` global). The
* function does not attempt to change memory permissions.
*
* @param[in] lib The library handle.
* @param[in] symbol_name The name of the global variable.
* @param[in] type_signature The `infix` signature string describing the variable's type.
* @param[in] buffer A pointer to the source buffer containing the data to write.
* @param[in] registry An optional registry for resolving named types in the signature.
* @return `INFIX_SUCCESS` on success, or an error code on failure.
*/
INFIX_API INFIX_NODISCARD infix_status infix_write_global(infix_library_t * lib,
const char * symbol_name,
const char * type_signature,
void * buffer,
infix_registry_t * registry) {
if (buffer == nullptr)
return INFIX_ERROR_INVALID_ARGUMENT;
void * symbol_addr = infix_library_get_symbol(lib, symbol_name);
if (symbol_addr == nullptr) {
_infix_set_error(INFIX_CATEGORY_GENERAL, INFIX_CODE_SYMBOL_NOT_FOUND, 0);
return INFIX_ERROR_INVALID_ARGUMENT;
}
infix_type * type = nullptr;
infix_arena_t * arena = nullptr;
infix_status status = infix_type_from_signature(&type, &arena, type_signature, registry);
if (status != INFIX_SUCCESS)
return status;
// Note: This assumes the memory page containing the global is writable.
// This is standard for data segments but could fail in unusual cases.
infix_memcpy(symbol_addr, buffer, type->size);
infix_arena_destroy(arena);
return INFIX_SUCCESS;
}
( run in 0.867 second using v1.01-cache-2.11-cpan-5735350b133 )