building and using dynamic link libraries (dlls)

35
Building and Using Dynamic Link Libraries (DLLs) Contents 1. DLL Concepts and Terms 1.1. DLLs and DLL Applications 1.2. Imported and Exported Functions and Variables 1.3. DLL Code and Non-DLL Code 1.4. Function and Variable Descriptors 1.5. Definition Side-Deck 2. Building a DLL or a DLL Application 2.1. Building a Simple C DLL 2.2. Building a Simple C DLL Application 2.3. Building a Complex DLL or DLL Application 3. Rules for Compiling DLL Code Versus Non-DLL Code 3.1. Rules for Modifying DLL Source 3.2. Summary Example: Creating and Using DLLs 4. Managing the Use of DLLs when Running DLL Applications 4.1. Loading DLLs 4.2. Sharing DLLs 4.3. Freeing DLLs 5. DLL Restrictions 6. Performance Considerations 7. Compatibility Issues between DLL and Non-DLL Code 7.1. Referencing Functions and External Variables 7.2. Pointer Assignment 7.2.1. External Variable Pointers 7.2.2. Function Pointers 7.3. DLL Function Pointer Call in Non-DLL Code 7.3.1. C Examples 7.4. Non-DLL Function Pointer Call in DLL Code 7.4.1. C Examples 7.5. Function Pointer Comparison in Non-DLL Code 7.6. Function Pointer Comparison in DLL Code 8. Explicitly Calling a DLL Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co... 1 of 35 11/28/2014 7:06 AM

Upload: bigfatdash

Post on 18-Jul-2016

243 views

Category:

Documents


6 download

DESCRIPTION

dls for all mate

TRANSCRIPT

Page 1: Building and Using Dynamic Link Libraries (DLLs)

Building and Using Dynamic Link Libraries (DLLs)

Contents

1. DLL Concepts and Terms1.1. DLLs and DLL Applications1.2. Imported and Exported Functions and Variables1.3. DLL Code and Non-DLL Code1.4. Function and Variable Descriptors1.5. Definition Side-Deck

2. Building a DLL or a DLL Application2.1. Building a Simple C DLL2.2. Building a Simple C DLL Application2.3. Building a Complex DLL or DLL Application

3. Rules for Compiling DLL Code Versus Non-DLL Code3.1. Rules for Modifying DLL Source3.2. Summary Example: Creating and Using DLLs

4. Managing the Use of DLLs when Running DLL Applications4.1. Loading DLLs4.2. Sharing DLLs4.3. Freeing DLLs

5. DLL Restrictions6. Performance Considerations7. Compatibility Issues between DLL and Non-DLL Code

7.1. Referencing Functions and External Variables7.2. Pointer Assignment

7.2.1. External Variable Pointers7.2.2. Function Pointers

7.3. DLL Function Pointer Call in Non-DLL Code7.3.1. C Examples

7.4. Non-DLL Function Pointer Call in DLL Code7.4.1. C Examples

7.5. Function Pointer Comparison in Non-DLL Code7.6. Function Pointer Comparison in DLL Code

8. Explicitly Calling a DLL

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

1 of 35 11/28/2014 7:06 AM

Page 2: Building and Using Dynamic Link Libraries (DLLs)

Building and Using Dynamic Link Libraries (DLLs)

A dynamic link library (DLL) is a collection of one or more functions or variables gathered in a load module and executable or accessible from a separate application load module. The term derives from the fact that the connection or link between the applicationthat uses the DLL and the DLL functions or variables is made dynamically while the application is executing rather than statically when the application is built. You can, therefore, call a function or use a variable in a load module other than the one that contains thedefinition. You can use DLLs both implicitly (load-on-call) and explicitly.

When an application implicitly calls a DLL function or references an imported variable, the DLL is implicitly loaded. This load-on-call use of a DLL is essentially transparent to the application code. All the connections for the references to the definitions thatbelong to the DLL are established when the DLL is first called or referenced.

The use of DLLs can also be explicitly controlled by the application code at the source level. The application uses explicit source-level calls to one or more execution-time services. The connections for the reference and the definition are made at run time.

The information in this chapter introduces DLL concepts and describes how to build DLLs and applications that use DLLs. For additional information about compiler options for DLLs or about prelinking applications, see the XL C/C++ for z/VM: User's Guide.

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

2 of 35 11/28/2014 7:06 AM

Page 3: Building and Using Dynamic Link Libraries (DLLs)

1. DLL Concepts and Terms

This section presents key concepts for understanding DLLs.

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

3 of 35 11/28/2014 7:06 AM

Page 4: Building and Using Dynamic Link Libraries (DLLs)

1.1. DLLs and DLL Applications

A DLL is a load module that exports function or variable definitions to other DLLs or DLL applications.

A DLL application is an application that references imported functions or imported variables. A DLL can also import functions and variables from other DLLs.

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

4 of 35 11/28/2014 7:06 AM

Page 5: Building and Using Dynamic Link Libraries (DLLs)

