Mailing-List: contact cygwin-help AT sourceware DOT cygnus DOT com; run by ezmlm List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT sourceware DOT cygnus DOT com Delivered-To: mailing list cygwin AT sourceware DOT cygnus DOT com Date: Tue, 28 Sep 1999 17:27:38 +0300 From: Paul Sokolovsky X-Mailer: The Bat! (v1.32) UNREG / CD5BF9353B3B7091 Reply-To: Paul Sokolovsky X-Priority: 3 (Normal) Message-ID: <14727.990928@is.lg.ua> To: Mumit Khan CC: cygwin AT sourceware DOT cygnus DOT com Subject: Re: Win32 DLLs -- suggested reading list In-reply-To: <199909271933.OAA11646@mercury.xraylith.wisc.edu> References: <199909271933 DOT OAA11646 AT mercury DOT xraylith DOT wisc DOT edu> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Hello Mumit, Mumit Khan wrote: MK> I'm in the process of collecting useful articles on windows32 dynamic MK> link libraries, and so far have added 3 links that may be useful. MK> http://www.xraylith.wisc.edu/~khan/software/gnu-win32/#dllhelpers MK> If you know of other useful links, whether it is elementary or advanced, MK> please do send it to me! Inspired by DATA patch to dlltool, I've written static-to-dll howto: ------ How to build Win32 Dynamic-Loading Library (DLL) from existing static library ----------------------------------------------------------------------------- ------- Timely note: to perform steps below, you'll need dlltool with patches not yet commited to CVS. Until then, required dlltool is avaliable here: ftp://ftp.is.lg.ua/pub/gnuwin32/altbinutils/{dlltool-def.zip,bfd-dll.zip} . Note that you may want to use that dlltool only for one task - creation of def from objects and nothing else. Using current (as of 1999-10) dlltool is not acceptable and will give you problems. ------- This document describes step-by-step procedure of building Win32 DLL from static library. It suitable for both your own and third-party (i.e. ones which you know, and would like to, little about) libs. However, for your own libraries you may adopt more handy and adequate method (exporting all symbols, as done here, may be not the best solution). However, procedure given here describes easiest and fastest way if what you want is just create proper DLL and forget about it. This documets assumes that you have, or will, read documentation for Mumit Khan's dllwrappers tools (dllwrap & dlltool utilities). Before proceeding with description of process, some notes about distinction of DLLs and usual *nix-style shared libraries (.so, referred as SO below) (read also if you don't have experience with .so): [Once again note that there's a big gap between abstract information below and specific practical steps which follow; if you want to fill that gap, read standard documentation.] Theory ------ 1. Usually, compilation of objects for shared libraries requires different set of compiler options comparing to static counterparts. For example, many systems require -fpic flag to generate position-independent code. However, for Win32, both static libs and DLLs are created from the same set of objects. Despite this little advantage, DLLs have following big disadvantage: 2. Once have been created, shared libraries require no additional fuzz for usage. When so-using executable is loaded, every reference to so-symbol gets fixed up to point directly to SO. Win32 has different system: every executable importing DLL has special section, .idata, to hold pointers to imported symbols. During loading, OS loader fills this section with actual info. And application is supposed, when needed DLL-symbol, first lookup its pointer in .idata, and only then have access by that pointer, As you see, for DLL-imported symbols, additional level of indirection is required. This stems probably from dark times of real-mode 16-bit Windows, working on 8086 processor lacking virtual memory. Having all import-related stuff in one single place facilated runtime relocation, which was needed to effictively manage memory there. So or other, but it is that way. So, as you see, special compiler support required to compile client of DLL (note strange symmetry - *nix require special support to compile library, while Win32 - to compile client. Former is better, I agree). 3. As was said before, with SO you use library just as you would static version. This is not so for Win32. Win32 DLL is self-contained executable, not supposed to be linked against. Instead, client is linked with special auxilary library, called 'import library' or 'implib'. Implib contains information to properly layout .idata section to be filled in by OS loader with information about DLL. Building DLL from existing static library ----------------------------------------- We assume that you already build static lib, which we will call 'libfoo.a'. However, building yourself is not requirement, to perform these instructions, you don't needed sources of library - only library itself and its headers. 1. Fisrt step would be to create export definition file (or just def). You can do this directly from library: dlltool libfoo.a --export-all-symbols --output-def foo.def 2. Now, we can create DLL itself. This may be done by two ways: 1) link dummy file referencing each symbol in libfoo.a (created by script acting on output from 'nm libfoo.a') against libfoo.a (so, each foo's object for sure will be in foo.dll) or 2) exploding library and linking all its objects together. I consider second way cleaner and show it: mkdir tmp cp libfoo.a tmp/ cd tmp ar x libfoo.a dllwrap *.o --def ../foo.def -o ../foo.dll [usual -l libraries here] cd .. 3. Let's create implib. If you want totally transparent transition from static to DLL, call it 'libfoo.a'. However, if you want to keep destinction, 'libfoo.dll.a' is good: dlltool --def foo.def --ouput-lib libfoo.dll.a 4. Now grep foo.def for entries containing 'DATA'. If there's none - congratulations, your library uses functional-only interface and you've done. Else, most unpleasant work left - patch headers to include dllimport tag. If you want to do it once-and-for-all (you should), do following: a) make something like 'dl_import.h' and put there: ----- #if !defined(STATIC) && defined(_WIN32) #define _DL_IMPORT __delcspec(dllimport) #else #define _DL_IMPORT #endif ----- , if you want to use DLL by default (note that you will need to compile library itself with STATIC defined), or ----- #if defined(DLL) && defined(_WIN32) #define _DL_IMPORT __delcspec(dllimport) #else #define _DL_IMPORT #endif ----- , if you want to include -DDLL each time you compile DLL client. b) for each def symbol having DATA attribute, find header where its declared as extern. If that header doesn't have '#include "dl_import.h"' at the top, add it. Put '_DL_IMPORT' in front of 'extern' (strictly speaking, position matters and proper place is after both extern and type, but for data declaration above works also (at least for me)). For example, if it was extern void *(*my_malloc)(int sz); becoming _DL_IMPORT extern void *(*my_malloc)(int sz); will suffice. Procedd with next symbol. However, if you're lazy for that, you may stretch the pleasure and mark symbol as _DL_IMPORT only whenever you encounter it in undefined symbol error during linking of client. 5. That's all! Now, just compile client either as usually or with -DDLL, and link either as usually or with -lfoo.dll . Paul DOT Sokolovsky AT technologist DOT com 1999-08-28 ------ MK> Regards, MK> Mumit Best regards, Paul mailto:paul-ml AT is DOT lg DOT ua -- Want to unsubscribe from this list? Send a message to cygwin-unsubscribe AT sourceware DOT cygnus DOT com