Home | History | Annotate | Download | only in src
      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