Shared libraries

Hi,

I’m new to this list, and I was wondering what the current
thinking/status of a few things are (sorry if I might repeat some things):

  1. Cross platform shared library support? If it’s bad, I might write
    something up.

  2. For the SDL_net maintainer, hows the SDL_net?

  3. On MacOS. I understand that there is no threading support. How does
    SDL act if you try to create threads anyway on Mac OS9? Does it instead
    preform some sort of forking, or does it just segfault?

Thanks in advance.

–sea

Brian Sea wrote:

  1. Cross platform shared library support? If it’s bad, I might write
    something up.

everything that libtool can. see http://www.gnu.org/software/libtool and
it’s http://www.gnu.org/software/libtool/manual.html#Tested%20platforms

Note that SDL ships with a patched libtool (1.3.5) - Sam’s win32
patches were later integrated into libtool (and I’m fixing the crossgcc
bugs in libtool 1.4 now…) It’s not that bad, but if you have some
experience we’d welcome your help - the current libtool-1.4b has seen
some changes to support other languages/compilers (than C/gcc) better
than before but at the same time it broke in some other places - and
therefore, if you sharedlib knowledge goes beyond C/gcc then I can
only hope to see you on the show. :wink:

everything that libtool can. see http://www.gnu.org/software/libtool and
it’s http://www.gnu.org/software/libtool/manual.html#Tested%20platforms

I’m sorry, I wasn’t clear. I meant dynamic library support. UNIX uses
dlopen while Win32 use LoadLibrary, type of thing.

–sea

Hi,

I’m new to this list, and I was wondering what the current
thinking/status of a few things are (sorry if I might repeat some things):

  1. 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.

  1. For the SDL_net maintainer, hows the SDL_net?

It’s okay. The latest release supports MacOS X and MacOS classic.

  1. On MacOS. I understand that there is no threading support. How does
    SDL act if you try to create threads anyway on Mac OS9? Does it instead
    preform some sort of forking, or does it just segfault?

It returns an error.

See ya,
-Sam Lantinga, Software Engineer, Blizzard Entertainment

Any ideas where I can get an API for this then? i would just want to pull
out the shared library code so I could included it. There’s no point in me
rewriting it then, and I’m not wanting to try to write to SDL 1.3 :slight_smile:

–seaOn Wed, Aug 01, 2001 at 06:21:53AM -0700, Sam Lantinga wrote:

Hi,

I’m new to this list, and I was wondering what the current
thinking/status of a few things are (sorry if I might repeat some things):

  1. 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.

Brian Sea wrote:

Hi,

I’m new to this list, and I was wondering what the current
thinking/status of a few things are (sorry if I might repeat some things):

  1. 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.

Any ideas where I can get an API for this then? i would just want to pull
out the shared library code so I could included it. There’s no point in me
rewriting it then, and I’m not wanting to try to write to SDL 1.3 :slight_smile:

libtool does come with libltdl - a dl-lib that is tightly
integrated with the libtool project, so that it support even
has a thing called dlpreopen to support sharedlib style on those
platforms that don’t have a dynamic linker in the system.

http://www.gnu.org/software/libtool/manual.html#Using%20libltdl

The bad thing about it: it is not multithreaded, and for all its
features it is not a lighweight. The latter has been making it a
problem to bring around the characteristic mentioned first :wink:

If you want to use a dl-API with SDL alone, I’d rather recommend
to wait for Sam’s code - all platforms that SDL runs on do actually
support some kind of dl-scheme, so the wrapper can be pretty
lightweight to some degree (apart from ensuring multithreading).

I have to admit that I did write may own dl-wrapper for a project
of mine - I have looked into about a dozen projects adressing dl
functions but most of them are not the modular design that I did
need (so I can add vxworks support in there), and for the most
part not multithreaded, and it happens that an emulation for a
multithreading dl-API on top of a non-multithreading one simply
needs to maintain a global module-table which in turn needs
mutexes which in turn is a very platform dependent thing which
in turn is already wrapped through SDL.

cheers, Guido> On Wed, Aug 01, 2001 at 06:21:53AM -0700, Sam Lantinga wrote:

  1. 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?

thanks,
–sea

  1. 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();
}
}