public inbox for cygwin@cygwin.com
 help / color / mirror / Atom feed
* RE: Can't Reference Stderr from a DLL
@ 1997-03-18  9:38 Sergey Okhapkin
  1997-03-18  9:38 ` John Cerney
  0 siblings, 1 reply; 8+ messages in thread
From: Sergey Okhapkin @ 1997-03-18  9:38 UTC (permalink / raw)
  To: gnu-win32, 'John Cerney'

John Cerney wrote:
> >  nothing about it! The only way I see is to place reent_data structure 
to
> >  cygwin.dll and modify fork() code to create a copy of it in a child
> >  process...
>
> main.c calls impure_setup() in the dll with main's impure_ptr as its 
argument
>        impure_setup() in init.cc takes the impure_ptr from main and 
copies the
>        value to its (the dll's) local copy of impure_ptr.

It's not a suitable way for me :-( It requires explicit call to 
impure_setup() for _each_ project's dll! This will prevent easy porting (X 
stuff for example). If reent_data will be exported from within cygwin.dll, 
then it will be possible to write

#include <windows.h>
extern struct reent *_impure_ptr, *__imp_reent_data;
int WINAPI dll_main(HANDLE a, DWORD reason, void *q)
{ switch (reason){
   case DLL_PROCESS_ATTACH: break;
   case DLL_PROCESS_DETACH: break;
   case DLL_THREAD_ATTACH:  break;
   case DLL_THREAD_DETACH:  break;
  }
  _impure_ptr = __imp_reent_data;
  return 1;
}

and link this file to every DLL. Function dll_main (declared as entry point 
on ld's command line) will be called automatically after loading dll, and 
will set up dll's _impure_ptr right without explicit call to it! Number of 
dll's may vary - initialisation for each dll will be done automatically.

> I guess this means that I will have to create a include file that does
> something like this for every global variable I want to access:
> #define variableName  (*_imp_variableName)

This technique is used in a port of X libraries with MSVC :-)

>
> I wish there was a more transparent way of doing this. I believe VC++ 
allows
> you to access global variables to/from DLLs without going to this 
trouble. I am
> trying to build the VC++ win32 port of perl 5.003 now to verify if this 
is
> true.

VC++ requires explicit dllimport/dllexport declarations. Almost the same 
way...

--
Sergey Okhapkin
Moscow, Russia
Looking for a job.


-
For help on using this list, send a message to
"gnu-win32-request@cygnus.com" with one line of text: "help".

^ permalink raw reply	[flat|nested] 8+ messages in thread

* RE: Can't Reference Stderr from a DLL
  1997-03-18  9:38 Can't Reference Stderr from a DLL Sergey Okhapkin
@ 1997-03-18  9:38 ` John Cerney
  0 siblings, 0 replies; 8+ messages in thread
From: John Cerney @ 1997-03-18  9:38 UTC (permalink / raw)
  To: gnu-win32, Sergey Okhapkin

>
>  > main.c calls impure_setup() in the dll with main's impure_ptr as its 
>  argument
>  >        impure_setup() in init.cc takes the impure_ptr from main and 
>  copies the
>  >        value to its (the dll's) local copy of impure_ptr.
>  
>  It's not a suitable way for me :-( It requires explicit call to 
>  impure_setup() for _each_ project's dll! This will prevent easy porting (X 
>  stuff for example). If reent_data will be exported from within cygwin.dll, 
>  then it will be possible to write
> 

For my work of porting perl5.003_25 to cygwin32, this was not really a problem.
Perl uses dynamic libraries to load language extension modules. These modules
are built as DLLs and are loaded at run-time (for win32, using the
LoadLibraryEx and GetProcAddress calls) by one piece of code (dynaloader.c).
Dynaloader.c in perl is already different for each OS the language is ported
to, so it was not hard for me to add the call to impure_setup() in dynaloader.c
just after it loads the dll module.
 
