Retro video games delivered to your door every month!
Click above to get retro games delivered to your door ever month!
X-Hacker.org- Blinker 5.10 Online Reference - <b> special considerations for all dll code</b> http://www.X-Hacker.org [<<Previous Entry] [^^Up^^] [Next Entry>>] [Menu] [About The Guide]
 Special considerations for all DLL code
------------------------------------------------------------------------------
 The section entitled `Dynamic linking and DLLs' in Chapter 4 discusses the
 coding requirements in order to place program code and data in a Windows
 DLL. Language compilers which provide native support for Windows and DLLs
 will typically contain a section discussing the requirements, with examples
 specific to the individual compiler, so please also refer to your compiler
 documentation for details.

 It is particularly important to compile the code with the correct compiler
 options for a DLL, otherwise general protection faults and other erros may
 occur at program run time. Code written in CA-Clipper, however, does not
 require any special compiler options before being placed in a DLL.

 It is also important to remember that the case of imported and exported
 symbols must match exactly. For compatibility with Windows, all imported and
 exported symbols must be upper case. By default, all symbols are converted
 to upper case at link time, so this is not usually an issue. Nor is it an
 issue with high level languages such as CA-Clipper, which always convert
 symbols to upper case at compile time.

 The MIXCASE link script command can be used to maintain case sensitivity at
 link time, but if this option is used then imported and exported symbols
 need to be converted to upper case in one of two ways. The first and most
 transparent is to always declare exported functions as type PASCAL, as is
 standard under Windows, since the compiler always converts PASCAL type
 functions to upper case at compile time. The second is simply to declare and
 code the functions with upper case names.

 Lower case imported and exported symbols will usually result in unresolved
 external errors at link time or unresolved imports at program load time,
 both of which prevent the program from executing.

 A limited subset of the Windows API is provided by the Blinker extender in
 order to allow the language runtime libraries to initialise themselves and
 operate in the same manner as under Windows. The Windows API functions
 provided include the Localxxxxx and Globalxxxxx memory allocation functions,
 the DLL loading and unloading functions, and certain startup functions. A
 list of the supported functions appears in the section entitled `Windows API
 function support' later in this chapter.

 If a dynamically loaded DLL is to be shared between Windows and DOS extended
 programs it should not call any other Windows API functions, either directly
 or indirectly, since they will not be available under the DOS extender. The
 example programs in the \C\DLL\DYN subdirectory use the LoadLibrary(),
 GetProcAddress() and FreeLibrary() Windows API functions to illustrate the
 use of both statically linked and dynamically linked DLLs in DOS extended
 programs.

 CA-Clipper DLLs

 For higher level languages such as CA-Clipper, the same functionality has
 been implemented in four Blinker API functions BLILIBLOD(), BLIFUNHAN(),
 BLIFUNCAL() and BLILIBFRE(). The functions BLILIBLOD() and BLILIBFRE() map
 directly onto the equivalent Windows API functions LoadLibrary() and
 FreeLibrary() as described in the section entitled `Dynamic linking and
 DLLs' in Chapter 4.

 High level languages do not usually give the programmer direct access to
 function pointers, so a two step process is required to call a dynamically
 linked function. The first step is to obtain a handle for the function, much
 the same as for the DLL, by passing the DLL handle and the function name to
 the function BLIFUNHAN(). If the named function exists in the DLL, then a
 handle representing the function is returned. Otherwise a value of zero is
 returned to indicate that the function does not exist or the DLL does not
 export a function with that name.

 The second step, to actually call the function, is simply to pass any
 parameters required by the function, along with the function handle as the
 last parameter, to the function BLIFUNCAL (). This function will execute the
 imported function with the parameters which were passed to it and will
 return the return value of the imported function.

 The relevant part of the main program looks as follows:

 libhan = BLILIBLOD (dllnme)  // Dynamically load the DLL
 if libhan > 32               // If it loaded
 successfully
    funhan = BLIFUNHAN (libhan,funnme)  // Get the handle
    if funhan <> 0            // If the function was found
                              // Call function with (multiple) params
       funres = BLIFUNCAL (funpa1,funpa2,funhan)
                              // Note that function handle is LAST
    else
       ? "DLL file", dllnme, "does not contain function", funnme
       ?
    endif
    ? "Function", funnme, "returned", funres // Display the results
    ?
    BLILIBFRE (libhan)        // Free the library else
    ? "DLL file ", dllnme, "not found or failed to load"
    ?
 endif

 An alternative syntax avoiding the call to BLIFUNCAL() is to use a macro
 function call. This may make the code slightly clearer, but is less
 efficient and has the disadvantage of giving a run time error if the
 function does not exist. The example program T.PRG in the CLP\DLL\DYN
 subdirectory contains a commented out version of this syntax:

 if libhan > 32                   // If it
 loaded successfully
    funres = &funnme (funpa1,funpa2)
 endif                         //
 Gives a runtime error if

 // the function is not found

Online resources provided by: http://www.X-Hacker.org --- NG 2 HTML conversion by Dave Pearson