DLL restrictions

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.