infix
A JIT-Powered FFI Library for C
Loading...
Searching...
No Matches
loader.c
Go to the documentation of this file.
1
30#if defined(INFIX_OS_WINDOWS)
31#include <windows.h>
32#else
33#include <dlfcn.h>
34#endif
48 if (lib == nullptr) {
50 return nullptr;
51 }
52#if defined(INFIX_OS_WINDOWS)
53 // On Windows, passing NULL to GetModuleHandleA returns a handle to the main executable file of the current process.
54 if (path == nullptr) {
55 lib->handle = GetModuleHandleA(path);
56 lib->is_pseudo_handle = true; // Mark this as a special, non-freeable handle.
57 }
58 else {
59 lib->handle = LoadLibraryA(path);
60 lib->is_pseudo_handle = false; // This is a regular, ref-counted handle.
61 }
62#else
63 // Use RTLD_LAZY for performance (resolve symbols only when they are first used).
64 // Use RTLD_LOCAL to keep symbols isolated within this handle. This prevents
65 // symbol pollution if multiple plugins link against different versions of the same
66 // dependency. Dependencies must be explicitly linked or loaded.
67 // Use RTLD_GLOBAL to make symbols from this library available for resolution
68 // by other libraries that might be loaded later. This is important for complex
69 // dependency chains.
70 // On POSIX, passing NULL to dlopen returns a handle to the main executable.
71 lib->handle = dlopen(path, RTLD_LAZY | RTLD_LOCAL);
72#endif
73 if (lib->handle == nullptr) {
74#if defined(INFIX_OS_WINDOWS)
75 // On Windows, GetLastError() provides the specific error code.
77#else
78 // On POSIX, dlerror() returns a human-readable string.
80#endif
81 infix_free(lib);
82 return nullptr;
83 }
84 return lib;
85}
94 if (lib == nullptr)
95 return;
96 if (lib->handle) {
97#if defined(INFIX_OS_WINDOWS)
98 // Only call FreeLibrary on real handles obtained from LoadLibrary.
99 // Never call it on a pseudo-handle from GetModuleHandle.
100 if (!lib->is_pseudo_handle)
101 FreeLibrary((HMODULE)lib->handle);
102#else
103 dlclose(lib->handle);
104#endif
105 }
106 infix_free(lib);
107}
124INFIX_API INFIX_NODISCARD void * infix_library_get_symbol(infix_library_t * lib, const char * symbol_name) {
125 if (lib == nullptr || lib->handle == nullptr || symbol_name == nullptr)
126 return nullptr;
127#if defined(INFIX_OS_WINDOWS)
128 return (void *)GetProcAddress((HMODULE)lib->handle, symbol_name);
129#else
130 return dlsym(lib->handle, symbol_name);
131#endif
132}
151 const char * symbol_name,
152 const char * type_signature,
153 void * buffer,
155 if (buffer == nullptr)
157 void * symbol_addr = infix_library_get_symbol(lib, symbol_name);
158 if (symbol_addr == nullptr) {
161 }
162 // Parse the signature to get the type's size.
163 infix_type * type = nullptr;
164 infix_arena_t * arena = nullptr;
165 infix_status status = infix_type_from_signature(&type, &arena, type_signature, registry);
166 if (status != INFIX_SUCCESS)
167 return status;
168 // Safely copy the data using the parsed size.
169 infix_memcpy(buffer, symbol_addr, type->size);
171 return INFIX_SUCCESS;
172}
193 const char * symbol_name,
194 const char * type_signature,
195 void * buffer,
197 if (buffer == nullptr)
199 void * symbol_addr = infix_library_get_symbol(lib, symbol_name);
200 if (symbol_addr == nullptr) {
203 }
204 infix_type * type = nullptr;
205 infix_arena_t * arena = nullptr;
206 infix_status status = infix_type_from_signature(&type, &arena, type_signature, registry);
207 if (status != INFIX_SUCCESS)
208 return status;
209 // Note: This assumes the memory page containing the global is writable.
210 // This is standard for data segments but could fail in unusual cases.
211 infix_memcpy(symbol_addr, buffer, type->size);
213 return INFIX_SUCCESS;
214}
infix_arena_t * arena
Definition 005_layouts.c:62
infix_registry_t * registry
Definition 008_registry_introspection.c:33
infix_status status
Definition 103_unions.c:61
@ INFIX_CODE_SYMBOL_NOT_FOUND
Definition infix.h:1374
@ INFIX_CODE_LIBRARY_LOAD_FAILED
Definition infix.h:1375
@ INFIX_CODE_OUT_OF_MEMORY
Definition infix.h:1350
@ INFIX_CATEGORY_ALLOCATION
Definition infix.h:1335
@ INFIX_CATEGORY_GENERAL
Definition infix.h:1334
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)
Reads the value of an exported global variable from a library into a buffer.
Definition loader.c:150
INFIX_API INFIX_NODISCARD void * infix_library_get_symbol(infix_library_t *lib, const char *symbol_name)
Retrieves the address of a symbol (function or variable) from a loaded library.
Definition loader.c:124
INFIX_API INFIX_NODISCARD infix_library_t * infix_library_open(const char *path)
Opens a dynamic library and returns a handle to it.
Definition loader.c:46
INFIX_API void infix_library_close(infix_library_t *lib)
Closes a dynamic library handle and frees associated resources.
Definition loader.c:93
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)
Writes data from a buffer into an exported global variable in a library.
Definition loader.c:192
size_t size
Definition infix.h:276
INFIX_API INFIX_NODISCARD infix_status infix_type_from_signature(infix_type **, infix_arena_t **, const char *, infix_registry_t *)
Parses a signature string representing a single data type.
Definition signature.c:1028
infix_status
Enumerates the possible status codes returned by infix API functions.
Definition infix.h:433
@ INFIX_SUCCESS
Definition infix.h:434
@ INFIX_ERROR_INVALID_ARGUMENT
Definition infix.h:436
#define infix_free
A macro that can be defined to override the default free function.
Definition infix.h:382
#define infix_memcpy
A macro that can be defined to override the default memcpy function.
Definition infix.h:386
#define infix_calloc
A macro that can be defined to override the default calloc function.
Definition infix.h:374
INFIX_API void infix_arena_destroy(infix_arena_t *)
Destroys an arena and frees all memory allocated from it.
Definition arena.c:83
#define INFIX_NODISCARD
A compatibility macro for the C23 [[nodiscard]] attribute.
Definition infix.h:140
#define INFIX_API
Symbol visibility macro.
Definition infix.h:114
Internal data structures, function prototypes, and constants.
INFIX_INTERNAL void _infix_set_system_error(infix_error_category_t category, infix_error_code_t code, long system_code, const char *msg)
Sets the thread-local error state for a system-level error.
Definition error.c:242
INFIX_INTERNAL void _infix_set_error(infix_error_category_t category, infix_error_code_t code, size_t position)
Sets the thread-local error state with detailed information.
Definition error.c:173
Internal definition of a memory arena.
Definition infix_internals.h:138
Internal definition of a dynamic library handle.
Definition infix_internals.h:195
void * handle
Definition infix_internals.h:196
Internal definition of a named type registry.
Definition infix_internals.h:165
A semi-opaque structure that describes a C type.
Definition infix.h:273