ObjC in DLLs

Scott Christley scottc@net-community.com
Sun Jun 8 12:32:00 GMT 1997


Hi Stephen,

Sorry for the long delay in getting back to you; I guess it was more than a
couple of days :-(  I'm cross posting this to a couple mailing lists because
there may be others who are interested in this stuff.

Anyways I've been playing around with putting the ObjC runtime into a DLL
and also using other ObjC code in DLLs.  It took me some playing around, but
I finally got it to work.  Actually there was nothing special involved other
than being very pedantic about the making of the DLLs.

Here is the Makefile segment to put the ObjC runtime into a relocatable DLL;
I'm not compiling the ObjC code with -fPIC, so I don't know if there is a
problem with relocation.  I know that the GNUstep Base Library compiles all
the code with -fPIC when generating a static library on Unix systems so
maybe that will need to be done here.

# Create a relocatable DLL
libobjc.dll: $(OBJC_O) libobjc_entry.o
	$(GCC_FOR_TARGET) -dll -Wl,--base-file -Wl,libobjc.base \
		-o libobjc.dll libobjc.a libobjc_entry.o -lkernel32
	dlltool --dllname libobjc.dll --def libobjc.def --base-file \
		libobjc.base --output-exp libobjc.exp
	$(GCC_FOR_TARGET) -dll -Wl,--base-file libobjc.base libobjc.exp \
		-o libobjc.dll libobjc.a libobjc_entry.o -lkernel32
	dlltool --dllname libobjc.dll --def libobjc.def \
		--base-file libobjc.base --output-exp libobjc.exp
	$(GCC_FOR_TARGET) libobjc.exp -dll \
		-o libobjc.dll libobjc.a libobjc_entry.o -lkernel32
	dlltool --dllname libobjc.dll --def libobjc.def \
		--output-lib libobjc-dll.a

I did the building with Colin's Minimalist package which required some work
with the GCC source; libgcc.a and libobjc.a had to be compiled with the
Minimalist compiler and it's header to eliminate the Cygnus references.
Note that there are subtle but very important differences in the three
executions of GCC; if not done properly you will get a non-functional DLL.

The DLL entry file for the ObjC DLL is below, note that the asm construct at
the end of the file is absolutely required.  I don't know exactly what the
issue is; something about a section not being terminated, so I'm just
following the advise of some people on the cygwin32 mailing list and
sticking it in.

/* GNU Objective C Runtime DLL Entry
   Copyright (C) 1997 Free Software Foundation, Inc.
   Contributed by Scott Christley <scottc@net-community.com>

This file is part of GNU CC.

GNU CC is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.

GNU CC is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING.  If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.  */

/* As a special exception, if you link this library with files compiled with
   GCC to produce an executable, this does not cause the resulting executable
   to be covered by the GNU General Public License. This exception does not
   however invalidate any other reasons why the executable file might be
   covered by the GNU General Public License.  */

#include <windows.h>

/*
  DLL entry function for Objective-C Runtime library
  This function gets called everytime a process/thread attaches to DLL
  */
WINBOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call,
        LPVOID lpReserved)
{
  switch(ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
      break;
    case DLL_PROCESS_DETACH:
      break;
    case DLL_THREAD_ATTACH:
      break;
    case DLL_THREAD_DETACH:
      break;
    }
  return TRUE;
}

/*
  This section terminates the list of imports under GCC. If you do not
  include this then you will have problems when linking with DLLs.
  */
asm (".section .idata$3\n" ".long 0,0,0,0,0,0,0,0");

So I think with your simple example that you sent me; you are going to need
to create a DLL entry file like the above.  Make sure that when you generate
the DLL that you link with the ObjC DLL import library (libobjc-dll.a for
me) and not the static one; otherwise, the classes in your application won't
be initialized properly with the ObjC runtime.  The following Makefile
segment is what I used to the GNUstep Base Library into a DLL.

You can see that it is pretty similar to the Makefile fragment for the ObjC
runtime itself; except that its linking in additional libraries.  The entry
file is also there (win32-entry.o) and looks practically identical to the
ObjC one.

lib$(LIBRARY_NAME).dll: $(OBJS_INSTALL) win32-entry$(OEXT)
	# Link DLL.
	$(CC) -dll -Wl,--base-file -Wl,libgnustep-base.base \
		-o libgnustep-base.dll $(OBJS_INSTALL) win32-entry.o \
		-lmoldname -lobjc-dll -lkernel32 -lwsock32 -ladvapi32
	dlltool --dllname libgnustep-base.dll \
		--def libgnustep-base.def --base-file \
		libgnustep-base.base --output-exp libgnustep-base.exp
	$(CC) -dll -Wl,--base-file -Wl,libgnustep-base.base \
		libgnustep-base.exp \
		-o libgnustep-base.dll $(OBJS_INSTALL) win32-entry.o \
		-lmoldname -lobjc-dll -lkernel32 -lwsock32 -ladvapi32
	dlltool --dllname libgnustep-base.dll --def libgnustep-base.def \
		--base-file libgnustep-base.base \
		--output-exp libgnustep-base.exp
	$(CC) -dll libgnustep-base.exp \
		-o libgnustep-base.dll $(OBJS_INSTALL) win32-entry.o \
		-lmoldname -lobjc-dll -lkernel32 -lwsock32 -ladvapi32
	# Build the libgnustep-base-dll.a lib to link to:
	dlltool --dllname libgnustep-base.dll --def libgnustep-base.def \
		--output-lib libgnustep-base-dll.a

cheers
Scott

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



More information about the Cygwin mailing list