Subject: DLL problems understood, but not solved
From: [email-masked] (Nick van Eijndhoven)

19 Mar 1997 16:56:22 -0800
Approved: [email-masked]
Distribution: cygnus
Message-ID: <[email-masked]>
Mime-Version: 1.0
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
Original-To: [email-masked]
Original-Cc: [email-masked] (Nick van Eijndhoven)
X-Mailer: ELM [version 2.4 PL25]
Original-Sender: [email-masked]

Dear GNU developers,
I think I have found the reason for my problems in creating a DLL from C++ source code
using GCC version 2.7.2-961023 under windows95
To my opinion the problems are due to the fact that currently it is not (yet)
possible to invoke a DLL from some other DLL.
This occurred in my case, since I use 'cout' in the member functions of my class
'Funcs' from which I would like to make a DLL. Due to some obscure reason, some
standard C++ stuff (like 'cout' etc...) has been put into the cygwin library with
the consequence that my DLL invokes cygwin.dll and hence produces all sorts of
cryptic errors. By changing the 'cout' into 'printf' in my member functions,
all problems were solved and the test was successfully run (thanks to the nice
examples concering relocatable DLL's from John Cerney and Gunther Ebert on the www).
Note that I can use 'cout' in my test.cc main program (since this is not in a DLL)
which confirms my diagnostics.
So to my opinion what should be done to make the GNU product usable for DLL's
is the following :

1) Move all standard C++ stuff out of cygwin and add it to libstdc++.a
   (where libstdc++.a is a normal static library).

2) Implement the possibility to invoke a DLL from another DLL.

3) Make sure that the GNU produced DLL's can be used together with the
   Microsoft visual C++ produced DLL's.
   This is vital in my case (being a member of a large high energy physics experiment
   where some packages use MS visual C++ stuff).
   
Below I will provide all the files I used to perform my tests so that you can try things
out for yourself. Note that I have used 'g++' instead of 'ld' in "dlltest.bat" which
means that automatically I get all the needed standard libs linked in.
It seems also that the extra 'ld' and 'dlltool' passes in John Cerney's example
are not needed (at least in this test case).
To see the errors appear, just change in (one of) the member functions the 'printf'
into 'cout' and include the iostream.h.

                                                              Cheers,
                                                               Nick.
*----------------------------------------------------------------------*
 Dr. Nick van Eijndhoven                Department of Subatomic Physics
 email : [email-masked]                Utrecht University / NIKHEF
 tel. +31-30-2532331 (direct)           P.O. Box 80.000
 tel. +31-30-2531492 (secr.)            NL-3508 TA Utrecht
 fax. +31-30-2518689                    The Netherlands
 WWW : http://www.fys.ruu.nl/~nick      Office : Ornstein lab. 172
 ----------------------------------------------------------------------
 tel. +41-22-7679751 (direct)           CERN PPE Division / ALICE exp.
 tel. +41-22-7675857 (secr.)            CH-1211 Geneva 23
 fax. +41-22-7679480                    Switzerland
 CERN beep : 13+7294                    Office : B 160 1-012
*----------------------------------------------------------------------*

================== dlltest.bat
@echo off
rem *** Script to create and test a relocatable GNU-Win32 DLL from *.cc files ***
rem --- The file init.cc provides the entry point for the DLL ---
rem --- Create a special file fixup.cc needed for execution of the DLL ---
echo asm (".section .idata$3\n" ".long 0,0,0,0, 0,0,0,0"); >fixup.cc
g++ -s -c Funcs.cc init.cc fixup.cc
ar rs q.a *.o
rem --- Create the .def file
echo EXPORTS >q.def
nm q.a | egrep " [CT] " | sed s/.........T._//g >q.scr
sed s/.........C._//g q.scr >>q.def
del q.scr
rem --- Create the export file to build the DLL ---
g++ -s -nostartfiles -Wl,--dll -e _dll_entry@12 -o q.dll -Wl,--base-file=q.base *.o
dlltool --def=q.def --output-exp=q.exp --dllname=q.dll --output-lib=q.a --base-file=q.base
rem --- Now actually create the DLL ---
g++ -s -nostartfiles -Wl,--dll -e _dll_entry@12  -o q.dll *.o q.exp
del fixup.cc
del *.o
del q.exp
del q.def
del q.base
echo *** mkdll done, going for test ...
g++ -s -o test.exe test.cc q.a
test
del test.exe
del q.a
del q.dll
echo *** testing done. 

============ init.cc
// Facility to provide an entry point to a DLL
#include <windows.h>
extern "C"
{
 int WINAPI dll_entry(HANDLE h, DWORD reason, void *ptr);
};

int WINAPI dll_entry(HANDLE, DWORD reason, void *)
{
 return 1;
}

============== Funcs.h
// Definitions of the functions for private test program
class Funcs
{
 public:
  Funcs();
  void aap();
  void noot();
  void mies();
};

================ Funcs.cc
//#include <iostream.h>
#include <stdio.h>
#include "Funcs.h"

Funcs::Funcs() { }

void Funcs::aap()
{
// cout << "*** aap ***" << endl;
 printf("*** aap ***\n");
}

void Funcs::noot()
{
// cout << "*** noot ***" << endl;
 printf("*** noot ***\n");
}

void Funcs::mies()
{
// cout << "*** mies ***" << endl;
 printf("*** mies ***\n");
}

============== test.cc
// Main program to test the class Funcs by using the DLL

#include <iostream.h>
//#include <stdio.h>
#include "Funcs.h"

void main()
{
 Funcs q;
 cout << "q defined" << endl;
// printf("q defined\n");
 q.aap();
 cout << "aap invoked" << endl;
// printf("aap invoked\n");
 q.noot();
 cout << "noot invoked" << endl;
// printf("noot invoked\n");
 q.mies();
 cout << "mies invoked" << endl;
// printf("mies invoked\n");
}

-
For help on using this list, send a message to
"[email-masked]" with one line of text: "help".