How to build a DLL

 


0. Before starting your DLL, be sure that the functions that you want to export (those that will be called by Windows or other application) DON'T have any modifier like _export or even WINAPI or CALLBACK (in the h, c or cpp code).

Functions with WINAPI or CALLBACK modifier are exported internally, so if you export then again in the DEF file, the DLL will not work or even be build, and you NEED a DEF file to build a DLL, as dlltool needs it.

You also need an entry point in the DLL prototyped as:
int WINAPI DllMain(HANDLE hDll, DWORD reason, LPVOID reserved);

Some use dllentry, dll_entry or else for the name of the function, but it don't matters as long as you tell the linker (and you MUST) which name it is. This funtion initializes the DLL when it is loaded (any Win32 reference explains it in detail), but the only thing you must remember about it it's just to return TRUE.

1. Compile al your files as usually
gcc -c mydll.c

2. Compile fixup.c (or add it to one of your sources):
file fixup.c:
#ifdef __GNUC__
/*
* 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");
#endif

3. Optionally, If you have more than one file to build the DLL, 
put then together in a library:
ar rc temp.a

4. Make a DEF file. You can do it manually (glups!) or use this:
echo EXPORTS > mydll.def
nm | grep " [TC] " | sed '/ _/s// /' | awk '{print $3;}' >> mydll.def
nm | grep '^........ [T] _' | sed 's/[^_]*_//' >> mydll.def

if necessary, edit the DEF file to make sure that includes only those functions that will be really called by Windows to avoid extra overhead in the entry/exit code for the function.

5. Build the DLL using one of the procedures listed below. The first is like the one used to build CYGNUS.DLL. Both seems to produce the same code, but the second is faster. Folow these instructions when using any of them:
- library names must be in the form
$LIBPATH/libxxx.a (this is, the true name as $LIBPATH/libcygwin.a)
or tell the linker where they are
-L/path/for/my/libs -lmylib (whithout libxxx or .a as -lcygwin)
- the entry point is declared as
-e _entrypoint@12 (both, the underscore and the @12 are needed)
- if you build a GUI DLL, be sure to declare it at the BEGINING of every
linker line as in
ld --dll --subsystem windows -e _DllMain@12 ....

- a) 6 steps procedure (in an example to build a console DLL)
----------------------------------------------------------
ld --base-file mydll.base --dll -o mydll.dll \
<$LIBPATH/libname> -e _DllMain@12
dlltool --as=as --dllname mydl.dll --def mydll.def --base-file \
mydll.base --output-exp mydll.exp
ld --base-file mydll.base mydll.exp --dll -o mydll.dll \
<$LIBPATH/libname> -e _DllMain@12
dlltool --as=as --dllname mydll.dll --def mydll.def --base-file \
mydll.base --output-exp mydll.exp
ld mydll.exp --dll -o mydll.dll \
<$LIBPATH/libname> -e _DllMain@12
dlltool --as=as --dllname mydll.dll --def mydll.def --output-lib mydll.a

- b) 3 steps procedure (in an example to build a GUI DLL)
-------------------------------------------------------
ld --dll --subsystem windows -e _DllMain@12 -o jnk --base-file \
mydll.base
dlltool --dllname mydll.dll --base-file mydll.base --def mydll.def \
--output-lib mydll.a --output-exp mydll.exp
ld --dll --subsystem windows -e _DllMain@12 -o mydll.dll \
mydll.exp
rm jnk mydll.base mydll.exp

6. Now you have mydll.dll and mydll.a. With the source files given below, you can compile appa and appb this way:
gcc -c appa.c appb.c
gcc -o appa appa.o -mwindows --subsystem windows
gcc -o appb appb.o mydll.a -mwindows --subsystem windows
- appa is a program that loads mydll.dll dinamically at runtime, so it don't have
to be linked with mydll.a
- appb is a program linked with mydll.a
- both are GUI apps.
-------------------------------------------------------------------------------------
MYDLL.H
-------------------------------------------------------------------------------------
#include

typedef void (*foop)();
void foof();

-------------------------------------------------------------------------------------
MYDLL.C
-------------------------------------------------------------------------------------
#include "mydll.h"

int WINAPI DllMain(HINSTANCE H, DWORD d, PVOID p) {
MessageBox(NULL, "Hello from DllMain", "DLL", MB_OK);
return TRUE;
}

void foof() {
MessageBox(NULL, "Hello from foof", "DLL", MB_OK);
}

// note that I include directly the code of fixup.c
asm (".section .idata$3\n" ".long 0,0,0,0,0,0,0,0");

-------------------------------------------------------------------------------------
MYDLL.DEF
-------------------------------------------------------------------------------------
EXPORTS
foof
-------------------------------------------------------------------------------------
APPA.C
-------------------------------------------------------------------------------------
#include
#include "mydll.h"

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR 
szCmdLine, int iCmdShow) {
HANDLE dllh;
foop foo;
char buf[126];
dllh=LoadLibrary("mydll.dll");
if ((UINT)dllh <= HINSTANCE_ERROR){
sprintf(buf,"Error loading dll: %d", dllh);
MessageBox(NULL, buf, "APP", MB_OK);
}
else {
foo=(foop)GetProcAddress(dllh, "foof");
if (foo==NULL)
MessageBox(NULL, "foo == null", "APP", MB_OK);
else
foo();
}
if ((UINT)dllh > HINSTANCE_ERROR)
FreeLibrary(dllh);
return 0;
}

-------------------------------------------------------------------------------------
APPB.C
-------------------------------------------------------------------------------------
#include "mydll.h"

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR 
szCmdLine, int iCmdShow) {
foof();
return 0;
};



How to run a DOS command at background

You create a batch file, say, bg.bat in your path directory, e.g. C:\WINNT, with the following content:

@echo off
start /B %1 %2 %3 %4 %5 %6 %7 %8 %9
:end

And you can run any dos command at background. To do it, you need to type

\>bg command

For example:

\>bg perl nasdaq.pl >output

 


Format Number Strings

 

If you want to copy a number to String w/ certain characters, you can use wsprintf w/ certain options. For example, you want to get a "00050" for an int i which has the value 50:

wsprintf(str, TEXT("%05i"), i);


UNIX Commands


How To Disable Call Waiting

If you have call waiting service, you will need to disable it by adding *70, to the phone number. ex. *70,xxx-xxxx-xxx. The commas signal a pause so that the *70 is not interpreted as part of the phone number.


Hosted by www.Geocities.ws

1