Skip to content
This repository has been archived by the owner on Oct 12, 2022. It is now read-only.

Commit

Permalink
Merge pull request #591 from dawgfoto/loadLibraryC
Browse files Browse the repository at this point in the history
publish C interfaces rt_loadLibrary/rt_unloadLibrary
  • Loading branch information
WalterBright committed Sep 1, 2013
2 parents 99496ed + 2c96a84 commit 21ae37e
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 42 deletions.
53 changes: 49 additions & 4 deletions src/core/runtime.d
Expand Up @@ -14,6 +14,15 @@
*/
module core.runtime;

version (Windows) import core.stdc.wchar_ : wchar_t;


/// C interface for Runtime.loadLibrary
extern (C) void* rt_loadLibrary(const char* name);
/// ditto
version (Windows) extern (C) void* rt_loadLibraryW(const wchar_t* name);
/// C interface for Runtime.unloadLibrary
extern (C) bool rt_unloadLibrary(void* ptr);

private
{
Expand All @@ -31,9 +40,6 @@ private
extern (C) bool rt_init( ExceptionHandler dg = null );
extern (C) bool rt_term( ExceptionHandler dg = null );

extern (C) void* rt_loadLibrary( in char[] name );
extern (C) bool rt_unloadLibrary( void* ptr );

extern (C) void* thread_stackBottom();

extern (C) string[] rt_args();
Expand Down Expand Up @@ -165,7 +171,46 @@ struct Runtime
*/
static void* loadLibrary( in char[] name )
{
return rt_loadLibrary( name );
import core.stdc.stdlib : free, malloc;
version (Windows)
{
import core.sys.windows.windows;

if (name.length == 0) return null;
// Load a DLL at runtime
enum CP_UTF8 = 65001;
auto len = MultiByteToWideChar(
CP_UTF8, 0, name.ptr, cast(int)name.length, null, 0);
if (len == 0)
return null;

auto buf = cast(wchar_t*)malloc((len+1) * wchar_t.sizeof);
if (buf is null) return null;
scope (exit) free(buf);

len = MultiByteToWideChar(
CP_UTF8, 0, name.ptr, cast(int)name.length, buf, len);
if (len == 0)
return null;

buf[len] = '\0';

return rt_loadLibraryW(buf);
}
else version (Posix)
{
/* Need a 0-terminated C string for the dll name
*/
immutable len = name.length;
auto buf = cast(char*)malloc(len + 1);
if (!buf) return null;
scope (exit) free(buf);

buf[0 .. len] = name[];
buf[len] = 0;

return rt_loadLibrary(buf);
}
}


Expand Down
58 changes: 20 additions & 38 deletions src/rt/dmain2.d
Expand Up @@ -32,6 +32,7 @@ version (Windows)
{
alias int function() FARPROC;
FARPROC GetProcAddress(void*, in char*);
void* LoadLibraryA(in char*);
void* LoadLibraryW(in wchar_t*);
int FreeLibrary(void*);
void* LocalFree(void*);
Expand Down Expand Up @@ -89,34 +90,22 @@ extern (C)
* opaque handle to the DLL if successfully loaded
* null if failure
*/
extern (C) void* rt_loadLibrary(in char[] name)
version (Windows)
{
version (Windows)
extern (C) void* rt_loadLibrary(const char* name)
{
return initLibrary(.LoadLibraryA(name));
}

extern (C) void* rt_loadLibraryW(const wchar_t* name)
{
return initLibrary(.LoadLibraryW(name));
}

void* initLibrary(void* mod)
{
if (name.length == 0) return null;
// Load a DLL at runtime
enum CP_UTF8 = 65001;
auto len = MultiByteToWideChar(
CP_UTF8, 0, name.ptr, cast(int)name.length, null, 0);
if (len == 0)
return null;

auto buf = cast(wchar_t*)malloc((len+1) * wchar_t.sizeof);
if (buf is null)
return null;
scope (exit)
free(buf);

len = MultiByteToWideChar(
CP_UTF8, 0, name.ptr, cast(int)name.length, buf, len);
if (len == 0)
return null;

buf[len] = '\0';

// BUG: LoadLibraryW() call calls rt_init(), which fails if proxy is not set!
// (What? LoadLibraryW() is a Windows API call, it shouldn't call rt_init().)
auto mod = LoadLibraryW(buf);
// BUG: LoadLibrary() call calls rt_init(), which fails if proxy is not set!
// (What? LoadLibrary() is a Windows API call, it shouldn't call rt_init().)
if (mod is null)
return mod;
gcSetFn gcSet = cast(gcSetFn) GetProcAddress(mod, "gc_setProxy");
Expand All @@ -125,9 +114,11 @@ extern (C) void* rt_loadLibrary(in char[] name)
gcSet(gc_getProxy());
}
return mod;

}
else version (Posix)
}
else version (Posix)
{
extern (C) void* rt_loadLibrary(const char* name)
{
throw new Exception("rt_loadLibrary not yet implemented on Posix.");
version (none)
Expand All @@ -138,16 +129,7 @@ extern (C) void* rt_loadLibrary(in char[] name)
*/
import core.sys.posix.dlfcn;

/* Need a 0-terminated C string for the dll name
*/
auto buf = cast(char*)malloc(name.length + 1);
if (!buf)
return null;
buf[0..len] = name[];
buf[len] = 0;
scope (exit) free(buf);

auto dl_handle = dlopen(buf, RTLD_LAZY);
auto dl_handle = dlopen(name, RTLD_LAZY);
if (!dl_handle)
return null;

Expand Down

0 comments on commit 21ae37e

Please sign in to comment.