1.2. Imported and Exported Functions and Variables

Imported functions and variables are not defined in the load module where the reference to them is made.

Non-imported functions and variables are defined in the same load module where a reference to them is made.

Exported functions or variables are defined in one load module and can be referenced from another load module. If an exported function or variable is also referenced within the load module where it is defined, the exported function or variable is alsonon-imported.

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

5 of 35 11/28/2014 7:06 AM

Page 6: Building and Using Dynamic Link Libraries (DLLs)

1.3. DLL Code and Non-DLL Code

DLL code and non-DLL code are types of object code. The difference between them is the way they reference functions and external variables. In DLL code, special code sequences are always generated by the compiler for referencing functions, externalvariables, and using function pointers. With these code sequences, a DLL application can reference imported functions and imported variables from a DLL as easily as it can non-imported ones.

The object code generated by the C/C++ compiler with the DLL compiler option is DLL code.

Other types of object code are classified as non-DLL code.

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

6 of 35 11/28/2014 7:06 AM

Page 7: Building and Using Dynamic Link Libraries (DLLs)

1.4. Function and Variable Descriptors

A function descriptor is an internal control block that contains the function address.

A variable descriptor is an internal control block that contains the variable address.

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

7 of 35 11/28/2014 7:06 AM

Page 8: Building and Using Dynamic Link Libraries (DLLs)

1.5. Definition Side-Deck

When you build a DLL, a definition side-deck is created on output by the prelinker. It is a directive file that contains an IMPORT control statement for each function and variable exported by that DLL. You must include this definition side-deck when you prelink aDLL application that imports any functions or variables from the DLL.

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

8 of 35 11/28/2014 7:06 AM

Page 9: Building and Using Dynamic Link Libraries (DLLs)

2. Building a DLL or a DLL Application

Building a DLL or a DLL application is similar to creating any C application. It involves three steps:

Compiling1. Prelinking

Note: Although some C applications may not require prelinking, the prelink step is mandatory when you are building a DLL or a DLL application.

2.

Building3.

To build a DLL or a DLL application, you must pay special attention to the compile and the prelink steps.

The following sections describe how to build simple DLLs or DLL applications. Building a Complex DLL or DLL Application discusses how to build a complex DLL or DLL application. A complex DLL could be any of the following:

A DLL that consists partially of C source files and C++ source files, and partially of other types of source files, such as an assembler source file.A DLL that contains C source files (compiled with the DLL compiler option) that must also be linked with additional object text decks, such as C text decks compiled without DLL. For example, to statically link your DLL to a TEXT library so that you canpackage them together, you need to create a complex DLL.A DLL that is intended to support both DLL and non-DLL applications.

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

9 of 35 11/28/2014 7:06 AM

Page 10: Building and Using Dynamic Link Libraries (DLLs)

2.1. Building a Simple C DLL

You can build a simple C DLL from C source files that contain some defined functions or variables with external linkage that you want to export to the users of the DLL.

Each function that you want to export from the DLL must be an external function.

To build a simple C DLL:

Write code using the #pragma export directive to export specific external functions and variables:

#pragma export(goo)int foo() { ...}int goo() { ...}int kpItHdn() { ...} ...#pragma export(hooVar)#pragma export(kooVar)int hooVar;int kooVar;int kpItHdnVar;

For the above example, the functions foo() and goo() and the variables hooVar and kooVar are exported. The function kpItHdn() and the variable kpItHdnVar are not exported.

Note: If you want to export all defined functions and variables with external linkage in the compilation unit to the users of the DLL, compile with the EXPORTALL compile option. This means that all defined functions and variables with external linkage willbe accessible from this DLL and by all users of this DLL.

Using EXPORTALL means that you do not need to include #pragma export(...) in your code.

1.

Compile with the DLL compiler option. For example, when using c89:

c89 ... -Wc,dll foogoo.c ...

This option instructs the compiler to generate special code when calling functions and referencing external variables. For a simple DLL that does not reference any imported functions or imported variables from other DLLs, specifying the DLL compileroption is not mandatory but it is recommended. Always compiling a simple DLL as DLL code eliminates the potential compatibility problems that may occur when linking DLL code with non-DLL code. See Building a Complex DLL or DLL Application formore information on compatibility issues.

2.

Prelink with the DLL prelinker option. For example, when using c89:

c89 ... -Wb,p,dll ... foogoo.o ...

No special text decks other than those for creating the DLL are required. The prelinker automatically creates a definition side-deck. For the users of this DLL, the definition side-deck describes the functions and the variables that can be imported by DLLapplications. A DLL provider must provide this side deck to the users of the DLL, and the users must include it when they prelink a DLL application.

When prelinking the TEXT file for the above source files, the prelinker generates the following definition side-deck:

IMPORT CODE 'FOOGOO' gooIMPORT DATA 'FOOGOO' hooVarIMPORT DATA 'FOOGOO' kooVar

