From: mbrett AT wren DOT rpms DOT ac DOT uk (Matthew Brett) Subject: Re: Initialising DLLs, again 20 May 1998 07:17:19 -0700 Message-ID: <199805191123.MAA19409.cygnus.gnu-win32@dopa.rpms.ac.uk> To: jeffdb AT goodnet DOT com Cc: mbrett AT wren DOT rpms DOT ac DOT uk, gnu-win32 AT cygnus DOT com Dear Mikey, Thanks again for the mail. You're quite right about not wanting to hear that I can't use the Posix emualation from within the DLL, if the DLL is used by a non-cywin app, it's a real bummer. If that's true, then it means that you can't easily use Cygwin DLLs with other programs such as Excel, Delphi, or in my case matlab, which I think is a major limitation to its application. Surely it would be possible to plumb in a mechanism within the Cygwin.dll to initialise the C runtime from a DLL? For example, Ton Overbeek has worked out a hack that gets more than halfway there (attached). Is there anyone intending to do this within the sources? Are the Cygnus team interested in this? I do think it is a significant problem... Anyway, thanks a lot for the info, Matthew > The fake _reent_data is there to keep the _reent_data in > libccrt0.o from being linked in, which pulls in the whole > libc.a initialization routine from libcygwin.a, and ends > up with either an undefined WinMainSRTStartup > or an unusable .dll. > > _reent_data can't be used by non cygwin apps, it is > the kludge that makes it possible for multiple threads > to call into newlib. > > you can build all of the rest of your app with msvc, > but the final link step of both the .dll and the .exe > MUST be done against libcygwin.a/crt0.o > using ld.exe, otherwise no libc/posix initialization is done, > and use of the standard files will give you segfaults. > > it is possible to program around this, look in the newlib source > tree or see reent.h sys/reent.h for the routines that end in _r, and don't use any of > them in your dll, or do not multithread your dll, and use the > non reent versions of these functions in newlib. see the file > .../H-i386-cygwin32/i386-cygwin32/include/reent.h on how > to build/link with libc.a directly, you lose the posix emulation, > but the routines should work. > > I know this isn't what you want to hear, but that's the way it is ;^( AFAIK ___________________________ init.c ____________________ /* Routine to initialise C runtime from DLL, when attached. Use when non-cygwin apps need to call a cygwin DLL, _not_ when DLL is used with Cygwin app (see FAQ for procedure here * By Ton Overbeek, posted by Steve Biskis compile with gcc -c init,c link into DLL in the usual way (FAQ), with -e _DLLMain AT 12 */ #include #include #include extern void __main( void ); extern struct _reent *__imp_reent_data; extern void cygwin_crt0( void *mainFunc ); static struct Globals { HANDLE cygwinDLLEvent; HANDLE cygwinDLLThread; } G; static int MLXCygwinDLLCallback( int argc, char **argv ) { __main(); // Initialize C++ runtime ... G.cygwinDLLEvent=CreateEvent(NULL,FALSE,FALSE,NULL); WaitForSingleObject(G.cygwinDLLEvent,INFINITE); return 0; } static DWORD WINAPI initCygwinDLL( void *dummy ) { cygwin_crt0(MLXCygwinDLLCallback); return 0; } BOOL WINAPI DLLMain( HANDLE h, DWORD reason, void *ptr ) { DWORD threadId; _impure_ptr=__imp_reent_data; switch ( reason ) { case DLL_PROCESS_ATTACH: G.cygwinDLLThread = CreateThread(NULL,0,initCygwinDLL,(void *)NULL,0,&threadId); SetThreadPriority(G.cygwinDLLThread,THREAD_PRIORITY_HIGHEST); break; case DLL_PROCESS_DETACH: PulseEvent(G.cygwinDLLEvent); break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; } return 1; } - For help on using this list (especially unsubscribing), send a message to "gnu-win32-request AT cygnus DOT com" with one line of text: "help".