From xemacs-m  Thu May  8 13:43:45 1997
Received: from newman.aventail.com (root@newman.aventail.com [199.238.236.1])
	by xemacs.org (8.8.5/8.8.5) with ESMTP id NAA00171
	for <xemacs-beta@xemacs.org>; Thu, 8 May 1997 13:43:44 -0500 (CDT)
Received: from kramer.in.aventail.com.aventail.com (wmperry@[192.168.1.12])
	by newman.aventail.com (8.8.5/8.8.5) with SMTP id LAA29538;
	Thu, 8 May 1997 11:43:37 -0700 (PDT)
Date: Thu, 8 May 1997 11:43:37 -0700 (PDT)
Message-Id: <199705081843.LAA29538@newman.aventail.com>
From: "William M. Perry" <wmperry@aventail.com>
MIME-Version: 1.0
Content-Type: multipart/mixed;
	boundary="5C0oQCs0zNVa/mF/azJsAQ8UF6Gjaw3Tzs7Duo3h"
Content-Transfer-Encoding: 7bit
To: Marius Vollmer <mvo@zagadka.ping.de>
cc: xemacs-beta@xemacs.org
Subject: Re: Dynamic linking code (was: Re: images in xemacs)
References: <199704200123.VAA11839@hal.cs.unh.edu> 	<kig2086iib9.fsf@jagor.srce.hr> <335BC56C.E6B4E4D3@netscape.com> 	<kigg1wjsdxy.fsf@jagor.srce.hr> <335FD35F.ED2675C0@netscape.com> 	<199704301615.SAA19888@boffi95.stru.polimi.it> 	<kigenbsjn6e.fsf@jagor.srce.hr> <3367CFBB.748BCFCD@netscape.com> 	<86iv13wwrj.fsf@wmperry.oz.net> <m2d8rac0gd.fsf_-_@zagadka.ping.de> 	<86911t8w2z.fsf@kramer.in.aventail.com> <m2pvv241dc.fsf@zagadka.ping.de>
Errors-to: wmperry@aventail.com
Reply-to: wmperry@aventail.com
X-Face: O~Rn;(l][/-o1sALg4A@xpE:9-"'IR[%;,,!m7</SYF`{vYQ(&RI1&EiH[FvT;J}@f!4kfz
 x_!Y#=y{Uuj9GvUi=cPuajQ(Z42R[wE@{G,sn$qGr5g/wnb*"*ktI+,CD}1Z'wxrM2ag-r0p5I6\nA
 [WJopW_J.WY;


--5C0oQCs0zNVa/mF/azJsAQ8UF6Gjaw3Tzs7Duo3h
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Marius Vollmer <mvo@zagadka.ping.de> writes:

> > > I would like to get your code for Guile, the Scheme thing of the FSF.  It
> > > supports dynamic linking, but only for dlopen, dld and HP/UX.
> > > 
> > > It would be great, if you could contribute your code to the Guile
> > > project.
> > 
> >   Gladly, but it wouldn't add support for anything but windows from the
> > sounds of it (and an abstract api instead of a bunch of #ifdef HAVE_DLOPEN
> > all over the code).  I'll try to whip it into shape wednesday night, my
> > wife is leaving a week earlier than I am for visiting my new niece, so I'll
> > have lots of free time. :)
> 
> Great!

  How's this look?  Basic usage would be:

main() needs to call dll_init(argv[0])
h = dll_open(fname)
f = dll_function(h,"foo")
f()
dll_close(h)

The DLD stuff is untested, as all the systems I use have one of the other
supported ways of loading libraries (~13 diff. systems).  

To link a .so file, you would do:

CFLAGS=$(CFLAGS) $(SHLIB_CFLAGS)
foo.so: $(FOO_OBJS)
	$(SHLIB_LD) -o $@ $(SHLIB_LFLAGS) $(FOO_OBJS) $(LIBS)

Under AIX, you would also need a foo.exp, that lists all the exported
symbols from the dll.  sysdll.m4 is an autoconf stub for figuring out what
CFLAGS, LDFLAGS, etc. to use.

I haven't actually compiled this just yet, its a modified version of some
old code I had laying around, but it should work.  My blanket disclaimer
for Emacs related work should cover this, as I intend for it to go in Emacs
and XEmacs hopefully. :)

-Bill P.


--5C0oQCs0zNVa/mF/azJsAQ8UF6Gjaw3Tzs7Duo3h
Content-Type: text/plain
Content-Disposition: inline;
	filename="sysdll.h"
Content-Transfer-Encoding: 7bit

#ifndef _SYSDLL_H
#define _SYSDLL_H