FOOGOO is the name or alias of the load module for the DLL. The prelinker puts out the DLL name in single quotation marks, and leaves enough extra blanks such that you can change FOOGOO to an 8-character name without moving the function orvariable name.

You can edit the definition side-deck to remove any functions or variables that you do not want to export. For instance, in the above example, if you do not want to expose goo(), remove the control statement IMPORT CODE 'FOOGOO' goo from thedefinition side-deck.

Note: You should also provide a header file containing the prototypes for exported functions and extern variable declarations for exported variables. DLL application writers can then include this header file in their source files that reference functions orvariables in the DLL.

3.

Build the DLL as you would any C application. For example, when using c89:

c89 -o foogoo ... foogoo.o ...

4.

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

10 of 35 11/28/2014 7:06 AM

Page 11: Building and Using Dynamic Link Libraries (DLLs)

2.2. Building a Simple C DLL Application

A simple C DLL application contains C source files. Some of the files contain references to imported functions or imported variables.

To use a load-on-call DLL in your simple C DLL application:

Compile with the DLL compile option. It instructs the compiler to generate special code when calling functions and referencing external variables.1. Prelink. Include the definition side-deck from the DLL provider in the set of text decks to prelink. The prelinker uses the definition side-deck to resolve references to functions and variables defined in the DLL. If you are referencing multiple DLLs, you mustinclude multiple definition side-decks.

Note: You must use an INCLUDE statement for each definition side-deck unless the DLL application uses only explicit DLL references. The automatic library call (autocall) process will not resolve these references if they are not explicit.

2.

Build the DLL application as you would any C application.3.

See Figure 1 for a summary of the processing steps required for a DLL application (and related DLLs).

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

11 of 35 11/28/2014 7:06 AM

Page 12: Building and Using Dynamic Link Libraries (DLLs)

2.3. Building a Complex DLL or DLL Application

A key characteristic of a complex DLL or DLL application is that it is created by linking DLL code with non-DLL code. Non-DLL code may be used because some of the source files are not written in C, or because some of the C source files must be compiled withthe NODLL compiler option (refer to Rules for Compiling DLL Code Versus Non-DLL Code). For example, DLL application writers may want to statically link their applications to a TEXT library that shipped earlier.

These are the general steps for creating a complex DLL or DLL application:

Determine the source files that must be compiled as non-DLL code and assume that the rest of the source files will be compiled as DLL code.1. Make sure that all the source files meet all the DLL rules. If there are violations, follow the corrective steps described in Rules for Modifying DLL Source.2. Compile the source files to produce DLL code and non-DLL code as determined in the previous steps.3. Prelink. Follow the steps for a simple DLL or DLL application.4. Build the DLL or DLL application as you would any C application.5.

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

12 of 35 11/28/2014 7:06 AM

Page 13: Building and Using Dynamic Link Libraries (DLLs)

3. Rules for Compiling DLL Code Versus Non-DLL Code

To create a complex DLL or DLL application, you must decide which source files should be compiled as DLL code and which should be compiled as non-DLL code. The following is a list of the rules for making that decision:

A source file that contains a function call through a pointer that may point to either a function or function descriptor must be compiled as non-DLL code. For example, the qsort() routine in Figure 4 must be compiled as non-DLL code, because qsort() gets apointer to a function to call. Because that pointer can be to a function compiled as either DLL code or non-DLL code, the qsort() routine emitted by the compiler cannot tell whether the routine to invoke is DLL or non-DLL code. This means that qsort()must be non-DLL. For additional information about function pointers, see Pointer Assignment.

1.

A source file that calls imported functions or imported variables by name must be compiled as DLL code.2. A source file that contains a comparison of function pointers that may be DLL function pointers must be compiled as DLL code.

The comparisons shown in Function Pointer Comparison in Non-DLL Code are undefined. To obtain valid comparisons, you must compile the same source files as DLL code.

3.

A source file that may pass a function pointer to DLL code through a parameter or a return value must be compiled as DLL code.

If the qsort() routine in Figure 4 is compiled as DLL code instead of non-DLL code, non-DLL applications can no longer call it. To be able to call the DLL code version of qsort(), the original non-DLL application must be recompiled as DLL code.

4.

A source file that may pass a function pointer to DLL code by linking the references to the definition of an external variable must be compiled as DLL code.

In the following examples, if source file 1 has been compiled as DLL code, source file 2 must be compiled as DLL code as well.

File 1:

void main(void) { goo(); /* initialize fp to be hello function */ fp(); /* call hello function */}

a.

File 2:

extern void (*fp)(void);void hello(void) { printf("hello\n");}void goo(void) { fp = hello;}

If you do not use the DLL compiler option, fp would contain the address of hello. File 1 would expect fp to contain a function descriptor for fp, and the execution of fp would abend.

b.

5.

You must comply with all the rules described above when creating a complex DLL or DLL application. The prelinker flags violations of rule 2 as an error, but the compiler and prelinker do not indicate any other rule violations.

