This is the mail archive of the
cygwin@sourceware.cygnus.com
mailing list for the Cygwin project.
Re: Troubles with DLL's
- To: Gnu win32 <gnu-win32 at cygnus dot com>
- Subject: Re: Troubles with DLL's
- From: Kees van Veen <cvn at interchain dot nl>
- Date: Thu, 19 Feb 1998 15:49:11 +0100
- Organization: Interchain
- References: <01bd3b03$4cbdf4e0$60040d8d@ROGKOMUN> <34E94FCC.68A26580@interchain.nl>
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