From: scottc AT net-community DOT com (Scott Christley) Subject: ObjC in DLLs 8 Jun 1997 14:05:32 -0700 Approved: cygnus DOT gnu-win32 AT cygnus DOT com Distribution: cygnus Message-ID: <199706081947.MAA17063.cygnus.gnu-win32@linus.net-community.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" X-Sender: scottc AT net-community DOT com X-Mailer: Windows Eudora Light Version 1.5.2 Original-To: "Stephen Crowley" Original-Cc: Cygnus GNU-WIN32 Discussion , GNU Objective-C Discussion Original-Sender: owner-gnu-win32 AT cygnus DOT com 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 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 /* 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 AT cygnus DOT com" with one line of text: "help".