Note: A DLL or DLL application that does not comply with these rules may produce undefined run-time behavior. For a detailed explanation of incompatibilities between DLL and non-DLL code, see Compatibility Issues between DLL and Non-DLL Code.

To comply with the DLL rules, you should also be aware of the following:

A C source file will be compiled as DLL code if the DLL compiler option is on.1. A C source file will be compiled as non-DLL code if the NODLL compiler option is on.2. Other types of source files can be compiled only as non-DLL code.3.

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

13 of 35 11/28/2014 7:06 AM

Page 14: Building and Using Dynamic Link Libraries (DLLs)

3.1. Rules for Modifying DLL Source

Sometimes, source files of a complex DLL or DLL application do not simultaneously meet all the DLL rules. For example,

If a C++ source file that is automatically compiled as DLL code contains a function call through a pointer that may be either a DLL function pointer or a non-DLL function pointer, it must be compiled as non-DLL code by DLL rule 1. For example, a userwrites the qsort() routine in Figure 4.

1.

A C source file that contains the qsort() routine (and therefore must be compiled as non-DLL code) also contains the source for a DLL application that must be compiled as DLL code.2.

When these situations occur, you can use the following methods to solve the problem:

Rewrite the source in C. Only the C source can be compiled as either DLL or non-DLL code. For example 1 above, rewrite the qsort() routine in C.1. Split a source file into two, so that one of the new files can be compiled as DLL code and the other can be compiled as non-DLL code. For example 2 above, split the source file into two so that one contains the qsort() routine while the other contains a DLLapplication.

Note: Sometimes you might have to split a function into two functions before you can successfully split the file.

2.

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

14 of 35 11/28/2014 7:06 AM

Page 15: Building and Using Dynamic Link Libraries (DLLs)

3.2. Summary Example: Creating and Using DLLs

Figure 1 summarizes the use of DLLs for both the DLL provider and for the writer of applications that use them. In this example, application ABC is referencing functions and variables from two DLLs, XYZ and PQR. The connection between DLL preparation andapplication preparation is shown. Each DLL shown contains a single compilation unit. The same general scheme applies for DLLs composed of multiple compilation units, except that they have multiple compiles and a single prelink for each DLL. For simplicity, thisexample assumes that ABC exports variables or functions and that XYZ and PQR do not use other DLLs.

Figure 1. Summary of DLL and DLL Application Preparation and Usage

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

15 of 35 11/28/2014 7:06 AM

Page 16: Building and Using Dynamic Link Libraries (DLLs)

4. Managing the Use of DLLs when Running DLL Applications

This section describes how the C/C++ compiler manages loading and freeing DLLs when you run a DLL application.

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

16 of 35 11/28/2014 7:06 AM

Page 17: Building and Using Dynamic Link Libraries (DLLs)

4.1. Loading DLLs

There are four ways to implicitly load a DLL. They are:

Statically initializing a variable pointer to the address of an exported DLL variable1. Calling an exported function2. Referencing (using, modifying, or taking the address of) an exported variable3. Calling through a function pointer that points to an exported function4.

In the first case, the DLL is loaded when writable static is initialized and (in C++) constructors are run before main() is invoked. In the other cases, the DLL is loaded at the time of the implicit call.

Note: In C++, constructors are run once on initial load and destructors are run once.

When a DLL is called explicitly, writable static is initialized and (in C++) constructors are run when the first call to dllload() is made. For more information on the library functions that make explicit calls to DLL services, see Explicitly Calling a DLL and the XLC/C++ for z/VM: Runtime Library Reference.

When you are running with Language Environment, you can load DLLs from the OpenExtensions byte file system (BFS) as well as from accessed CMS minidisks and SFS directories. In most cases when the Language Environment run-time library attempts to loadthe DLL, it tries to load first from the BFS and then, if it does not find the DLL, from the CMS search order.

