📄 dynlink.gml
字号:
/* allocate private storage for thread */
/* and save pointer to it */
TlsSetValue( TlsIndex, malloc(200) );
break;
.code break
case DLL_THREAD_DETACH:
/* do thread cleanup */
/* get the TLS value and free associated memory */
free( TlsGetValue( TlsIndex ) );
break;
.code break
case DLL_PROCESS_DETACH:
/* do process cleanup */
/* free TLS index */
TlsFree( TlsIndex );
break;
}
return( 1 ); /* indicate success */
/* returning 0 indicates initialization failure */
}
.code break
EXPORTED void dll_entry_1( void )
{
printf( "Hi from dll entry #1\n" );
}
.code break
EXPORTED void dll_entry_2( void )
{
printf( "Hi from dll entry #2\n" );
}
.do end
.el .if '&targetos' eq 'OS/2 2.x' .do begin
#include <os2.h>
#if defined(__cplusplus)
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
unsigned APIENTRY LibMain( unsigned hmod, unsigned termination )
{
if( termination ) {
/* DLL is detaching from process */
} else {
/* DLL is attaching to process */
}
return( 1 );
}
.code break
EXTERNC void dll_entry_1( void )
{
printf( "Hi from dll entry #1\n" );
}
.code break
EXTERNC void dll_entry_2( void )
{
printf( "Hi from dll entry #2\n" );
}
.do end
.code end
.if '&targetos' eq 'Windows NT' .do begin
.begnote Arguments:
.*
.note hinstDLL
.*
This is a handle for the DLL.
It can be used as a argument to other functions such as
.kw GetModuleFileName.
.*
.note fdwReason
.*
This argument indicates why
.kw LibMain
is being called.
It can have one of the following values:
.*
.begnote
.notehd1 Value
.notehd2 Meaning
.*
.note DLL_PROCESS_ATTACH
.*
This value indicates that 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 or to
use the
.kw TlsAlloc
function to allocate a Thread Local Storage (TLS) index.
.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.
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 DLL_THREAD_ATTACH
.*
This value indicates that the current process is creating a new
thread.
When this occurs, the system calls the
.kw LibMain
entry-point 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 a Thread Local Storage
(TLS) slot for the thread.
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 DLL_THREAD_DETACH
.*
This value indicates that a thread is exiting normally.
If the DLL has stored a pointer to allocated memory in a TLS slot, it
uses this opportunity to free the memory.
The operating system calls the
.kw LibMain
entry-point 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 DLL_PROCESS_DETACH
.*
This value indicates that 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.
The DLL can use this opportunity to call the
.kw TlsFree
function to free any TLS indices allocated by using
.kw TlsAlloc
and to free any thread local data.
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.
.endnote
.*
.note lpvReserved
.*
This argument specifies further aspects of DLL initialization and
cleanup.
If
.id fdwReason
is
.id DLL_PROCESS_ATTACH,
.id lpvReserved
is NULL for dynamic loads and non-NULL for static loads.
If
.id fdwReason
is
.id DLL_PROCESS_DETACH,
.id lpvReserved
is NULL if
.kw LibMain
has been called by using
.kw FreeLibrary
and non-NULL if
.kw LibMain
has been called during process termination.
.*
.note Return Value
.*
When the system calls the
.id LibMain
function with the
.id DLL_PROCESS_ATTACH
value, the function returns TRUE (1) if initialization succeeds or
FALSE (0) if initialization fails.
.np
If the return value is FALSE (0) when
.kw LibMain
is called because the process uses the
.kw LoadLibrary
function,
.kw LoadLibrary returns NULL.
.np
If the return value is FALSE (0) when
.kw LibMain
is called during process initialization, the process terminates with
an error.
To get extended error information, call
.kw GetLastError.
.np
When the system calls
.kw LibMain
with any value other than
.id DLL_PROCESS_ATTACH,
the return value is ignored.
.endnote
.do end
.el .if '&targetos' eq 'OS/2 2.x' .do begin
.np
32-bit OS/2 DLLs can include a
.kw LibMain
entry point when you are using the &product run-time libraries.
.begnote Arguments:
.*
.note hmod
.*
This is a handle for the DLL.
.*
.note termination
.*
A 0 value indicates that 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 DosLoadModule.
A DLL can use this opportunity to initialize any instance data.
.np
A non-zero value indicates that 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 DosFreeModule.
.*
.note Return Value
.*
The
.id LibMain
function returns 1 if initialization succeeds or 0 if initialization fails.
.np
If the return value is 0 when
.kw LibMain
is called because the process uses the
.kw DosLoadModule
function,
.kw DosLoadModule
returns an error.
.np
If the return value is 0 when
.kw LibMain
is called during process initialization, the process terminates with
an error.
.endnote
.do end
.do end
.np
Assume the above example is contained in the file
.fi dllsamp.&langsuff..
We can compile the file using the following command.
Note that we must specify the "bd" compiler option.
.millust begin
&prompt.&ccmd32 &sw.bd dllsamp
.millust end
.np
Before we can link our example, we must create a linker directive file
that describes the attributes and entry points of our dynamic link
library.
The following is a linker directive file, called
.fi dllsamp.lnk,
that can be used to create the dynamic link library.
.millust begin
.if '&targetos' eq 'OS/2 2.x' .do begin
system os2v2 dll initinstance terminstance
option manyautodata
.do end
.el .do begin
system nt_dll initinstance terminstance
.do end
.if '&lang' eq 'FORTRAN 77' .do begin
export DLL_ENTRY_1
export DLL_ENTRY_2
.do end
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
export dll_entry_1_
export dll_entry_2_
.do end
file dllsamp
.millust end
.autonote Notes:
.note
The "SYSTEM" directive specifies that we are creating
.if '&targetos' eq 'OS/2 2.x' .do begin
a 32-bit OS/2
.do end
.el .do begin
a Windows NT
.do end
dynamic link library.
.note
.if '&targetos' eq 'OS/2 2.x' .do begin
The "MANYAUTODATA" option specifies that the automatic data segment is
allocated for every instance of the dynamic link library.
This option must be specified only for a dynamic link library that
uses the &product run-time libraries.
If the &product run-time libraries are not used, this option is not
required.
Our example does use the &product run-time libraries so we must
specify the "MANYAUTODATA" option.
.np
As was just mentioned, when a dynamic link library uses the &product
run-time libraries, an automatic data segment is created each time a
process accesses the dynamic link library.
.do end
.el .do begin
When a dynamic link library uses the &product
run-time libraries, an automatic data segment is created each time a
new process accesses the dynamic link library.
.do end
For this reason, initialization code must be executed when a process
accesses the dynamic link library for the first time.
To achieve this, "INITINSTANCE" must be specified in the "SYSTEM"
directive.
Similarly, "TERMINSTANCE" must be specified so that the termination
code is executed when a process has completed its access to the
dynamic link library.
If the &product run-time libraries are not used, these options are not
required.
.note
The "EXPORT" directive specifies the entry points into the dynamic
link library.
.if '&lang' eq 'FORTRAN 77' .do begin
Note that in &product, names of all symbols are uppercased. Regardless
of the case used in source files, linker directives must use uppercased
symbol names. The linker is case sensitive by default, although the
"OP NOCASEEXACT" directive may be used to override this.
.do end
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
Note that the names specified in the "EXPORT" directive are appended
with an underscore.
This is the default naming convention used when compiling using the
register-based calling convention.
No underscore is required when compiling using the stack-based calling
convention.
.do end
.endnote
.np
We can now create our dynamic link library by issuing the following
command.
.millust begin
&prompt.&lnkcmd @dllsamp
.millust end
.pc
A file called
.fi dllsamp.dll
will be created.
.*
.section Using Dynamic Link Libraries
.*
.np
.ix 'dynamic link library access' '&targetos.'
.ix 'DLL access' '&targetos.'
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
.if '&targetos' eq 'Windows NT' .do begin
.np
It is assumed that all symbols imported by a client application were
declared with a
.id __declspec( dllimport )
modifier when the client application was compiled. At the link stage
we have to tell the linker which dynamic libraries the client
application should link to.
.do end
.do end
Once we have created a dynamic link library, we must allow other
applications to access the functions available in the dynamic link
library.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -