윤제균
윤제균

Reputation: 159

Loading dll in windows C for cross-platform design

I wrote a c-code designed for linux platform. Now, I want to make it cross-platform so to use in Windows as-well. In my code, I dlopen an so file and utilize the functions inside it. Below is how my code looks like. But I just found out that in windows, the way to load and use dynamic library is quite different.

void *mydynlib
mydynlib= dlopen("/libpath/dynlib.so",RTLD_LAZY);
void (*dynfunc1)() = dlsym(mydynlib,"dynfunc1");
void (*dynfunc2)(char*, char*, double) = dlsym(mydynlib,"dynfunc2");
int (*dynfunc3)() = dlsym(mydynlib,"dynfunc3");

From what I found, I need to use LoadLibrary & GetProcAddress instead of dlopen & dlsym. However, I do not know how to convert above line for windows using those. I've tried to search some examples for hours but couldn't find exact solution. If someone had this kind of experience, please give me a tip. Excuse me if this is too obvious problem. I'm quite new to C. I usually write my program in python.

Upvotes: 7

Views: 6341

Answers (3)

traversaro
traversaro

Reputation: 230

In case adding an external dependency (or manually copying two MIT-licensed files, dlfcn.h and dlfcn.c) is not a problem in your project, you can use https://github.com/dlfcn-win32/dlfcn-win32 to directly use dlopen and dlclose also on Windows.

Upvotes: 0

Govind Parmar
Govind Parmar

Reputation: 21562

You could use a set of macros that change depending on the OS you're targeting:

#ifdef __linux__
#define LIBTYPE void*
#define OPENLIB(libname) dlopen((libname), RTLD_LAZY)
#define LIBFUNC(lib, fn) dlsym((lib), (fn))
#define CLOSELIB(lib) dlclose((lib))
#elif defined(WINVER)
#define LIBTYPE HINSTANCE
#define OPENLIB(libname) LoadLibraryW(L ## libname)
#define LIBFUNC(lib, fn) GetProcAddress((lib), (fn))
#define CLOSELIB(lib) FreeLibrary((lib))
#endif

Upvotes: 7

Lorinczy Zsigmond
Lorinczy Zsigmond

Reputation: 1910

Once in my youth I created something like this:

/* dlfcn.h */

#ifndef DLFCN_H
#define DLFCN_H

#define RTLD_GLOBAL 0x100 /* do not hide entries in this module */
#define RTLD_LOCAL  0x000 /* hide entries in this module */

#define RTLD_LAZY   0x000 /* accept unresolved externs */
#define RTLD_NOW    0x001 /* abort if module has unresolved externs */

/*
   How to call in Windows:

   void *h = dlopen ("path\\library.dll", flags)
   void (*fun)() = dlsym (h, "entry")
*/

#ifdef __cplusplus
extern "C" {
#endif

      void *dlopen  (const char *filename, int flag);
      int   dlclose (void *handle);

      void *dlsym   (void *handle, const char *name);

const char *dlerror (void);

#ifdef __cplusplus
}
#endif

#endif

and dlfcn.c:

/* dlfcn.c */ 

#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>

static struct {
    long lasterror;
    const char *err_rutin;
} var = {
    0,
    NULL
};

void *dlopen (const char *filename, int flags)
{
    HINSTANCE hInst;

    hInst= LoadLibrary (filename);
    if (hInst==NULL) {
        var.lasterror = GetLastError ();
        var.err_rutin = "dlopen";
    }
    return hInst;
}

int dlclose (void *handle)
{
    BOOL ok;
    int rc= 0;

    ok= FreeLibrary ((HINSTANCE)handle);
    if (! ok) {
        var.lasterror = GetLastError ();
        var.err_rutin = "dlclose";
        rc= -1;
    }
    return rc;
}

void *dlsym (void *handle, const char *name)
{
    FARPROC fp;

    fp= GetProcAddress ((HINSTANCE)handle, name);
    if (!fp) {
        var.lasterror = GetLastError ();
        var.err_rutin = "dlsym";
    }
    return (void *)(intptr_t)fp;
}

const char *dlerror (void)
{
static char errstr [88];

    if (var.lasterror) {
        sprintf (errstr, "%s error #%ld", var.err_rutin, var.lasterror);
        return errstr;
    } else {
        return NULL;
    }
}

Upvotes: 7

Related Questions