The exception to the above case is if the DLL name is unambiguous, or specifically a BFS path ID or CMS file ID. For example, if a DLL name starts with two slashes (//), the run-time library looks only in the accessed CMS search order. If the name starts with asingle slash, the library looks only in the BFS.

When the run-time library attempts to load a DLL from the BFS, it will look in the directories specified by the LIBPATH environment variable. If LIBPATH is not specified, the current working directory is searched.

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

17 of 35 11/28/2014 7:06 AM

Page 18: Building and Using Dynamic Link Libraries (DLLs)

4.2. Sharing DLLs

DLLs are shared at the enclave level (as defined by Language Environment). A referenced DLL is loaded only once per enclave, and only one copy of the writable static is created or maintained per DLL per enclave. Thus, a single copy of a DLL serves all modulesin a given enclave regardless of whether the DLL is loaded implicitly (through a reference to a function or variable) or explicitly (through dllload()). You can simultaneously access a given DLL within a given enclave both implicitly and by explicit execution-timeservices.

All accesses to a given variable in a given DLL in a given enclave refer to the only copy of that variable. All accesses to a given function in a given DLL in a given enclave refer to the only copy of that function.

Although only one copy of a DLL is maintained per enclave, multiple logical loads are counted and used to determine when the DLL (including its writable static area) is actually deleted. For a given DLL in a given enclave, there is one logical load of it for the firstimplicit reference to one of its variables or functions from a given load module, and one logical load for each explicit dllload() request.

DLLs are not shared in a nested enclave environment. Only the enclave that loaded the DLL can access functions and variables. For example, if program A loads a DLL and makes a system call to program B, program B cannot access any of the DLL variablesor functions loaded by program A. Program B can access the DLL variables and functions by loading its own copy of the DLL.

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

18 of 35 11/28/2014 7:06 AM

Page 19: Building and Using Dynamic Link Libraries (DLLs)

4.3. Freeing DLLs

Explicitly-loaded DLLs may be freed with a dllfree() request. This request is optional because the DLLs are automatically deleted by the run-time library at enclave termination.

Implicitly-loaded DLLs cannot be deleted from the DLL application code. They are deleted by the run-time library at enclave termination.

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

19 of 35 11/28/2014 7:06 AM

Page 20: Building and Using Dynamic Link Libraries (DLLs)

5. DLL Restrictions

Consider the following restrictions when creating DLLs and DLL applications:

CEESTART must exist in the load module.1. The AMODE of a DLL application must be the same as the AMODE of the DLL that it calls.2. DLL facilities are not available under the SPC environment.3. DLL facilities are not available to application programs with main() written in PL/I and that dynamically call C/C++ functions.4. DLL facilities are not available to application programs written in COBOL and that dynamically call C/C++ functions.5. You cannot implicitly load a DLL while running C++ static destructors.6. You cannot use DLL static constructors to create new threads. This restriction is to prevent the creation of a DLL loop, where one DLL loads another, which then tries to load the first. In a single thread, if you try to create a DLL loop, you will get an errormessage. However, Language Environment supports DLLs in a multithreaded environment. If a DLL static constructor could create threads, there might be a case where DLL A loaded DLL B, whose static constructor created a new thread that tried to loadDLL A before the static constructor for DLL B completed. The run-time library would not recognize this as a DLL loop. For this reason, DLL static constructors cannot create new threads.

7.

You cannot use the 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.8. Be very careful when you use the explicit DLL functions in a multithreaded environment. Make sure you avoid any situation where one thread frees a DLL while another thread calls any of the DLL functions. Such a situation happens, for example, when amain() function uses dllload() to load a DLL, then creates a thread that uses the ftw() function. The ftw() target function routine is in the DLL. If the main() function uses dllfree() to free the DLL, but the created thread uses ftw() at any point, you will get anabend. There are many scenarios similar to this, all of which can be avoided if you do either of the following:

Do not free any DLLs by using dllfree(). (Language Environment will free them when the enclave is terminated.)Have the main() function call dllfree() only after all threads have been terminated.

9.

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

20 of 35 11/28/2014 7:06 AM

Page 21: Building and Using Dynamic Link Libraries (DLLs)

6. Performance Considerations

This section contains some hints on using DLLs efficiently.

Static Initialization in DLL code

Do not use the static initializations that require a DLL to be loaded if the code actually using the DLL may not be executed.

The static initialization of an external or static pointer variable to the address of an imported variable implies loading a DLL. Static initialization occurs when a DLL application begins executing, before C++ static constructors are run and before the executionof the main function.

A DLL needed for the static initialization is always loaded at initialization time, even if the code using those pointers may not be executed later. To minimize unnecessary startup time, use a run-time initialization so that the DLL is loaded only if it is actuallyused.

Group external variables

Group all external variables into one external structure.

POSIX Run-time Option and Loading DLLs

When POSIX(ON) is used, Language Environment always tries to load DLLs from the BFS first, then from the accessed CMS search order. If the DLLs actually reside on CMS minidisks or SFS directories, this results in unnecessary load attempts. If anapplication must run with CMS DLLs, you can put two slashes (//) in front of the CMS DLL names before the application is prelinked, to make the DLL names in the side-decks unambiguous. If your application uses a DLL in the BFS, you can make the DLLname unambigious by putting a period and a slash (./) in front of it before you prelink.

In C, do not compile with the DLL compiler option if the compilation unit does not use imported symbols.

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

21 of 35 11/28/2014 7:06 AM

Page 22: Building and Using Dynamic Link Libraries (DLLs)

7. Compatibility Issues between DLL and Non-DLL Code

This section describes the differences between DLL code and non-DLL code, and discusses the related compatibility issues for linking them to create complex DLLs.

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

22 of 35 11/28/2014 7:06 AM

Page 23: Building and Using Dynamic Link Libraries (DLLs)

7.1. Referencing Functions and External Variables

Table 1, Figure 1, and Figure 2 show the differences between DLL and non-DLL code in referencing functions and variables. Undefined references fail during the link step.

Table 1. Referencing Functions and External Variables

DLL Non-DLL

Imported Functions A function descriptor is created by the prelinker. The descriptor is in the writable staticarea (WSA) and contains the address of the function and the address of the writablestatic area associated with that function. The function address is resolved when theDLL is loaded. 1

Explicit reference is undefined 5

Non-imported Functions Also called by the function descriptor, but the function address is resolved at loadtime. 3

Directly, by function address 7

Imported Variables A variable descriptor is created in the WSA by the prelinker. It contains addressinginformation for accessing an imported variable. The address is resolved when the DLLis loaded. 2

Undefined 6

Non-imported Variables Direct access 4 Direct access 8

Figure 1. Referencing Functions and External Variables in DLL code

Figure 2. Reference of Functions and External Variables in non-DLL code

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

23 of 35 11/28/2014 7:06 AM

Page 24: Building and Using Dynamic Link Libraries (DLLs)

7.2. Pointer Assignment

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

24 of 35 11/28/2014 7:06 AM

Page 25: Building and Using Dynamic Link Libraries (DLLs)

7.2.1. External Variable Pointers

If you assign the address of an imported variable to a variable pointer in non-DLL code, any reference to that pointer will fail.

In DLL code and non-DLL code, the absolute address of a variable is assigned to a variable pointer.

A valid variable pointer always points to the variable itself and causes no compatibility problems.

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

25 of 35 11/28/2014 7:06 AM

Page 26: Building and Using Dynamic Link Libraries (DLLs)

7.2.2. Function Pointers

If you assign the address of an imported function to a pointer in non-DLL code, the link step will fail. In non-DLL code, the absolute address of a non-imported function is assigned to a function pointer. In DLL code, the address of a function descriptor is assignedto a function pointer.

In a complex DLL or DLL application, a DLL function pointer may be passed to non-DLL code and a non-DLL function pointer may be passed to DLL code. (A function pointer can be passed from DLL code to non-DLL code, or vice versa, by a parameter, areturn value, or an external variable through the link step.) Thus, in a complex DLL or DLL application, a function pointer may point either to a descriptor or to a function entry, depending on whether the function pointer originates in DLL or non-DLL code. Thedifferent ways of de-referencing a function pointer causes the compatibility problem in linking DLL code with non-DLL code.

In Figure 1, 1 assigns the address of the descriptor for the imported function f to fp. 2 assigns the address of the imported variable x to xp. 3 assigns the address of the descriptor for the non-imported function g to gp. 4 assigns the address of the non-importedvariable y to yp.

Figure 1. Pointer Assignment in DLL Code

In Figure 2, 1 causes a link error because the assignment to fp is undefined. 2 causes a prelink error because the assignment to xp is undefined. 3 assigns gp to the address of the non-imported function, g. 4 assigns the address of the non-imported variable y toyp.

Figure 2. Pointer Assignment in Non-DLL Code

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

26 of 35 11/28/2014 7:06 AM

Page 27: Building and Using Dynamic Link Libraries (DLLs)

7.3. DLL Function Pointer Call in Non-DLL Code

The C/C++ compiler supports the DLL function pointer call in non-DLL code. You can, therefore, create a DLL to support both DLL and non-DLL applications. To make those calls possible, glue code is included at the beginning of a function descriptor to allowbranching to a function descriptor.

A function pointer in non-DLL code points to the function entry, and a function pointer call branches to the function address. However, when a DLL function pointer is passed from DLL code to non-DLL code, the pointer points to a function descriptor. A callmade through this pointer in non-DLL code results in branching to the descriptor.

The C/C++ compiler executes a DLL function pointer call in non-DLL code by branching to the descriptor and executing the glue code that invokes the actual function.

The example below and in Figure 4 show a DLL function pointer call in non-DLL code, where a simplified qsort() routine is used as an example of non-DLL code. Note that the qsort() routine compiled as non-DLL code can be called from both a DLL applicationand a non-DLL application.

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

27 of 35 11/28/2014 7:06 AM

Page 28: Building and Using Dynamic Link Libraries (DLLs)

7.3.1. C Examples

Figure 1 shows an example of C non-DLL code in a DLL.

Figure 1. C Non-DLL Code in a DLL

int qqsort(int* z,int num,int (*comp)(int e1,int e2)){ int i,j,temp,rc; for(i=0;i<num-1;i++) { for(j=1;j<num-i;j++) { rc=(*comp)(z[j-1],z[j]); if(rc>0) { temp=z j ; z j =z j-1 ; z j-1 =temp; } } } return(0);} int comp(int e1,int e2){ if(e1==e2){ return(0); } else if(e1<e2){ return(-1); } else{ return(1); }}

Figure 2 shows an example of C DLL code in a DLL application.

Figure 2. C DLL Code in a DLL Application

int (*comp)(int e1, int e2));int comp(int e1, int e2){ if (e1 == e2) return(0); else (e1 < e2) return(-1); else return(1);}int (*fp)(int e1, int e2);main(){ int a[2] = { 2, 1 }; fp = comp; /* assign address of function descriptor */ qsort(a, 2, fp); /* call qsort */}

Figure 3 shows an example of C non-DLL code in a non-DLL application.

Figure 3. C Non-DLL Code in a Non-DLL Application

int (*comp)(int e1, int e2));int comp(int e1, int e2){ if (e1 == e2) return(0); else if (e1 < e2) return(-1); else return(1);}int (*fp)(int e1, int e2);main(){ int a[2&] = { 2, 1 }; fp = comp; /* assign function address */ qsort(a, 2, fp); /* call qsort */}

