Linking a DLL into UCW

Here is the UCW header file for the <cctype> character classification functions:

// UnderC Development Project, 2001
#ifndef __cctype_H
#define __cctype_H
#lib MSVCRT40.DLL
extern "C" {
  int isalpha(int);
  int isalnum(int);
  int isdigit(int);
  int isspace(int);
  int isprint(int);
  char toupper(int);
  char tolower(int);
}
#lib
#endif

The #lib command is unique to UnderC. It dynamically loads the specified DLL. Thereafter, any function prototype is assumed to be a reference to that DLL, until a #lib command appears without a filename.

The extern “C” qualifier is standard C++ and requires some explanation. Normally, C++ function names within libraries are mangled or decorated; that is, the function name has extra information about the signature.

For example, the following is an Microsoft mangled name: ?getline@istream@@QAEAAV1@PACHD@Z. Name mangling is not done to confuse programmers; rather, it is a consequence of function overloading. Name mangling allows the linker to find exactly the right function from an overloaded set; there is actually more than one function called istream::getline(). Although mangling occurs in a number of ways depending on the compiler, it is not the major obstacle to compatibility between different compilers. More important is the fact that implementors have done things like passing and returning object values in different ways.

extern "C" tells the compiler that the function name is not mangled as a C++ name but imported (or exported) as a plain C-style function. In a similar way, to export a C++ function to another language, you use this:

extern "C" double sqr(double x)
{ return x*x; }

In this way, C++ programs can be linked with other languages such as C, Pascal, and FORTRAN.

You can extract the exported functions from a DLL by using the TDUMP utility that comes with the Borland compiler. For example, you can find the mangled form of istream::getline() by dumping the exports of MSVCRT40.DLL into a redirected file out.txt. MSVCRT40.DLL is the Microsoft runtime library that ships with Windows:

C:gcc	est>tdump -ee windowssystemmsvcrt40.dll > out.txt
					

Fortunately, the standard C functions are exported with plain undecorated names, otherwise only Microsoft C++ programs could use them. Any function in this DLL that you need to export must therefore include extern "C".

You can import any Windows API call by linking to the correct DLL. Most window-management functions are in user32.dll; note that any function that deals with text comes in ASCII and Unicode versions, which are distinguished by A and W, respectively. (All these names are publicly available through TDUMP.) The __API attribute is unique to UCW and is necessary because the calling convention (__stdcall) is different from usual C calls. __stdcall is also an available attribute, but the name mangling is nonstandard (that is, Microsoft does not follow its own conventions). This example shows how two Windows API functions, FindWindow() and SetWindowText(), can be imported into an UnderC interactive session. Note the A for ASCII at the end of the function names:

;> #lib user32.dll
;> extern "C"
;>  __API int FindWindowA(char *,char *);
;> extern "C"
;>  __API void SetWindowTextA(int,char *);
;> int h;
;> h
						=
						FindWindowA(NULL,"UnderC for Windows");
(int) 1332
;> SetWindowTextA(h,"hello dolly");
					

The FindWindowA() API call finds the first window with the specified caption and returns an integer value called the window handle—in this session, the UCW console window. Using the window handle, you can change the window text, which for top-level windows is the caption. Interactively experimenting with the Windows API is a good way to become familiar with the available resources. Bear in mind that there is practically no overhead involved in using the API because DLLs such as user32.dll have already been loaded.

Building an API program with GCC is straightforward because the prototypes are all available in <windows.h>. You don't need to remember the A because FindWindow is a macro defined as FindWindowA if you're using ASCII. GCC by default uses the import libraries for user32.dll and kernel32.dll, which covers most common API calls, except for graphics (in which case you use –lgdi as with linking YAWL programs). Here is a standalone version of the preceding UCW session which will compile with GCC (or any Windows compiler):

// wtext.cpp
#include <windows.h>
int main()
{
 HWND h = FindWindow(NULL,"UnderC for Windows");
 SetWindowText(h,"hello dolly");
}
c:gcc	est> c++ –s wtext.cpp
					

This produces a 4KB program, which again proves that C++ isn't always bloated. However, compiling wtext.cpp is not fast because of the sheer size of <windows.h>. UnderC is such a useful prototyping tool for API programming because it is practically instaneous.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
13.58.116.51