Programmer's Notes

For Windows NT

Contents


There are 3 libraries included:

All these libraries share particular similarities such as:
The use of function tags.
These tags are used to pass a variable number of arguments to functions with a view to making the addition of new capabilities as painless as possible.
Some systems are hampered by the fact that structures have to be passed to functions and the sizes of structures change frequently to support new capabilities. This system attempts to provide capabilities without requiring users to re-build their applications when new capabilities are added.
The use of Call/Connection descriptors.
CALLTs, FCALLTs, SCALLTs are descriptors which should not be de-referenced to obtain information about a call/connection. Information should only be accessed by supported macros and documented function calls.
Similar function names, wherever possible.
Libraries attempt to provide a unique prefix, but mostly leave the purpose of the function intact. ie. libsync has a sync_write() call whereas libx25 has an X25write() call. This may make it easier to switch between protocols in the future.


Multithreading

All libraries are modeled on a call(s) per-thread basis. That is, each CALLT, SCALLT, or FCALLT must be handled completely within one thread. This implies that it is usually not possible to split up reading and writing across multiple threads for the same call/connection.


Link Libraries

All supplied libraries are import libraries which means that they only contain links to actual functions within the supplied DLLs and not the functions themselves. These .lib files, however, are not compatible between Development systems. Thus Borland C++ Builder users cannot simply link with the supplied .lib and expect the functions to be resolved.

Not only are the .lib files produced by different vendors not compatible, but the way functions are called is also slightly different. Under Visual C++ there are numerous calling conventions such as __fastcall, __stdcall, & __cdecl which dictate how arguments are passed (on the stack and/or in registers) as well as what kind of name decoration should be performed to resolve a symbol. (ie. for a __stdcall function called Func(int a, int b) the decorated name may be _Func@8

The following information may help in using our supplied libraries in a non Visual C++ environment.


Accessing Library Functions

Since there is an incompatibility with the .lib and the linker used to produce the executable, we abandon load-time linking in favour of run-time linking. Thus we call LoadLibrary() and GetProcAddress() (standard Win32 functions which should be available in any implementation) to attach to the DLL and find the address of a single function within this DLL. We call this function to fill in a function table and from then on will use this table to call any function.

Each library now has a getexports() function. For the synchronous library this function is called sync_getexports(). The function takes a single parameter which is a pointer to a function table. Function tables for each library are defined in libXXXexp.h (where XXX is sync, x25, or frel).

The libXXXexp.h file contains all function pointers to the functions within the DLL. Calling the getexports() function will fill in this structure with the addresses of the function within the process's context.

All functions within the DLL are __stdcall functions except for the variable length argument list functions. Variable length functions may be harder to access, but with the presence of the tags variant of these functions there may be no need to access them.

Example of using the X25getexports function

#include <windows.h>
#include "libx25.h"
#include "libx25exp.h"

void main(void)
{
    HINSTANCE hi;
    WANX25exports X25exp, *e = &X25exp;
    X25getexportsProc GetExportProc;
    int rc;
    char buf[128];

    // Attach to the X.25 DLL
    hi = LoadLibrary("libx25.dll");
    if (!hi)
    {
	printf("Unable to load X.25 library\n");
	exit(1);
    }
    // retrieve the function pointer for the X25getexports function
    // you may have to adjust the calling convention of the
    // X25getexportsProc typedef in order to get proper linkage
    GetExportProc = (X25getexportsProc) GetProcAddress(hi, GETEXPORTSNAME);
    if (!GetExportProc)
    {
	FreeLibrary(hi);
	printf("Unable to get X.25 export function\n");
	exit(1);
    }

    // call the X25getexports() function
    GetExportProc(e);
    // the X25exp function export table is now set up.

    // this call to X25write should fail
    rc = e->X25write(NULL, TAG_END);

    // the return code should be -1
    printf("X25write returns %d\n", rc);
    rc = e->X25geterror();
    e->X25errormsg(rc, buf, sizeof(buf));

    // the error should be: Bad CALLT (28)
    printf("The error is: %s (%d)\n", buf, rc);

    // detach from the DLL
    FreeLibrary(hi);
}


Support

Please e-mail support@software.group.com your experiences with the libraries, so that we may take them into account for future releases.


Copyright © 1997 The Software Group Limited