blob: a46a4621cbb76db40f753787b730f267e052904d [file] [log] [blame]
/* Copyright (C) 2011 The Android Open Source Project
**
** This software is licensed under the terms of the GNU General Public
** License version 2, as published by the Free Software Foundation, and
** may be copied, distributed, and modified under those terms.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
*/
#include <android/utils/dll.h>
#include <android/utils/system.h>
#include <android/utils/path.h>
#include <stdlib.h>
/* Utility function, append one string to another, caller must free result */
static char*
append_string( const char* str1, const char* str2 )
{
int len1 = strlen(str1);
int len2 = strlen(str2);
char* result = malloc(len1+len2+1);
if (result != NULL) {
memcpy(result, str1, len1);
memcpy(result + len1, str2, len2);
result[len1+len2] = '\0';
}
return result;
}
#ifdef _WIN32
#include <windows.h>
/* This function is used to revert all forward slashes (/) in a path
* string into unquoted backwards one (\). This is necessary because
* LoadLibrary() and AddDllDirectory() do not support forward slashes.
*
* Caller must free the result string
*/
static char*
reverse_slashes( const char* path )
{
int len = strlen(path);
char* result = malloc(len+1);
int nn;
for (nn = 0; nn < len; nn++) {
int ch = path[nn];
if (ch == '/') {
ch = '\\';
}
result[nn] = (char)ch;
}
result[nn] = '\0';
return result;
}
ADynamicLibrary*
adynamicLibrary_open( const char* libraryName,
char** pError)
{
char* libName = (char*) libraryName;
void* result;
/* Append a .dll to the library name if it doesn't have an extension */
if (strchr(libraryName,'.') == NULL) {
libName = append_string(libraryName, ".dll");
}
/* Now do our magic */
*pError = NULL;
result = (ADynamicLibrary*) LoadLibrary( libName );
if (result == NULL) {
*pError = ASTRDUP("Could not load DLL!");
}
/* Free the library name if we modified it */
if (libName != libraryName) {
free(libName);
}
return (ADynamicLibrary*) result;
}
void*
adynamicLibrary_findSymbol( ADynamicLibrary* lib,
const char* symbolName,
char** pError)
{
void* result;
*pError = NULL;
if (lib == NULL) {
*pError = strdup("NULL library pointer");
return NULL;
}
if (symbolName == NULL || symbolName[0] == '\0') {
*pError = strdup("NULL or empty symbolName");
return NULL;
}
result = GetProcAddress( (HMODULE)lib, symbolName );
if (result == NULL) {
*pError = ASTRDUP("Could not find symbol");
}
return result;
}
/* Close/unload a given dynamic library */
void
adynamicLibrary_close( ADynamicLibrary* lib )
{
if (lib != NULL) {
FreeLibrary( (HMODULE)lib );
}
}
#else /* !_WIN32 */
#include <dlfcn.h>
#include <stdlib.h>
ADynamicLibrary*
adynamicLibrary_open( const char* libraryName,
char** pError)
{
char* libName = (char*) libraryName;
void* result;
#ifdef __APPLE__
# define SO_EXTENSION ".dylib"
#else
# define SO_EXTENSION ".so"
#endif
/* Append a .so to the library name if it doesn't have an extension */
if (strchr(libraryName,'.') == NULL) {
libName = append_string(libraryName, SO_EXTENSION);
}
/* Now do our magic */
*pError = NULL;
result = dlopen( libName, RTLD_LAZY );
if (result == NULL) {
*pError = strdup(dlerror());
}
/* Free the library name if we modified it */
if (libName != (char*)libraryName) {
free(libName);
}
return (ADynamicLibrary*) result;
}
void*
adynamicLibrary_findSymbol( ADynamicLibrary* lib,
const char* symbolName,
char** pError)
{
void* result;
*pError = NULL;
if (lib == NULL) {
*pError = strdup("NULL library pointer");
return NULL;
}
if (symbolName == NULL || symbolName[0] == '\0') {
*pError = strdup("NULL or empty symbolName");
return NULL;
}
result = dlsym(lib, symbolName);
if (result == NULL) {
*pError = strdup(dlerror());
}
return result;
}
/* Close/unload a given dynamic library */
void
adynamicLibrary_close( ADynamicLibrary* lib )
{
if (lib != NULL) {
dlclose(lib);
}
}
#endif /* !_WIN32 */