Subject: RE: Can't Reference Stderr from a DLL
From: [email-masked] (John Cerney)

17 Mar 1997 18:57:33 -0800
Approved: [email-masked]
Distribution: cygnus
Message-ID: <[email-masked]>
Reply-To: John Cerney <[email-masked]>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7Bit
X-Mailer: BeyondMail for Windows/Professional 2.3
Original-To: "[email-masked]" <[email-masked]>,
        Sergey Okhapkin
	<[email-masked]>
X-BeyondMail-Priority: 1
Conversation-ID: <01BC332D.57BADC20@sos>
In-Reply-To: <01BC332D.57BADC20@sos>
X-Receipt-From-Agent: true
Original-Sender: [email-masked]

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