⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dynlink.gml

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 GML
📖 第 1 页 / 共 3 页
字号:
:set symbol="oprompt"   value=&prompt.
.if '&targetos' eq 'OS/2 2.x' .do begin
:set symbol="prompt"    value="[C:\]".
:set symbol="tgtosname" value="os2v2".
.do end
.el .do begin
:set symbol="prompt"    value="C:\>".
:set symbol="tgtosname" value="nt".
.do end
:set symbol="tgtopts"   value="".
.*
.if '&lang' eq 'FORTRAN 77' .do begin
:set symbol="dll_init"  value="__fdll_initialize_".
:set symbol="dll_term"  value="__fdll_terminate_".
:set symbol="thrd_init"  value="__fthrd_initialize_".
:set symbol="thrd_term"  value="__fthrd_terminate_".
.do end
.*
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
.if '&targetos' eq 'Windows NT' .do begin
:set symbol="tgtopts"   value="&sw.bm ".
.do end
:set symbol="dll_init"  value="__dll_initialize".
:set symbol="dll_term"  value="__dll_terminate".
:set symbol="thrd_init"  value="__thrd_initialize".
:set symbol="thrd_term"  value="__thrd_terminate".
.do end
.*
.chap &targetos Dynamic Link Libraries
.*
.np
.ix 'dynamic link libraries' '&targetos.'
.ix 'DLL' '&targetos.'
A dynamic link library, like a standard library, is a library of
functions.
.ix 'static linking'
When an application uses functions from a standard library, the
library functions referenced by the application become part of the
executable module.
This form of linking is called static linking.
.ix 'dynamic linking'
When an application uses functions from a dynamic link library, the
library functions referenced by the application are not included in
the executable module.
Instead, the executable module contains references to these functions
which are resolved when the application is loaded.
This form of linking is called dynamic linking.
.np
Let us consider some of the advantages of using dynamic link libraries
over standard libraries.
.autonote
.note
Functions in dynamic link libraries are not linked into your program.
Only references to the functions in dynamic link libraries are placed
in the program module.
.ix 'import definitions'
These references are called import definitions.
As a result, the linking time is reduced and disk space is saved.
If many applications reference the same dynamic link library, the
saving in disk space can be significant.
.note
Since program modules only reference dynamic link libraries and do not
contain the actual executable code, a dynamic link library can be
updated without re-linking your application.
When your application is executed, it will use the updated version of
the dynamic link library.
.note
Dynamic link libraries also allow sharing of code and data between the
applications that use them.
If many applications that use the same dynamic link library are
executing concurrently, the sharing of code and data segments improves
memory utilization.
.endnote
.*
.section Creating Dynamic Link Libraries
.*
.np
.ix 'dynamic link library creation' '&targetos.'
.ix 'DLL creation' '&targetos.'
Once you have developed the source for a library of functions, a
number of steps are required to create a dynamic link library
containing those functions.
.np
First, you must compile your source using the "bd" compiler option.
This option tells the compiler that the module you are compiling is
part of a dynamic link library.
Once you have successfully compiled your source, you must create a
linker directive file that describes the attributes of your dynamic
link library.
The following lists the most common linker directives required to
create a dynamic link library.
.autopoint
.point
The "SYSTEM" directive is used to specify that a dynamic link library
is to be created.
.point
The "EXPORT" directive is used to to specify which functions in the
dynamic link library are to be exported.
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
.begnote
.*
.note Specifying exports in the source code
.np
.if '&targetos' eq 'Windows NT' .do begin
The "EXPORT" directive need not be used when the symbols to be exported
are declared with the
.id __declspec( dllexport )
modifier in the source code. Such symbols are exported automatically,
through special records inserted into the object files by the compiler.
.if '&lang' eq 'C/C++' .do begin
.note Exporting C++ symbols and classes
.np
Symbols exported via the "EXPORT" directive have to be entered in their
mangled form. This makes it rather awkward to export C++ functions, classes
or global objects. These symbols also often reference other compiler-generated
symbols (invisible to the user) that need be exported together with the
class/object. Using the
.id __declspec( dllexport )
method of exporting symbols is the preferred solution.
.do end
.do end
.if '&targetos' eq 'OS/2 2.x' .do begin
The "EXPORT" directive need not be used when the symbols to be exported
are declared with the
.id __export
type qualifier in the source code. Such symbols are exported automatically,
through special records inserted into the object files by the compiler.
.do end
.np
.endnote
.do end
.point
The "OPTION" directive is used to specify attributes such as the name of
the dynamic link library and how to allocate the automatic data segment
when the dynamic link library is referenced.
.point
The "SEGMENT" directive is used to specify attributes of segments.
For example, a segment may be read-only or read-write.
.endpoint
.np
Once the dynamic link library is created, you must allow access to the
dynamic link library to client applications that wish to use it.
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
.if '&targos' eq 'Windows NT' .do begin
The client application should to be compiled so that each symbol that will
be imported from a dynamic link library is declared with
.id __declspec( dllimport )
modifier in the source code. This is highly recommended for imported
functions and required for imported variables or classes.
The linker must also be told where the symbols should be imported from.
.do end
.do end
This can be done by creating an import library for the dynamic link
library or creating a linker directive file that contains "IMPORT"
directives for each of the entry points in the dynamic link library.
.*
.section Creating a Sample Dynamic Link Library
.*
.np
.ix 'dynamic link library sample' '&targetos.'
.ix 'DLL sample' '&targetos.'
Let us now create a dynamic link library using the following example.
.if '&lang' eq 'FORTRAN 77' .do begin
The source code for this example can be found in
.if '&targetos' eq 'OS/2 2.x' .do begin
.fi &pathnam.\samples\fortran\os2\dll.
.do end
.el .do begin
.fi &pathnam.\samples\fortran\win\dll.
.do end
Unlike applications developed in the C or C++ language, the &lang
developer must not provide a
.kw LibMain
entry point.
This entry point is already defined in the &product run-time
libraries.
The run-time system's
.kw LibMain
provides for the proper initialization of the &lang run-time system
and includes hooks to call developer-written process attach/detach and
thread attach/detach routines.
These routines are optional but we show skeleton versions in the
following example so that you can develop your own if required.
.code begin
* DLLSAMP.FOR

      integer function __fdll_initialize_()
