Subject: Re: Initialising DLLs, again
From: [email-masked] (Matthew Brett)

20 May 1998 07:17:19 -0700
Message-ID: <[email-masked]>
To: [email-masked]
Cc: [email-masked], [email-masked]

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 <[email-masked]>

   compile with gcc -c init,c
   link into DLL in the usual way (FAQ), with -e _DLLMain@12 */

#include <stdio.h>
#include <windows.h>
#include <objc/runtime.h>

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
"[email-masked]" with one line of text: "help".