>  #include <windows.h>
>  extern struct reent *_impure_ptr, *__imp_reent_data;
>  int WINAPI dll_main(HANDLE a, DWORD reason, void *q)
>  { switch (reason){
>     case DLL_PROCESS_ATTACH: break;
>     case DLL_PROCESS_DETACH: break;
>     case DLL_THREAD_ATTACH:  break;
>     case DLL_THREAD_DETACH:  break;
>    }
>    _impure_ptr = __imp_reent_data;
>    return 1;
>  }
>  
>  and link this file to every DLL. Function dll_main (declared as entry point 
>  on ld's command line) will be called automatically after loading dll, and 
>  will set up dll's _impure_ptr right without explicit call to it! Number of 
>  dll's may vary - initialisation for each dll will be done automatically.
>  

This looks like a good, clean approach, hopefully cygnus will implement
something like this.

-
For help on using this list, send a message to
"gnu-win32-request@cygnus.com" with one line of text: "help".

^ permalink raw reply	[flat|nested] 8+ messages in thread

* RE: Can't Reference Stderr from a DLL
@ 1997-03-17 14:51 Sergey Okhapkin
  1997-03-17 14:51 ` John Cerney
  0 siblings, 1 reply; 8+ messages in thread
From: Sergey Okhapkin @ 1997-03-17 14:51 UTC (permalink / raw)
  To: gnu-win32, 'John Cerney'

John Cerney wrote:
> Thanks for the input on the problem. I ended up puting in a impure_ptr
> initialization
> routine that is called by my main program before it uses any functions in 
a
> DLL.

How did you initialize _local_ for a DLL _impure_ptr? Main program knows 
nothing about it! The only way I see is to place reent_data structure to 
cygwin.dll and modify fork() code to create a copy of it in a child 
process...

> Have you had any luck exporting global data variables from/to a DLL?

Place var_name to a .def file, build a dll and import library. Now You can 
access this global data - variable __imp_var_name contains the pointer to 
var_name.

--
Sergey Okhapkin
Moscow, Russia
Looking for a job

-
For help on using this list, send a message to
"gnu-win32-request@cygnus.com" with one line of text: "help".

^ permalink raw reply	[flat|nested] 8+ messages in thread

* RE: Can't Reference Stderr from a DLL
  1997-03-17 14:51 Sergey Okhapkin
@ 1997-03-17 14:51 ` John Cerney
  0 siblings, 0 replies; 8+ messages in thread
From: John Cerney @ 1997-03-17 14:51 UTC (permalink / raw)
  To: gnu-win32, Sergey Okhapkin

>  How did you initialize _local_ for a DLL _impure_ptr? Main program knows 
>  nothing about it! The only way I see is to place reent_data structure to 
>  cygwin.dll and modify fork() code to create a copy of it in a child 
>  process...
>  

I included 3 files at the end of this message that are a simple example of the
technique I used. 
main.c : main executable; calls impure_setup with its impure_ptr as an arg
foo.c  : dll file
init.cc: dll file, contains the dll initialization functions.

main.c calls impure_setup() in the dll with main's impure_ptr as its argument
       impure_setup() in init.cc takes the impure_ptr from main and copies the
       value to its (the dll's) local copy of impure_ptr.

The Actual application I am trying to port (perl5.003_25) has one function that
loads DLLs at runtime. It was fairly simple to modify this function so that is
calls the impure_setup function just after it loads the DLLs. This solved my
problem with impure_ptr in DLLs. Now my problem is the DLLs need to access some
global variables in the perl executable. 

>  > Have you had any luck exporting global data variables from/to a DLL?
>  
>  Place var_name to a .def file, build a dll and import library. Now You can 
>  access this global data - variable __imp_var_name contains the pointer to 
>  var_name.
>  

I was afraid you were going to say that :) 
I guess this means that I will have to create a include file that does
something like this for every global variable I want to access:
#define variableName  (*_imp_variableName)

I wish there was a more transparent way of doing this. I believe VC++ allows
you to access global variables to/from DLLs without going to this trouble. I am
trying to build the VC++ win32 port of perl 5.003 now to verify if this is
true.

Thanks,

John

******************* Example Files*********************************
***** File main.c *****
// Main file to try linking with a DLL under gnuwin32

// Includes call a dll function to initialize it's impure_ptr

#include <stdio.h>

extern int doit(int, FILE *);


extern void impure_setup(struct _reent *);

int
main()
{

 
        // setup the DLLs impure_ptr:
        impure_setup(_impure_ptr);
        printf("doit(5) returns %d\n", doit(5,stderr));

}
****** File foo.c *****
// This file is one of the files that makes up foo.dll
// Test file to check out building DLLs with gnuwin32
//  This uses printf from the std lib

#include <stdio.h>


//* function declarations:  ***
int doit (int i, FILE *a);


int
doit (int i, FILE *a)
{


     printf("In foo.c inside of doit with printf\n");
     fputs("In foo.c inside of doit, with fputs main stderr\n",a);


     fputs("In foo.c inside of doit, with fputs stderr\n",stderr);
     return( 4 );
}
******* File init.cc ************
// This file is one of the one that makes up the foo.dll library
// DLL entry point module
// Added impure_ptr initialization routine. This is needed for any DLL that
needs
//   to output to the main (calling) executable's stdout, stderr, etc. This
routine
//   needs to be called from the executable using the DLL before any other DLL 
//   routines are called
#include <windows.h> 

extern "C" 
{
  int WINAPI dll_entry (HANDLE h, DWORD reason, void *ptr);
  void impure_setup(struct _reent *_impure_ptrMain);
};

struct _reent *_impure_ptr;  // this will be the Dlls local copy of impure ptr

int WINAPI dll_entry (HANDLE , 
		     DWORD reason,
		     void *)
{
  switch (reason) 
    {
    case DLL_PROCESS_ATTACH:
      break;
    case DLL_PROCESS_DETACH:
      break;
    case DLL_THREAD_ATTACH:
      break;
    case DLL_THREAD_DETACH:
      break;
    }
  return 1;
}

//
// Function to set our local (in this dll) copy of impure_ptr to the
// main's (calling executable's) impure_ptr
void impure_setup(struct _reent *_impure_ptrMain){

	_impure_ptr = _impure_ptrMain;

}
-
For help on using this list, send a message to
"gnu-win32-request@cygnus.com" with one line of text: "help".

^ permalink raw reply	[flat|nested] 8+ messages in thread

* RE: Can't Reference Stderr from a DLL
  1997-03-13  6:25 Sergey Okhapkin
@ 1997-03-17  9:29 ` John Cerney
  0 siblings, 0 replies; 8+ messages in thread
From: John Cerney @ 1997-03-17  9:29 UTC (permalink / raw)
  To: gnu-win32, Sergey Okhapkin

>  From: Sergey Okhapkin <sos@prospect.com.ru>, on 3/13/97 11:32 AM:

>  John Cerney wrote:
>  > I've run into problem trying to build a dynamic lib version of 
>  perl5.003_25.
>  >
>  > Looking at the cygwin.dll source code, it appears that stderr is 
>  translated to
>  > _impure_ptr->stderr by the defines inside of the <stdio.h> include. 
>  _impure_ptr
>  > is defined in libccrt0.cc inside of cygwin.dll, which also references 
>  main().
>  > Does the linker try to resolve all references in an object file, even if 
>  you
>  > just refer to one variable that is defined in it?
>  >
>  > I have tried building the DLL using the --noinhibit-exec linker option. 
>  The dll
>  > is built in this case, but the main.exe executable crashes with a seg 
>  fault.
>  >
>  
>  This is due to _impure_ptr in a main program and in DLL are _different_ 
>  variables! And _impure_ptr in a DLL is not initialised to point to 
>  reent_data structure in a main program. I have the same troubles with X 
>  libraries builded as DLL. I already wrote mr. Noer about this bug, no 
>  answer for a now...
>  
>  --
>  Sergey Okhapkin
>  Moscow, Russia
>  Looking for a job.
>  
>  

Thanks for the input on the problem. I ended up puting in a impure_ptr
initialization
routine that is called by my main program before it uses any functions in a
DLL. 

Now I have another problem:

Have you had any luck exporting global data variables from/to a DLL?

Dlltool seems to treat all exports as function names. i.e. they show up as 'T
_VariableName' when you do a 'nm libname.a', where libname.a is the import lib
generated by dlltool. If you do a 'nm libname.o' (libname.o is the object code
for the dll) the global variable shows up properly as 'D _VariableName'.

Thanks,

John
-
For help on using this list, send a message to
"gnu-win32-request@cygnus.com" with one line of text: "help".

^ permalink raw reply	[flat|nested] 8+ messages in thread

* RE: Can't Reference Stderr from a DLL
@ 1997-03-13  6:25 Sergey Okhapkin
  1997-03-17  9:29 ` John Cerney
  0 siblings, 1 reply; 8+ messages in thread
From: Sergey Okhapkin @ 1997-03-13  6:25 UTC (permalink / raw)
  To: gnu-win32, 'John Cerney'

John Cerney wrote:
> I've run into problem trying to build a dynamic lib version of 
perl5.003_25.
>
> Looking at the cygwin.dll source code, it appears that stderr is 
translated to
> _impure_ptr->stderr by the defines inside of the <stdio.h> include. 
_impure_ptr
> is defined in libccrt0.cc inside of cygwin.dll, which also references 
main().
> Does the linker try to resolve all references in an object file, even if 
you
> just refer to one variable that is defined in it?
>
> I have tried building the DLL using the --noinhibit-exec linker option. 
The dll
> is built in this case, but the main.exe executable crashes with a seg 
fault.
>

This is due to _impure_ptr in a main program and in DLL are _different_ 
variables! And _impure_ptr in a DLL is not initialised to point to 
reent_data structure in a main program. I have the same troubles with X 
libraries builded as DLL. I already wrote mr. Noer about this bug, no 
answer for a now...

--
Sergey Okhapkin
Moscow, Russia
Looking for a job.


-
For help on using this list, send a message to
"gnu-win32-request@cygnus.com" with one line of text: "help".

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Can't Reference Stderr from a DLL
  1997-03-12  6:22 John Cerney
@ 1997-03-12 13:11 ` Fergus Henderson
  0 siblings, 0 replies; 8+ messages in thread
From: Fergus Henderson @ 1997-03-12 13:11 UTC (permalink / raw)
  To: j-cerney1; +Cc: gnu-win32

John Cerney, you wrote:
> 
> Does the linker try to resolve all references in an object file, even if you
> just refer to one variable that is defined in it?

Yes.

-- 
Fergus Henderson <fjh@cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: < http://www.cs.mu.oz.au/~fjh >   |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3         |     -- the last words of T. S. Garp.
-
For help on using this list, send a message to
"gnu-win32-request@cygnus.com" with one line of text: "help".

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Can't Reference Stderr from a DLL
@ 1997-03-12  6:22 John Cerney
  1997-03-12 13:11 ` Fergus Henderson
  0 siblings, 1 reply; 8+ messages in thread
From: John Cerney @ 1997-03-12  6:22 UTC (permalink / raw)
  To: gnu-win32

I've run into problem trying to build a dynamic lib version of perl5.003_25.
I believe I have narrowed it down to a referencing stderr or stdout in a dll. A
simple test case which duplicates the problem is included at the end of this
message.

Specifically, if I build a dll that references stderr inside of it (like a
fputs("test out",stderr) call inside the DLL) the linker complains about
unresolved references:
libcmain.cc:29: undefined reference to `GetModuleHandleA@4'
libcmain.cc:30: undefined reference to `GetCommandLineA@0'
libcmain.cc:30: undefined reference to `WinMain@16'

When I remove the reference to stderr by replacing the fputs call with a simple
printf, the dll builds and runs fine.

Looking at the cygwin.dll source code, it appears that stderr is translated to
_impure_ptr->stderr by the defines inside of the <stdio.h> include. _impure_ptr
is defined in libccrt0.cc inside of cygwin.dll, which also references main().
Does the linker try to resolve all references in an object file, even if you
just refer to one variable that is defined in it?

I have tried building the DLL using the --noinhibit-exec linker option. The dll
is built in this case, but the main.exe executable crashes with a seg fault.

Has anyone here seen this problem before? Does anyone know what is going on?

-John

*********** Simple Test Case *******
*** file foo.c ***
// Test file to check out building DLLs with gnuwin32
//  This uses printf from the std lib

#include <stdio.h>


int
doit (int i)
{

     //printf("In foo.c inside of doit\n");  
     fputs("In foo.c inside of doit\n",stderr);
     return( 4 );
}
*** File init.cc ***
// DLL entry point module
#include <windows.h> 

extern "C" 
{
  int WINAPI dll_entry (HANDLE h, DWORD reason, void *ptr);
};

int WINAPI dll_entry (HANDLE , 
		     DWORD reason,
		     void *)
{
  switch (reason) 
    {
    case DLL_PROCESS_ATTACH:
      break;
    case DLL_PROCESS_DETACH:
      break;
    case DLL_THREAD_ATTACH:
      break;
    case DLL_THREAD_DETACH:
      break;
    }
  return 1;
}
*** File fixup.c ***

/* This is needed to terminate the list of import stuff */
/* Copied from winsup/dcrt0.cc in the cygwin32 source distribution. */
        asm(".section .idata$3\n" ".long 0,0,0,0, 0,0,0,0");
*** File Main.c ***
// Main file to try linking with a DLL under gnuwin32
int
main()
{
        printf("doit(5) returns %d\n", doit(5));
       
}

*** File buildLib ****
#! /bin/sh
# script to build the simple test case DLL and a the main executable that runs
it
#   jc 3/12/97

LIBPATH=/gnuwin32/H-i386-cygwin32/i386-cygwin32/lib

gcc -c foo.c
gcc -c init.cc
gcc -c fixup.c
echo EXPORTS > foo.def
nm foo.o init.o fixup.o | grep '^........ [T] _' | sed 's/[^_]*_//' >> foo.def

# Link DLL.
ld --base-file foo.base --dll -o foo.dll foo.o init.o fixup.o \
 $LIBPATH/libcygwin.a -e _dll_entry@12 --noinhibit-exec
dlltool --as=as --dllname foo.dll --def foo.def --base-file foo.base
--output-exp foo.exp
ld --base-file foo.base foo.exp --dll -o foo.dll foo.o init.o fixup.o \
  $LIBPATH/libcygwin.a -e _dll_entry@12 --noinhibit-exec
dlltool --as=as --dllname foo.dll --def foo.def --base-file foo.base
--output-exp foo.exp
ld foo.exp --dll -o foo.dll foo.o init.o fixup.o\
 $LIBPATH/libcygwin.a -e _dll_entry@12 --noinhibit-exec

# Build the foo.a lib to link to:
dlltool --as=as --dllname foo.dll --def foo.def --output-lib foo.a

# Linking with main
gcc main.c foo.a -o main.exe

-
For help on using this list, send a message to
"gnu-win32-request@cygnus.com" with one line of text: "help".

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~1997-03-18  9:38 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1997-03-18  9:38 Can't Reference Stderr from a DLL Sergey Okhapkin
1997-03-18  9:38 ` John Cerney
  -- strict thread matches above, loose matches on Subject: below --
1997-03-17 14:51 Sergey Okhapkin
1997-03-17 14:51 ` John Cerney
1997-03-13  6:25 Sergey Okhapkin
1997-03-17  9:29 ` John Cerney
1997-03-12  6:22 John Cerney
1997-03-12 13:11 ` Fergus Henderson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).