This is the mail archive of the cygwin@sourceware.cygnus.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Troubles with DLL's


root@jacob.remcomp.fr wrote:

> Look, if you care to read this mailing list you will remember that roger
> (roger@isp-uni-kassel.de) complained in a message sent on Feb 16th that
> static data is totally messed up when linking dlls.

> Nobody answered that message.

> And that message is only the last one of an unendless series.

> But go on then. I didn't say anything. The linker is O.K., wonderful.


Well, maybe I should've send the message to the list as well. I
apologize.
Kees


Roger René Kommer wrote:
>
> Hi,
> I?m playing around with dll?s, but received several troubles with static and
> global data defined in the dll.
> In a little less complex situation (only one dll or without the static
> data), the binaries works like expected.
> 

Hi, I've been wrestling with DLL's some time ago and have a script that
does everything for me, including producing relocatable DLL's. I'm
running programs with 5 relocatable DLL's without problems. I'm using
the latest coolview on NT4 SP3 and Windows 95.
 
I've attached two scripts (all stolen from Makefile.DLLs by Fergus
Henderson, see the Cygnus page):
 
         umakedll        to produce relocatable DLLs
         getglobals      a script to locate global variables and to
transform them
			 into a function-like macros (the macros should be used by the
programs 
			 or objects that use the global variables, not by the routines in the
DLL - 
			 check the #ifdef libname_DLL)

Furthermore I have trouble with environment variables. I think that's
caused because the umakedll script links with -lc -lcygwin -lkernel -lc,
which get getenv() from libc instead of winsup (coolview version), so
in order to use environment variables from within the DLL I have
redefined, so I do
 
#ifdef __CYGWIN32__
#define execvp  _execvp
#define execv   _execv
#define execl   _execl
#define system  _system
#define getenv  _getenv
#define putenv  _putenv
#endif /* __CYGWIN32__ */
 
#endif /* UCYGWIN32_H */
 
If you want to run on Windows95 you have to adjust the relocation
section with a program called dllfix.exe.
I've included that as well.

Hope this helps,
Kees
#! /bin/sh
#	Script to compile and link a relocatable DLL
#	For usage see below
#
#	Files that make up the DLL = $* and $DLLENTRY.cc $FIXUP.c.
#	($DLLENTRY.cc and $FIXUP.c are housekeeping routines needed for the DLL.

if [ "$1" = "-g" ]; then DEBUG="-g"; fi
if [ "$1" = "-s" ]; then USRLIBS="$2"; shift; shift; fi

if [ "$4" = "" ]
then
	echo "Usage: `basename $0` [-g] [-s link-opts] dirname libname libsuffix object..."
	exit 1
fi

DIR=$1;
LIB=$2;
LIBSUFFIX=$3;
shift; shift; shift;

SYSLIBS="$USRLIBS -L`dirname \`gcc -print-file-name=libcygwin.a |
	sed -e 's@^\\\\([A-Za-z]\\\\):@//\\\\1@g' -e 's@\\\\\\\\@/@g' \` `
	-lc -lcygwin -lkernel32 -lc"
DLLENTRY=dllentry
FIXUP=dllfixup

# Generate an entry point routine
echo '
#include <stdio.h>
#include <windows.h> 
extern "C" 
{
	extern struct _reent *_impure_ptr;
	extern struct _reent *__imp_reent_data;
	__attribute__((stdcall))
	int WINAPI dll_entry (HANDLE h, DWORD reason, void *ptr);
};

int WINAPI dll_entry (HANDLE, DWORD reason, void*)
{
	_impure_ptr=__imp_reent_data;

	switch (reason) 
	{
	case DLL_PROCESS_ATTACH: break;
	case DLL_PROCESS_DETACH: break;
	case DLL_THREAD_ATTACH: break;
	case DLL_THREAD_DETACH: break;
 	}
	return 1;
}
' >$DLLENTRY.cc

# This is needed to terminate the list of import stuff */
# Copied from winsup/dcrt0.cc in the cygwin32 source distribution. */
echo '	asm(".section .idata$3\n" ".long 0,0,0,0, 0,0,0,0");' > $FIXUP.c

# Compile the generated sources
gcc -c $DLLENTRY.cc $FIXUP.c

# Make .def file:
echo EXPORTS > $LIB.def
nm $* $DLLENTRY.o $FIXUP.o |
grep '^........ [BCDRT] _' |
sed 's/[^_]*_//' >> $LIB.def

# Link DLL.

ld $DEBUG --base-file $LIB.base --dll -o $DIR/$LIB.dll_new \
	$DLLENTRY.o $FIXUP.o $* $SYSLIBS -e _dll_entry@12 

dlltool --as=as --dllname $LIB.dll --def $LIB.def \
	--base-file $LIB.base --output-exp $LIB.exp

ld $DEBUG --base-file $LIB.base $LIB.exp --dll -o $DIR/$LIB.dll_new \
	$DLLENTRY.o $FIXUP.o $* $SYSLIBS -e _dll_entry@12 

dlltool --as=as --dllname $LIB.dll --def $LIB.def \
	--base-file $LIB.base --output-exp $LIB.exp

ld $DEBUG $LIB.exp --dll -o $DIR/$LIB.dll_new $DLLENTRY.o $FIXUP.o $* \
	$SYSLIBS -e _dll_entry@12 

dllfix $DIR/$LIB.dll_new >/dev/null 2>&1

# Build the $LIB.a lib to link to:
dlltool --as=as --dllname $LIB.dll --def $LIB.def \
	--output-lib $DIR/$LIB$LIBSUFFIX

if [ -f $DIR/$LIB.dll ]
then
	mv -f $DIR/$LIB.dll $DIR/$LIB.dll_old
fi
mv -f $DIR/$LIB.dll_new $DIR/$LIB.dll

rm -f $DLLENTRY.cc $DLLENTRY.o $FIXUP.c $FIXUP.o \
	$LIB.base $LIB.exp $LIB.def
if [ "$1" = "" ]
then
	echo Usage: $0 libname
	exit 1
fi

SYM_PREFIX=$1
GUARD_MACRO=${SYM_PREFIX}_GLOBALS_H
DEFINE_DLL_MACRO=${SYM_PREFIX}_DEFINE_DLL
USE_DLL_MACRO=${SYM_PREFIX}_USE_DLL
IMP_MACRO=${SYM_PREFIX}_IMP
GLOBAL_MACRO=${SYM_PREFIX}_GLOBAL
IMPURE_PTR=${SYM_PREFIX}_impure_ptr

echo "
#ifndef ${GUARD_MACRO}
#define ${GUARD_MACRO}
#if defined(__GNUC__) && defined(__CYGWIN32__)
#if defined(${USE_DLL_MACRO})
	#define ${IMP_MACRO}(name)	__imp_##name
	#define ${GLOBAL_MACRO}(name)	(*${IMP_MACRO}(name))
	#include \"${SYM_PREFIX}_globals.h\"
#endif /* ${USE_DLL_MACRO} */
#endif /* __GNUC__ && __CYGWIN32__ */

#endif /* ${GUARD_MACRO} */"	> ${SYM_PREFIX}_dll.h

for sym in ${IMPURE_PTR} \
	`nm $1.a | grep '^........ [BCDR] _' | sed 's/[^_]*_//'`;
do
	echo "#define $sym	${GLOBAL_MACRO}($sym)"
done > ${SYM_PREFIX}_globals.h

dllfix.exe.gz


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]