Figure 4. DLL Function Pointer Call in Non-DLL Code

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

28 of 35 11/28/2014 7:06 AM

Page 29: Building and Using Dynamic Link Libraries (DLLs)

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

29 of 35 11/28/2014 7:06 AM

Page 30: Building and Using Dynamic Link Libraries (DLLs)

7.4. Non-DLL Function Pointer Call in DLL Code

In DLL code, a function pointer is assumed to point to a function descriptor. A function pointer call is made by first obtaining the function address through de-referencing the pointer, and then branching to the function entry. When a non-DLL function pointer ispassed to DLL code, it points directly to the function entry. An attempt to de-reference through such a pointer produces an undefined function address. The subsequent branching to the undefined address may result in an exception. Below are examples of passing anon-DLL function pointer to DLL code through an external variable. Its behavior is undefined:

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

30 of 35 11/28/2014 7:06 AM

Page 31: Building and Using Dynamic Link Libraries (DLLs)

7.4.1. C Examples

C DLL code:

void (*fp)(void);void main (void) { goo(); (*fp)(); /* Expect a descriptor, but get a function address, */ /* so it de-references to an undefined address and */ /* call fails */}

C Non-DLL code:

extern void (*fp)(void);void hello(void) { printf("hello\n");}void goo(void) { fp = hello; /* assign address of hello, to fp */}

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