#ifdef __cplusplus
extern "C" {
#endif

#if defined(WIN32)
#define DLLEXPORT __declspec(dllexport)
#elif defined(_WINDOWS)
#define DLLEXPORT FAR PASCAL _EXPORT
#else
#define DLLEXPORT
#endif

typedef void * dll_handle;
typedef void * dll_func;
typedef void * dll_var;

int dll_init(char *);
int dll_shutdown(void);
dll_handle dll_open(const char *);
int dll_close(dll_handle);
dll_func dll_function(dll_handle,const char *);
dll_var dll_variable(dll_handle,const char *);
const char *dll_error(dll_handle);

#ifdef __cplusplus
}
#endif

#endif /* _SYSDLL_H */


--5C0oQCs0zNVa/mF/azJsAQ8UF6Gjaw3Tzs7Duo3h
Content-Type: text/plain
Content-Disposition: inline;
	filename="sysdll.c"
Content-Transfer-Encoding: 7bit

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <sysdll.h>

/* This whole file is conditional upon HAVE_DLL */
#ifdef HAVE_DLL

/* Thankfully, most systems follow the ELFish dlopen() method.
** HAVE__DLOPEN is lame, but SCO has their dl* functions as _dl*, and
** unless you include dlfcn.h you don't get the macros to mask them, and
** autoconf fails to find them.
**
** Anybody who wants to use this on SCO needs to have their configure.in
** look for _dlopen() as well as dlopen()
*/
#if defined(HAVE_DLOPEN) || defined(HAVE__DLOPEN)
#include <dlfcn.h>

#ifndef RTLD_LAZY
#define RTLD_LAZY 1
#endif /* RTLD_LAZY isn't defined under FreeBSD - ick */

int dll_init(char *arg) {
  return(0);
}

dll_handle dll_open(const char *fname) {
  return((dll_handle)dlopen(fname,RTLD_LAZY));
}

int dll_close(dll_handle h) {
  return(dlclose((void *)h));
}

dll_func dll_function(dll_handle h,const char *n) {
#ifdef DLSYM_NEEDS_UNDERSCORE
    char buf[1024];
    *buf = '_';
    (void)strcpy(buf + 1, n);
    n = buf;
#endif
  return((dll_func)dlsym((void *)h,n));
}

dll_var dll_variable(dll_handle h,const char *n) {
  return((dll_var)dlsym((void *)h,n));
}

const char *dll_error(dll_handle h) {
#ifdef HAVE_DLERROR
  return((const char *)dl_error());
#else
  return("Shared library error");
#endif
}

#elif defined(HAVE_SHL_LOAD)
/* This is the HP/UX version */
#include <dl.h>
int dll_init(char *arg) {
  return(0);
}

dll_handle dll_open(const char *fname) {
  return((dll_handle)shl_load(fname,BIND_DEFERRED,0L));
}

int dll_close(dll_handle h) {
  return (shl_unload((shl_t)h));
}

dll_func dll_function(dll_handle h,const char *n) {
  long handle = 0L;

  if (shl_findsym(&(shl_t)h,n,TYPE_PROCEDURE,&handle))
    return(NULL);

  return((dll_func)handle);
}

dll_var dll_variable(dll_handle h,const char *n) {
  long handle = 0L;

  if (shl_findsym(&(shl_t)h,n,TYPE_DATA,&handle))
    return(NULL);

  return((dll_var)handle);
}

const char *dll_error(dll_handle h) {
  return("Generic shared library error");
}

#elif defined(HAVE_INIT_DLD)
#include <dld.h>
int dll_init(char *arg) {
  char *real_exe = dld_find_executable(arg);
  int rc;

  rc = dld_init(real_exe);
  if (rc) {
    dld_perror (exe);
    return(-1);
  }
  return(0);
}

dll_handle dll_open(const char *fname) {
  rc = dld_link(fname);
  if (rc) {
    return (NULL);
  }
  return((dll_handle)1);
}

int dll_close(dll_handle h) {
  /* *sigh* DLD is pretty lame and doesn't return a handle that you can use
  ** later on to free the file - you have to remember the filename and
  ** use that as the unlinker.  We should eventually keep a linked list
  ** of loaded modules and then use the node pointer as the unique id
  ** for the shared library.  Wheeee.  But not now.
  */
  return(1);
}

DLL_FUNC dll_function(dll_handle h,const char *n) {
  return (dld_get_func(n));
}

DLL_FUNC dll_variable(dll_handle h,const char *n) {
  return (dld_get_symbol(n));
}
#elif defined(_WINDOWS) || defined(WIN32)
int dll_init(char *arg) {
  return(0);
}

dll_handle dll_open(const char *fname) {
  return((dll_handle)LoadLibrary(fname));
}

int dll_close(dll_handle h) {
  return(FreeLibrary(h));
}

dll_func dll_function(dll_handle h,const char *n) {
  return((dll_func)GetProcAddress(h,n));
}

