Consider the following restrictions when creating DLLs and DLL
applications:
The
entry point for a DLL must be in a program compiled with a Language Environment-conforming
compiler that includes DLL support capability. Otherwise, Language Environment issues
an error and terminates the application.
DLLs must be REENTRANT. Be sure to specify the RENT option
when you bind your code. Unpredictable results will occur if you link-edit
a DLL as NORENT. One possible symptom you may see that indicates the
DLL was link-edited as NORENT is more than one writable static area
for the same DLL.
In a C/C++ DLL
application that contains main(), main() cannot
be exported.
The AMODE of a DLL application must be the same as the AMODE of
the DLL that it calls.
DLL facilities are not available:
Under MTF, CSP or SP C
To application programs with main() written in
PL/I that dynamically call C functions. (This restriction does not
apply to Enterprise PL/I.)
In C++ applications,
you cannot implicitly or explicitly perform a physical load of a DLL
while running static destructors. However, a logical load of a DLL
(meaning that the DLL has previously been loaded into the enclave)
is allowed from a static destructor. In this case, references from
the load module containing the static destructor to the previously-loaded
DLL are resolved.
You cannot use the C functions set_new_handler() or set_unexpected() in
a DLL if the DLL application is expected to invoke the new handler
or unexpected function routines.
If a fetched C module is compiled as a DLL, it can import variables
and functions from the other DLL modules, but it cannot export variables
or functions.
A COBOL dynamic call cannot be made to a load module that is a
DLL.
A COBOL dynamic call cannot be made to a COBOL for OS/390 & VM program
that is compiled with the DLL compiler option.
COBOL data declared with the EXTERNAL attribute are independent
of DLL support; these data items are managed by the COBOL runtime
environment and are accessible by name from any COBOL program in the
run-unit that declares them, regardless of whether the programs are
in DLLs or not.
In particular, the facilities for exporting and
importing external variables from DLLs implemented in C/C++ do not
apply to COBOL external data.
When using the explicit C DLL functions in a multithreaded environment,
avoid any situation where one thread frees a DLL while another thread
calls any of the DLL functions. For example, this situation occurs
when a main() function uses dllload() or dlopen() to
load a DLL, and then creates a thread that uses the ftw() function.
The ftw() target function routine is in the DLL.
If the main() function uses dllfree() or dlclose() to
free the DLL, but the created thread uses ftw() at
any point, you will get an abend.
To avoid a situation where
one thread frees a DLL while another thread calls a DLL function,
do either of the following:
Do not free any DLLs by using dllfree() or dlclose() (Language Environment will
free them when the enclave is terminated).
Have the main() function call dllfree() or dlclose() only
after all threads have been terminated.
For C/C++ DLLs
to be processed by IPA, they must contain at least
one function or method. Data-only DLLs will result in a compilation
error.
The use of circular C++ DLLs
may result in unpredictable behavior related to the initialization
of non-local static objects. For example, if a static constructor
(being run as part of loading DLL "A") causes another DLL "B" to be
loaded, then DLL "B" (or any other DLLs that "B" causes to be loaded
before static constructors for DLL "A" have completed) cannot expect
non-local static objects in "A" to be initialized (that is what static
constructors do). You should ensure that non-local static objects
are initialized before they are used, by coding techniques such as
counters or by placing the static objects inside functions.