#include "core.h"
#include "filesystem.h"
#include "module.h"
#if defined(_WINDOWS)
#include
static bool throw_win32(void)
{
return false;
}
bool MCModuleLoad(const char *p_filename, MCModuleRef& r_module)
{
bool t_success;
t_success = true;
void *t_native_filename;
t_native_filename = nil;
if (t_success)
t_success = MCFileSystemPathToNative(p_filename, t_native_filename);
HMODULE t_module;
t_module = nil;
if (t_success)
{
t_module = LoadLibraryW((LPCWSTR)t_native_filename);
if (t_module == nil)
t_success = throw_win32();
}
if (t_success)
r_module = (MCModuleRef)t_module;
MCMemoryDeallocate(t_native_filename);
return t_success;
}
void MCModuleUnload(MCModuleRef self)
{
if (self == nil)
return;
FreeLibrary((HMODULE)self);
}
bool MCModuleLookupSymbol(MCModuleRef self, const char *p_symbol, void **r_address)
{
void *t_address;
t_address = GetProcAddress((HMODULE)self, p_symbol);
*r_address = t_address;
return true;
}
bool MCModuleGetFilename(MCModuleRef p_module, char*& r_path)
{
bool t_success;
t_success = true;
// For some unfathomable reason, it is not possible find out how big a
// buffer you might need for a module file name. Instead we loop until
// we are sure we have the whole thing.
unichar_t *t_wpath;
uint32_t t_wpath_length;
t_wpath_length = 0;
t_wpath = nil;
while(t_success)
{
t_wpath_length += 256;
MCMemoryDeleteArray(t_wpath);
if (t_success)
t_success = MCMemoryNewArray(t_wpath_length, t_wpath);
DWORD t_result;
t_result = 0;
if (t_success)
{
// If the buffer is too small, the result will equal the input
// buffer size.
t_result = GetModuleFileNameW((HMODULE)p_module, t_wpath, t_wpath_length);
if (t_result == 0)
t_success = false;
else if (t_result == t_wpath_length)
continue;
}
if (t_success)
break;
}
// Convert the unicode string to UTF-8.
if (t_success)
t_success = MCFileSystemPathFromNative(t_wpath, r_path);
MCMemoryDeleteArray(t_wpath);
return t_success;
}
#elif defined(_LINUX)
#include
bool MCModuleLoad(const char *p_filename, MCModuleRef& r_module)
{
MCModuleRef t_module;
t_module = (void *)dlopen(p_filename, (RTLD_NOW | RTLD_LOCAL));
if (t_module == nil)
return false;
r_module = t_module;
return true;
}
void MCModuleUnload(MCModuleRef self)
{
if (self != nil)
dlclose(self);
}
bool MCModuleLookupSymbol(MCModuleRef self, const char *p_symbol, void **r_address)
{
void *t_address;
t_address = dlsym(self, p_symbol);
if (t_address == nil)
return false;
*r_address = t_address;
return true;
}
bool MCModuleGetFilename(MCModuleRef p_module, char*& r_path)
{
Dl_info t_info;
if (p_module == nil && dladdr((void *)MCModuleGetFilename, &t_info) != 0)
return MCCStringClone(t_info . dli_fname, r_path);
return false;
}
#elif defined(_MACOSX)
#include
#include
bool MCModuleLoad(const char *p_filename, MCModuleRef& r_module)
{
MCModuleRef t_module;
if (MCCStringEndsWith(p_filename, ".dylib"))
{
t_module = (void *)dlopen(p_filename, (RTLD_NOW | RTLD_LOCAL));
if (t_module == nil)
return false;
}
else
{
CFURLRef t_url;
t_url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8 *)p_filename, MCCStringLength(p_filename), TRUE);
if (t_url != nil)
{
t_module = (void *)CFBundleCreate(kCFAllocatorDefault, t_url);
if (t_module != nil)
t_module = (void *)((uintptr_t)t_module | 1);
CFRelease(t_url);
}
if (t_module == nil)
return false;
}
r_module = t_module;
return true;
}
void MCModuleUnload(MCModuleRef self)
{
if (self == nil)
return;
if (((uintptr_t)self & 1) == 0)
dlclose(self);
else
CFRelease((CFBundleRef)((uintptr_t)self & ~1));
}
bool MCModuleLookupSymbol(MCModuleRef self, const char *p_symbol, void **r_address)
{
if (self == nil)
return false;
void *t_address;
if (((uintptr_t)self & 1) == 0)
{
t_address = dlsym(self, p_symbol);
if (t_address == nil)
return false;
}
else
{
CFStringRef t_symbol;
if (!MCCStringToCFString(p_symbol, t_symbol))
return false;
t_address = CFBundleGetFunctionPointerForName((CFBundleRef)((uintptr_t)self & ~1), t_symbol);
CFRelease(t_symbol);
if (t_address == nil)
return false;
}
*r_address = t_address;
return true;
}
bool MCModuleGetFilename(MCModuleRef p_module, char*& r_path)
{
Dl_info t_info;
if (p_module == nil && dladdr((void *)MCModuleGetFilename, &t_info) != 0)
return MCCStringClone(t_info . dli_fname, r_path);
return false;
}
#endif