dll_func dll_variable(dll_handle h,const char *n) {
  return((dll_func)GetProcAddress(h,n));
}

const char *dll_error(dll_handle h) {
  return("Windows DLL Error");
}
#else
/* Catchall if we don't know about this systems method of dynamic loading */
int dll_init(char *arg) {
  return(-1);
}

dll_handle dll_open(const char *fname) {
  return(NULL);
}

int dll_close(dll_handle h) {
  return(0);
}

dll_func dll_function(dll_handle h,const char *n) {
  return(NULL);
}

dll_func dll_variable(dll_handle h,const char *n) {
  return(NULL);
}

const char *dll_error(dll_handle h) {
  return("Shared libraries not implemented on this system.");
}
#endif /* System conditionals */

#endif /* HAVE_SHLIB */

--5C0oQCs0zNVa/mF/azJsAQ8UF6Gjaw3Tzs7Duo3h
Content-Type: text/plain
Content-Disposition: inline;
	filename="sysdll.m4"
Content-Transfer-Encoding: 7bit

AC_DEFUN(AC_MAKE_SHAREDLIB, [
SHLIB_LD="ld"
SHLIB_LFLAGS="-shared"
SHLIB_CFLAGS="-r"
SHLIB_OFLAGS="-o "

AC_MSG_CHECKING(shared library support)
case `uname -rs` in
	UNIX_SV*|UNIX_System_V*)
		SHLIB_LFLAGS="-G"
		SHLIB_CFLAGS=-Kpic
		SHLIB_LD="ld"
		;;
	BSD/OS*)
		SHLIB_CFLAGS=
		SHLIB_LFLAGS="-r"
		SHLIB_LD="shlicc2"
		;;
	FreeBSD*2*)
		SHLIB_LFLAGS="-Bshareable"
		SHLIB_CFLAGS="-fPIC -DPIC"
		SHLIB_LD=ld
		PRELOADS="LD_PRELOAD"
		;;
	SunOS*4.*)
 		SHLIB_CFLAGS="-P"
		SHLIB_LFLAGS="-dp -assert pure-text -assert nodefinitions"
		PRELOADS="LD_PRELOAD"
		;;
	SunOS*5.*)
		SHLIB_LD="cc"
		SHLIB_CFLAGS="-KPIC"
		SHLIB_LFLAGS="-G"
		SHLIB_OFLAGS="-W0,-y-o -W0,-y"
		PRELOADS="LD_PRELOAD"
		;;	
	IRIX*5.*|IRIX*6.*)
		SHLIB_CFLAGS="-KPIC"
		PRELOADS="_RLD_LIST"
		PRELOADA=":DEFAULT"
		;;
	OSF1*)
		;;
	HP-UX*)
		SHLIB_LD="ld"
		SHLIB_LFLAGS="-b"
		SHLIB_CFLAGS="+z"
		;;
	SCO_SV*)
		SHLIB_LD="ld"
		SHLIB_LFLAGS="-G"
		SHLIB_CFLAGS="-Kpic"
		;;
	AIX*)
		SHLIB_LFLAGS="-H512 -T512 -bhalt:4 -bM:SRE -bE:\${@:.so=.exp} -b noentry -lc"
		SHLIB_LD="ld"
		;;
	*)
		;;
	esac

	if test "$CC" = "gcc" ; then
		SHLIB_CFLAGS="-fPIC"
		case `uname -rs` in
		SunOS*5.*)
			SHLIB_LD="ld"
			SHLIB_OFLAGS="-o "
			SHLIB_LFLAGS="-G"
			;;
		SCO_SV*)
			SHLIB_LD="ld"
			SHLIB_LFLAGS="-G"
			SHLIB_CFLAGS="-b elf"
			;;
		FreeBSD*)
			SHLIB_CFLAGS="-DDLSYM_NEEDS_UNDERSCORE -DPIC -fPIC"
			SHLIB_LFLAGS="-Bshareable"
			SHLIB_LD=ld
			;;
		BSD/OS*)
			SHLIB_CFLAGS=
			SHLIB_LFLAGS="-r"
			SHLIB_LD="shlicc2"
			;;
		UNIX_SV*)
			SHLIB_CFLAGS="-fPIC"
			;;
		*)
			SHLIB_LD="gcc"
			SHLIB_LFLAGS="-shared"
		esac
	fi

	AC_MSG_RESULT("lflags: $SHLIB_LFLAGS cflags: $SHLIB_CFLAGS")
else
	AC_MSG_RESULT(no)
fi
AC_SUBST(SHLIB_LD)
AC_SUBST(SHLIB_CFLAGS)
AC_SUBST(SHLIB_OFLAGS)
AC_SUBST(SHLIB_LFLAGS)
])dnl

--5C0oQCs0zNVa/mF/azJsAQ8UF6Gjaw3Tzs7Duo3h--