31 of 35 11/28/2014 7:06 AM

Page 32: Building and Using Dynamic Link Libraries (DLLs)

7.5. Function Pointer Comparison in Non-DLL Code

In non-DLL code, the results of the following function pointer comparisons are undefined:

Comparing a DLL function pointer to a non-DLL function pointer, or, in other words, comparing the address of a function to the address of a function descriptor. In the following examples, both the DLL function pointer and the non-DLL function pointerpoint to the same function, but the pointers themselves compare unequal (refer to Figure 1).

C DLL code:

extern int foo(int (*fp1)(const char *, ...));main (){ int (*fp)(const char *, ...); fp = printf; /* assign address of a descriptor that */ /* points to printf. */ if (foo(fp)) printf("Test result is undefined\n");}

C Non-DLL code:

{ int (*fp2)(const char *, ...); fp2 = printf; /* assign the address of printf. */ if (fp1 == fp2) /* comparing address of descriptor to */ /* address of printf results in unequal.*/ return(0); else return(1);}

In the preceding example, DLL code and non-DLL code can reside either in the same load module or in different load modules.

Figure 1. Comparison of Function Pointers in Non-DLL Code

1.

Comparing a DLL function pointer to another DLL function pointer. Here, you are comparing addresses of function descriptors. In the following examples, both DLL function pointers point to the same function, but they compare unequal (refer to Figure 2).C DLL1 code:

extern int goo(int (*fp1)(const char *, ...));main (){ int (*fp)(const char *, ...); fp = printf; /* assign address of a descriptor that */ /* points to printf. */ if (goo(fp)) printf("Test result is undefined\n");}

C DLL2 code:

extern int foo(int (*fp1)(const char *, ...), int (*fp2)(const char *, ...));int goo(int (*fp1)(const char *, ...)){ int (*fp2)(const char *, ...); fp2 = printf; /* assign address of a different */ /* descriptor that points to printf. */ return (foo(fp1, fp2));}

C Non-DLL code:

int (*fp2)(const char *, ...)){ if (fp1 == fp2) /* comparing the addresses of two */ /* descriptors results in unequal. */ return(0); else return(1);}

Here, DLL1 code and DLL2 code reside in different load modules. The non-DLL code can reside in the same load module with DLL1 or DLL2 or in a different load module.

Figure 2. Comparison of Two DLL Function Pointers in Non-DLL Code

2.

Comparing a DLL function pointer to a constant function address other than NULL. Here, you are comparing the constant function address to an address of a function descriptor.

Note: Comparing a DLL function pointer to NULL is well defined, because when a pointer variable is initialized to NULL in DLL code, it has a value zero.

3.

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

32 of 35 11/28/2014 7:06 AM

Page 33: Building and Using Dynamic Link Libraries (DLLs)

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

33 of 35 11/28/2014 7:06 AM

Page 34: Building and Using Dynamic Link Libraries (DLLs)