*     Called from LibMain during "DLL PROCESS ATTACH"

*     do process initialization
      print *, 'Hi from process attach'

*     returning 0 indicates failure
      __fdll_initialize_ = 1
      return
      end

.if '&targetos' eq 'Windows NT' .do begin
.code break
      integer function __fthrd_initialize_()
*     Called from LibMain during "DLL THREAD ATTACH"

*     do thread initialization
      print *, 'Hi from thread attach'

*     returning 0 indicates failure
      __fthrd_initialize_ = 1
      return
      end

.code break
      integer function __fthrd_terminate_()
*     Called from LibMain during "DLL THREAD DETACH"

*     do thread cleanup
      print *, 'Hi from thread detach'

*     returning 0 indicates failure
      __fthrd_terminate_ = 1
      return
      end

.do end
.code break
      integer function __fdll_terminate_()
*     Called from LibMain during "DLL PROCESS DETACH"

*     do process cleanup
      print *, 'Hi from process detach'

*     returning 0 indicates failure
      __fdll_terminate_ = 1
      return
      end

.code break
      subroutine dll_entry_1()
      print *, 'Hi from dll entry #1'
      end

      subroutine dll_entry_2()
      print *, 'Hi from dll entry #2'
      end
.code end
.if '&targetos' eq 'Windows NT' .do begin
.np
Here are some explanatory notes on this example.
.begnote
.notehd1 Function
.notehd2 Description
.*
.note __FDLL_INITIALIZE_
.*
This function is called when the DLL is attaching to the address space
of the current process as a result of the process starting up or as a
result of a call to
.kw LoadLibrary.
A DLL can use this opportunity to initialize any instance data.
.np
During initial process startup or after a call to
.kw LoadLibrary,
the operating system scans the list of loaded DLLs for the process.
For each DLL that has not already been called with the
.id DLL_PROCESS_ATTACH
value, the system calls the DLL's
.kw LibMain
entry-point (in the &product run-time system).
This call is made in the context of the thread that caused the process
address space to change, such as the primary thread of the process or
the thread that called
.kw LoadLibrary.
.*
.note __FTHRD_INITIALIZE_
.*
This function is called when the current process is creating a new
thread.
When this occurs, the system calls the
.kw LibMain
entry-point (in the &product run-time system) of all DLLs currently
attached to the process.
The call is made in the context of the new thread.
DLLs can use this opportunity to initialize thread specific data.
A thread calling the DLL's
.id LibMain
with the
.id DLL_PROCESS_ATTACH
value does not call
.kw LibMain
with the
.id DLL_THREAD_ATTACH
value.
Note that
.kw LibMain
is called with this value only by threads created after the DLL is
attached to the process.
When a DLL is attached by
.kw LoadLibrary,
existing threads do not call the
.kw LibMain
entry-point of the newly loaded DLL.
.*
.note __FTHRD_TERMINATE_
.*
This function is called when a thread is exiting normally.
The DLL uses this opportunity to do thread specific termination such
as closing files that were opened by the thread.
The operating system calls the
.kw LibMain
entry-point (in the &product run-time system) of all currently loaded
DLLs with this value.
The call is made in the context of the exiting thread.
There are cases in which
.kw LibMain
is called for a terminating thread even if the DLL never attached to
the thread.
For example,
.kw LibMain
is never called with the
.id DLL_THREAD_ATTACH
value in the context of the thread in either of these two situations:
.begbull
.bull
The thread was the initial thread in the process, so the system called
.kw LibMain
with the
.id DLL_PROCESS_ATTACH
value.
.bull
The thread was already running when a call to the
.kw LoadLibrary
function was made, so the system never called
.kw LibMain
for it.
.endbull
.*
.note __FDLL_TERMINATE_
.*
This function is called when the DLL is detaching from the address
space of the calling process as a result of either a normal
termination or
of a call to
.kw FreeLibrary.
When a DLL detaches from a process as a result of process termination
or as a result of a call to
.kw FreeLibrary,
the operating system does not call the DLL's
.kw LibMain
with the
.id DLL_THREAD_DETACH
value for the individual threads of the process.
The DLL is only given
.id DLL_PROCESS_DETACH
notification.
DLLs can take this opportunity to clean up all resources for all
threads attached and known to the DLL.
.*
.note Note:
.*
These functions return 1 if initialization succeeds or 0 if
initialization fails.
Subsequently, this value will be returned by the run-time system's
.id LibMain
function.
.np
If the return value is 0 when
.kw LibMain
is called because the process uses the
.kw LoadLibrary
function,
.kw LoadLibrary returns NULL.
.np
If the return value is 0 when
.kw LibMain
is called during process initialization, the process terminates with
an error.
.*
.note DLL_ENTRY_1, DLL_ENTRY_2
.*
These are sample DLL entry points that we will call from our simple
test program.
.endnote
.np
Some further explanation and an example are provided in a later
section.
.do end
.do end
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
.code begin
#include <stdio.h>
.if '&targetos' eq 'Windows NT' .do begin
#include <windows.h>

#if defined(__cplusplus)
#define EXPORTED extern "C" __declspec( dllexport )
#else
#define EXPORTED __declspec( dllexport )
#endif

DWORD TlsIndex; /* Global Thread Local Storage index */

/* Error checking should be performed in following code */

.code break
BOOL APIENTRY LibMain( HANDLE hinstDLL,
                       DWORD  fdwReason,
                       LPVOID lpvReserved )
{
    switch( fdwReason ) {
    case DLL_PROCESS_ATTACH:
        /* do process initialization */

        /* create TLS index */
        TlsIndex = TlsAlloc();
        break;

.code break
    case DLL_THREAD_ATTACH:
        /* do thread initialization */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -