- Cross platform shared library support? If it’s bad, I might write
something up.
It’s planned for SDL 1.3. The code is actually already written.
Since it’s been written already, can Iget access to either what’s been
written of SDL 1.3 or just the shared library code?
Sure.
-Sam Lantinga, Software Engineer, Blizzard Entertainment
-------------- next part --------------
/*
SDL - Simple DirectMedia Layer
load.c, placed in the public domain by Sam Lantinga 6/7/99
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#ifdef WIN32
#define INITGUID
#include <windows.h>
#endif
#ifdef macintosh
#include <QuickDraw.h>
#endif
/* Include definitions of all the datatypes and stub functions */
#define SDL_PROTOTYPES_ONLY
#undef _BUILDING_SDL
#include “SDL.h”
#include “SDL_mutex.h”
#include “SDL_thread.h”
#include “SDL_timer.h”
#include “SDL_syswm.h”
/* Define the exported function pointers */
#define SDL_DECLARE(type, name, args) type (*name) args = 0;
#include “exports.decl”
#include “sysdep.decl”
#undef SDL_DECLARE
/* Define the table from which we load the SDL functions */
#define SDL_DECLARE(type, name, args) { “_”#name, (void **) &name },
typedef struct {
const char *symnam;
void **symbol;
} symbol_t;
static symbol_t symtab = {
#include “exports.decl”
#include “sysdep.decl”
{ (char *)0, (void **)0 }
};
#undef SDL_DECLARE
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
/ The dynamic library initialization and finalization functions */
int (_init_func)(Uint32 flags) = 0;
void (_quit_func)(void) = 0;
int (*_lock_SO)(void) = 0;
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
/ Local error message handling */
static char STUB_errbuf[BUFSIZ];
static char *STUB_error = NULL;
void STUB_SetError (char *fmt, …)
{
va_list ap;
va_start(ap, fmt);
vsprintf(STUB_errbuf, fmt, ap);
va_end(ap);
STUB_error = STUB_errbuf;
}
char * STUB_GetError (void)
{
return(STUB_error ? STUB_error : “”);
}
void STUB_ClearError(void)
{
STUB_error = NULL;
}
/* This macro allows errors to propogate in case of library load failure */
#define RESET_ERROR() (SDL_GetError = STUB_GetError)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
/ System dependent library loading routines */
static void *libhandle = (void *)0;
#if defined(unix) || defined(unix)
include <dlfcn.h>
#elif defined(WIN32)
#ifndef NO_DIRECTX_HEADERS
include <directx.h>
#endif
#elif defined(BEOS)
include <be/kernel/image.h>
#elif defined(macintosh)
include <Strings.h>
include <CodeFragments.h>
include <Errors.h>
#else
#error Unsupported dynamic link environment
#endif /* system type */
/* The directory in which can be found the SDL dynamic library.
If it is set to ‘\0’, then the default system path is used.
*/
static char libprefix[BUFSIZ] = { 0 };
/* Set the library load path, for security or convenience */
void SDL_SetLibraryPath(const char *path)
{
char *bufp = NULL;
if ( strlen(path) < (BUFSIZ-(32+1)) ) {
sprintf(libprefix, "%s/", path);
#ifdef macintosh
#define DIR_SEPARATOR ‘:’
#endif
#ifdef DIR_SEPARATOR
/* Correct for odd directory separators */
for ( bufp = libprefix; *bufp; ++bufp ) {
if ( *bufp == ‘/’ ) {
bufp = DIR_SEPARATOR;
}
}
#endif / DIR_SEPARATOR */
}
}
static int SDL_LoadLibrary(void)
{
char *loaderror;
char library;
char libstring[BUFSIZ];
#if defined(unix) || defined(unix)
/ * /
libhandle = NULL;
/ If no X11 display, try to load fullscreen library */
if ( getenv(“DISPLAY”) == NULL ) {
static char fullscreen_libs[] = {
“mgl”, “ggi”, “fb”, “svga”, NULL
};
int i;
for ( i=0; (libhandle == NULL) && fullscreen_libs[i]; ++i ) {
sprintf(libstring, “%slibSDL%s.so.%d.%d”, libprefix,
fullscreen_libs[i],
SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
library = libstring;
libhandle = dlopen(library, RTLD_NOW);
}
}
/ If we couldn’t load fullscreen library, try X11 library */
if ( libhandle == NULL ) {
sprintf(libstring, “%slibSDLx11.so.%d.%d”, libprefix,
SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
library = libstring;
libhandle = dlopen(library, RTLD_NOW);
}
loaderror = (char )dlerror();
#elif defined(WIN32)
/ * */
char errbuf[512];
HINSTANCE DDrawDLL;
/* Clear everything out -- no default library */
library = (char *)0;
libhandle = (void *)0;
/* Version check DDRAW.DLL (Is DirectX okay?) */
DDrawDLL = LoadLibrary("DDRAW.DLL");
if ( DDrawDLL != NULL ) {
#ifdef NO_DIRECTX_HEADERS
/* Assume DirectX 5.0 or better – a bad assumption on NT */
sprintf(libstring, “%sSDL-dx5.dll”, libprefix);
library = libstring;
#else
HRESULT (WINAPI *DDrawCreate)(GUID *,LPDIRECTDRAW *,IUnknown *);
LPDIRECTDRAW DDraw;
/* Try to create a valid DirectDraw object */
DDrawCreate = (void *)GetProcAddress(DDrawDLL, "DirectDrawCreate");
if ( (DDrawCreate != NULL)
&& !FAILED(DDrawCreate(NULL, &DDraw, NULL)) ) {
if ( !FAILED(IDirectDraw_SetCooperativeLevel(DDraw,
NULL, DDSCL_NORMAL)) ) {
DDSURFACEDESC desc;
LPDIRECTDRAWSURFACE DDrawSurf;
LPDIRECTDRAWSURFACE3 DDrawSurf3;
/* Try to create a DirectDrawSurface3 object */
memset(&desc, 0, sizeof(desc));
desc.dwSize = sizeof(desc);
desc.dwFlags = DDSD_CAPS;
desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
if ( !FAILED(IDirectDraw_CreateSurface(DDraw, &desc,
&DDrawSurf, NULL)) ) {
if ( !FAILED(IDirectDrawSurface_QueryInterface(DDrawSurf,
&IID_IDirectDrawSurface3, (LPVOID *)&DDrawSurf3)) ) {
/* Yay! */
sprintf(libstring, "%sSDL-dx5.dll", libprefix);
library = libstring;
/* Clean up.. */
IDirectDrawSurface3_Release(DDrawSurf3);
}
IDirectDrawSurface_Release(DDrawSurf);
}
}
IDirectDraw_Release(DDraw);
}
#endif /* NO_DIRECTX_HEADERS */
FreeLibrary(DDrawDLL);
}
/* If we determined that the DirectX library is okay, load it! */
if ( library != (char *)0 ) {
libhandle = (void *)LoadLibrary(library);
}
/* Try loading DIB library if DirectX doesn't work */
if ( libhandle == (void *)0 ) {
sprintf(libstring, "%sSDL-dib.dll", libprefix);
library = libstring;
libhandle = (void *)LoadLibrary(library);
}
/* Generate an error message if all loads failed */
if ( libhandle == (void *)0 ) {
FormatMessage((FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_FROM_SYSTEM),
NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
errbuf, 512, NULL);
loaderror = errbuf;
} else {
loaderror = (char *)0;
}
#elif defined(BEOS)
/* * */
static image_id library_id;
/* Currenly only BWindow is supported */
sprintf(libstring, "%slibSDLbwindow.so.%d.%d", libprefix,
SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
library = libstring;
library_id = load_add_on(library);
if ( library_id == B_ERROR ) {
libhandle = (void *)0;
loaderror = "BeOS error";
} else {
libhandle = (void *)(&library_id);
loaderror = (char *)0;
}
#elif defined(macintosh)
/* * */
static CFragConnectionID library_id;
Ptr mainAddr;
Str255 errName;
OSErr error;
sprintf(libstring, "%sSDL", libprefix);
library = libstring;
error = GetSharedLibrary(C2PStr(library), kCompiledCFragArch,
kLoadCFrag, &library_id, &mainAddr, errName);
switch (error) {
case noErr:
loaderror = (char *)0;
break;
case cfragNoLibraryErr:
loaderror = "Library not found";
break;
case cfragUnresolvedErr:
loaderror = "Unabled to resolve symbols";
break;
case cfragNoPrivateMemErr:
case cfragNoClientMemErr:
loaderror = "Out of memory";
break;
default:
loaderror = "Unknown Code Fragment Manager error";
break;
}
if ( loaderror ) {
libhandle = (void *)0;
} else {
libhandle = (void *)(&library_id);
}
#endif /* system type */
if ( loaderror ) {
STUB_SetError("Failed loading %s: %s", library, loaderror);
return(-1);
}
return(0);
}
static void *SDL_LoadSym(const char *symnam)
{
char *loaderror;
void symbol;
#if defined(unix) || defined(unix)
/ * */
symbol = dlsym(libhandle, symnam);
loaderror = (char )dlerror();
#elif defined(WIN32)
/ * */
char errbuf[512];
symbol = (void *)GetProcAddress((HMODULE)libhandle, symnam);
if ( symbol == (void *)0 ) {
FormatMessage((FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_FROM_SYSTEM),
NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
errbuf, 512, NULL);
loaderror = errbuf;
} else {
loaderror = (char *)0;
}
#elif defined(BEOS)
/* * /
if ( get_image_symbol(((image_id *)libhandle),
symnam, B_SYMBOL_TYPE_TEXT, &symbol) != B_NO_ERROR ) {
symbol = (void *)0;
loaderror = “Symbol not found”;
} else {
loaderror = (char )0;
}
#elif defined(macintosh)
/ * */
CFragSymbolClass class;
if ( FindSymbol(*((CFragConnectionID *)libhandle),
C2PStr((char *)symnam), (char **)&symbol, &class) != noErr ) {
symbol = (void *)0;
loaderror = "Symbol not found";
} else {
loaderror = (char *)0;
}
#endif /* system type */
if ( loaderror ) {
STUB_SetError("Failed loading %s: %s", symnam, loaderror);
}
return(symbol);
}
static void SDL_UnloadLibrary(void)
{
/* Don’t do anything if SDL isn’t loaded */
if ( libhandle == (void *)0 ) {
return;
}
/* Unload the SDL shared library */
#if defined(unix) || defined(unix)
/* * /
dlclose(libhandle);
#elif defined(WIN32)
/ * /
FreeLibrary((HMODULE)libhandle);
#elif defined(BEOS)
/ * /
unload_add_on(((image_id )libhandle));
#elif defined(macintosh)
/ * */
CloseConnection((CFragConnectionID )libhandle);
#endif / system type */
libhandle = (void *)0;
}
static void SDL_Unload_SO(void)
{
int i;
_init_func = 0;
for ( i=0; symtab[i].symnam; ++i ) {
*symtab[i].symbol = (void *)0;
}
RESET_ERROR();
if ( (_lock_SO == 0) || ! (*_lock_SO)() ) {
SDL_UnloadLibrary();
}
}
static int SDL_Load_SO(void)
{
int i;
/* Load the SDL shared library */
RESET_ERROR();
if ( SDL_LoadLibrary() < 0 ) {
return(-1);
}
#ifdef LOAD_DEBUG
fprintf(stderr, “Loaded SDL library\n”);
#endif
/* Load the initialization code /
_init_func = (int ()(unsigned))SDL_LoadSym(“_SDL_Init”);
_quit_func = (void ()(void))SDL_LoadSym(“_SDL_Quit”);
_lock_SO = (int ()(void))SDL_LoadSym(“_SDL_LockSO”);
if ( (_init_func == 0) || (_quit_func == 0) ) {
SDL_Unload_SO();
return(-1);
}
/* Load all of the function pointers */
for ( i=0; symtab[i].symnam; ++i ) {
*symtab[i].symbol = SDL_LoadSym(symtab[i].symnam);
if ( *symtab[i].symbol == (void *)0 ) {
SDL_Unload_SO();
return(-1);
}
}
#ifdef LOAD_DEBUG
fprintf(stderr, “Loaded SDL functions\n”);
#endif
STUB_ClearError();
return(0);
}
/* Stubs that load all of our symbols and initialize the SDL library /
int SDL_Init(Uint32 flags)
{
/ Check to make sure the library isn’t already loaded /
if ( _init_func == 0 ) {
if ( SDL_Load_SO() < 0 ) {
return(-1);
}
/ Check the library version */
{ const SDL_version *lib_version = SDL_Linked_Version();
SDL_version our_version;
SDL_VERSION(&our_version);
if ( (our_version.major != lib_version->major) ||
(our_version.minor != lib_version->minor) ||
(((our_version.minor%2) != 0) &&
(our_version.patch != lib_version->patch)) ) {
fprintf(stderr,
“Warning: SDL version mismatch – expected: %d.%d.%d, loaded: %d.%d.%d\n”,
our_version.major, our_version.minor,
our_version.patch,
lib_version->major, lib_version->minor,
lib_version->patch);
}
}
}
#ifdef LOAD_DEBUG
fprintf(stderr, “Running init function: 0x%p\n”, _init_func);
#endif
return((*_init_func)(flags));
}
void SDL_Quit(void)
{
if ( _init_func != 0 ) {
(*_quit_func)();
SDL_Unload_SO();
}
}