7.6. Function Pointer Comparison in DLL Code

In DLL code, a function pointer is checked for NULL before it is compared. For a non-NULL pointer, the pointer is further de-referenced to obtain the function address that is used for the comparison. For an uninitialized function pointer that actually has a non-zerovalue, the de-reference can cause an exception to occur if the storage that the uninitialized pointer points to is read-protected.

Usually, comparing uninitialized function pointers in DLL code results in undefined behavior. You must initialize a function pointer to NULL or the function address (from source view). Two examples follow.

Undefined comparison in DLL code:

int (*fp2)(const char *, ...) /* Initialize to point to the */ = printf; /* descriptor for printf */int goo(void);int (*fp2)(void) = goo;int goo(void) { int (*fp1)(void); if (fp1 == fp2) return (0); else return (1);} #include <stdio.h> void check_fp(void (*fp)()) { /* exception likely when -1 is de-referenced below */ if (fp == (void (*)())-1) printf("Found terminator\n"); else fp(); } void dummy() { printf("In function\n"); } main() { void (*fa[2])(); int i; fa[0] = dummy; fa[1] = (void (*)())-1; for(i=0;i<2;i++) check_fp(fa[i]); }

Figure 1 shows that, when fp1 points to a read-protected memory block, an exception occurs.

Figure 1. Comparison of Function Pointers in DLL Code

1.

Valid comparisons in DLL code:

int (*fp1)(const char *, ...); /* An extern variable is implicitly*/ /* initialized to zero */ /* if it has not been explicitly */ /* initialized in source. */int (*fp2)(const char *, ...) /* Initialize to point to the */ = printf; /* descriptor for printf */int foo(void) { if (fp1 != fp2 ) return (0); else return (1);}

2.

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

34 of 35 11/28/2014 7:06 AM

Page 35: Building and Using Dynamic Link Libraries (DLLs)

8. Explicitly Calling a DLL

DLLs can be explicitly controlled by the application code at the source level. Explicit source-level calls to one or more execution-time services connect the reference and the definition.

The DLL application writer can explicitly call the following execution-time services:

dllload()dllqueryfn()dllqueryvar()dllfree()

Apart from these calls, there is no implicit or automatic connection between the application and the DLL.

The following guidelines apply to explicitly calling a DLL in your application:

Determine the names of the exported functions and variables that you want to use. You can get this information from the DLL provider's documentation or by looking at the definition side-deck file that came with the DLL.Include the DLL header file, dll.h, in your application.Compile your source as usual.Prelink your code as usual.

Note: Do not prelink with the definition side-deck if you are calling the DLL explicitly with the callable services.

Link your application with the same AMODE value as the DLL.

Figure 1 is an example of an application that explicitly uses a DLL:

Figure 1. Explicit Use of a DLL in an Application Part 1 of 2

#include <stdio.h>#include <string.h> #ifdef __cplusplus extern "C" {#endif typedef int (DLL_FN)(void); #ifdef __cplusplus }#endif #define FUNCTION "FUNCTION"#define VARIABLE "VARIABLE" static void Syntax(const char* progName) { fprintf(stderr, "Syntax: %s <DLL-name> <type> <identifier>\n" " where\n" " <DLL-name> is the DLL to load,\n" " <type> can be one of FUNCTION or VARIABLE\n" " and <identifier> is the function or variable\n" " to reference\n", progName); return;}int value; int* varPtr; char* dll; char* type; char* id; dllhandle* dllHandle; if (argc != 4) { Syntax(argv[0]); return(4); } dll = argv[1]; type = argv[2]; id = argv[3];

Figure 2. Explicit Use of a DLL in an Application Part 2 of 2

dllHandle = dllload(dll); if (dllHandle == NULL) { perror("DLL-Load"); fprintf(stderr, "Load of DLL %s failed\n", dll); return(8); } if (strcmp(type, VARIABLE)) { fprintf(stderr, "Type specified was not " FUNCTION " or " VARIABLE "\n"); Syntax(argv[0]); return(8); } /* * variable request, so get address of variable */ varPtr = (int*)(dllqueryvar(dllHandle, id)); if (varPtr == NULL) { perror("DLL-Query-Var"); fprintf(stderr, "Variable %s not exported from %s\n", id, dll); return(8); } value = *varPtr; printf("Variable %s has a value of %d\n", id, value); } else { /* * function request, so get function descriptor and call it */ DLL_FN* fn = (DLL_FN*) (dllqueryfn(dllHandle, id)); if (fn == NULL) { perror("DLL-Query-Fn"); fprintf(stderr, "Function %s() not exported from %s\n", id, dll); return(8); } value = fn(); printf("Result of call to %s() is %d\n", id, value); } dllfree(dllHandle); return(0);}

Building and Using Dynamic Link Libraries (DLLs) http://pic.dhe.ibm.com/infocenter/zvm/v6r3/advanced/print.jsp?topic=/co...

35 of 35 11/28/2014 7:06 AM