1 #include <stdio.h> 2 #include <stdlib.h> 3 4 #if defined(PLATFORM_WIN) 5 #include <windows.h> 6 #elif defined(PLATFORM_MAC) || defined(PLATFORM_LINUX) 7 #include <dlfcn.h> 8 #include <libgen.h> 9 #include <string.h> 10 #include <sys/param.h> 11 #define MAX_PATH PATH_MAX 12 #endif 13 14 #if defined(PLATFORM_WIN) 15 #define MODULE_SUFFIX ".dll" 16 #elif defined(PLATFORM_MAC) 17 #define MODULE_SUFFIX ".so" 18 #elif defined(PLATFORM_LINUX) 19 #define MODULE_SUFFIX ".so" 20 #endif 21 22 typedef void (*module_symbol)(void); 23 char bin_path[MAX_PATH + 1]; 24 25 26 void CallModule(const char* module) { 27 char module_path[MAX_PATH + 1]; 28 const char* module_function = "module_main"; 29 module_symbol funcptr; 30 #if defined(PLATFORM_WIN) 31 HMODULE dl; 32 char drive[_MAX_DRIVE]; 33 char dir[_MAX_DIR]; 34 35 if (_splitpath_s(bin_path, drive, _MAX_DRIVE, dir, _MAX_DIR, 36 NULL, 0, NULL, 0)) { 37 fprintf(stderr, "Failed to split executable path.\n"); 38 return; 39 } 40 if (_makepath_s(module_path, MAX_PATH, drive, dir, module, MODULE_SUFFIX)) { 41 fprintf(stderr, "Failed to calculate module path.\n"); 42 return; 43 } 44 45 dl = LoadLibrary(module_path); 46 if (!dl) { 47 fprintf(stderr, "Failed to open module: %s\n", module_path); 48 return; 49 } 50 51 funcptr = (module_symbol) GetProcAddress(dl, module_function); 52 if (!funcptr) { 53 fprintf(stderr, "Failed to find symbol: %s\n", module_function); 54 return; 55 } 56 funcptr(); 57 58 FreeLibrary(dl); 59 #elif defined(PLATFORM_MAC) || defined(PLATFORM_LINUX) 60 void* dl; 61 char* path_copy = strdup(bin_path); 62 char* bin_dir = dirname(path_copy); 63 int path_size = snprintf(module_path, MAX_PATH, "%s/%s%s", bin_dir, module, 64 MODULE_SUFFIX); 65 free(path_copy); 66 if (path_size < 0 || path_size > MAX_PATH) { 67 fprintf(stderr, "Failed to calculate module path.\n"); 68 return; 69 } 70 module_path[path_size] = 0; 71 72 dl = dlopen(module_path, RTLD_LAZY); 73 if (!dl) { 74 fprintf(stderr, "Failed to open module: %s\n", module_path); 75 return; 76 } 77 78 funcptr = dlsym(dl, module_function); 79 if (!funcptr) { 80 fprintf(stderr, "Failed to find symbol: %s\n", module_function); 81 return; 82 } 83 funcptr(); 84 85 dlclose(dl); 86 #endif 87 } 88 89 int main(int argc, char *argv[]) 90 { 91 fprintf(stdout, "Hello from program.c\n"); 92 fflush(stdout); 93 94 #if defined(PLATFORM_WIN) 95 if (!GetModuleFileName(NULL, bin_path, MAX_PATH)) { 96 fprintf(stderr, "Failed to determine executable path.\n"); 97 return 1; 98 } 99 #elif defined(PLATFORM_MAC) || defined(PLATFORM_LINUX) 100 // Using argv[0] should be OK here since we control how the tests run, and 101 // can avoid exec and such issues that make it unreliable. 102 if (!realpath(argv[0], bin_path)) { 103 fprintf(stderr, "Failed to determine executable path (%s).\n", argv[0]); 104 return 1; 105 } 106 #endif 107 108 CallModule("lib1"); 109 CallModule("lib2"); 110 return 0; 111 } 112