Using Shared Libraries (DLLs)


The advantages of shared/DLL libraries include:

In general, an application can use either static or shared/DLL libraries without modification to its source code. However, when using ACIS DLLs, precautions must be taken when compiling your application to prevent errors. Also, if you need to create your own custom ACIS component as a shared library, the component must meet certain requirements in order to be built as a shared ACIS library.

DLLs

If you are going to link your Windows NT application against the ACIS DLLs, you must define the symbol ACIS_DLL when you compile any file that references global symbols defined in any ACIS DLL to avoid unresolved symbol errors. Also, you must use compiler flags consistent with those used to build the DLLs to avoid runtime problems. In addition the symbols NT_DLL and NT_DLLD must define the target ARCH.

Ensure that you are using the same version of the C Runtime Library when you compile and link your application as was used when the DLLs were built. Also, ensure that the same C Runtime Library was used to build all of the DLLs being linked to the application. Otherwise, you will get access violation errors when working with pointers or file handles passed between DLLs or between the application and the DLLs.

Building ACIS Shared Libraries

When adding your own custom components to ACIS, you may want the libraries to be available as shared/DLL. When using shared/DLL libraries, it is important to keep the order of libraries in mind. Functions from higher libraries can not be called from lower libraries.

The following steps should be done for each library that is to be built as a shared ACIS library. An example (for Constructors or Intersectors libraries) is shown for most steps.

Note:  The string <MODULE> should be substituted with the shared library module identifier listed in the Type column of the appropriate library table in section Libraries. The string <module> should be replaced with the lowercase version of this.

  1. Create a dcl_<module>.h file in the librarys directory.
  2. This header file defines the DECL_<MODULE> macro to indicate whether symbols are being exported or imported from the shared library. It also causes the library to be searched automatically by any file that includes this header on Windows systems.

    #ifndef DECL_CSTR
    #ifdef ACIS_DLL
    #ifdef EXPORT_CSTR
    #define DECL_CSTR __declspec(dllexport)
    #else
    #define DECL_CSTR __declspec(dllimport)
    #ifdef NT
    #pragma comment(lib, constrct.lib) /*linklibrary*/
    #endif
    #endif
    #else
    #define DECL_CSTR
    #endif
    #endif
  3. Add a MODULE command to the config file in the library directory.
  4. This tells the build tool the module name and include path for the dcl_<module>.h file. It also tells the build tool that the library can be built as a shared/DLL library.

    MODULE CSTR constrct/dcl_cstr.h
  5. Add a DEFINE * EXPORT_<MODULE> command to the config file in the library directory.
  6. This causes the dcl_<module>.h file to define DECL_<MODULE> so that symbols are exported if ACIS_DLL is defined.

    DEFINE * EXPORT_CSTR
  7. Add a LIB_DEPEND command to the config file in the library directory.
  8. This tells the build tool which libraries this library depends on, so it builds them in the correct order. The first library listed is the one being built, followed by those on which it depends.

    LIB_DEPEND constrct intersct kernel spline
  9. Add the DECL_<MODULE> modifier to declarations of classes, global variables and functions in header files.
  10. This tells the compiler that the symbol should be exported when compiling files in the DLL and imported when compiling files outside the DLL.

    DECL_CSTR outcome api_initialize_constructors();
    class DECL_CSTR splgrid
    {
    .
    .
    .
    };
  11. Change definitions of THIS_LIB and PARENT_LIB to <MODULE> instead of NONE.
  12. #define THIS() ATTRIB_INT
    #define THIS_LIB INTR
    #define PARENT() ATTRIB_BLND
    #define PARENT_LIB KERN
  13. Change uses of the MODULE_DEF, MODULE_REF, ENTITY_FUNCTIONS, ATTRIB_FUNCTIONS, MASTER_ENTITY_DECL, MASTER_ATTRIB_DECL, DISPATCH_DECL, and LIST macros to specify <MODULE> instead of NONE.
  14. #define MODULE() sg_check_wire
    MODULE_DEF(sg_check_wire, CSTR);
  15. Include the dcl_<module>.h file in any file which uses DECL_<MODULE> or <MODULE> as described above.
  16. #include dcl_cstr.h
  17. Ensure that the header file that declares a symbol is included in the source file in which it is defined. Otherwise, you will get unresolved symbols when attempting to reference the symbol from outside the DLL.

These steps only make it possible to build the library as a shared/DLL library. The symbol ACIS_DLL must be defined during compilation and special commands must be used to create the DLL or shared library instead of a static library. These items should already be handled by the architecture specific config files in the bldcfg directory.

Note:  These steps are not required for UNIX platforms. Steps 2 and 4 tell the build tool to build as a shared library, if allowed, and are the only steps needed for shared libraries on UNIX platforms.

C Runtime Library DLL

When using the ACIS DLLs, it is important that you link your application against the DLL version of the C Runtime Library. Otherwise you will have two separate versions of the runtime library. Files opened (using fopen) by the C runtime library in your executable will not be recognized by the C runtime library used by ACIS and other DLLs. If you use the DLL version of the C Runtime Library, it will be shared by the executable and all DLLs.

You must also make sure that you do not use two different C runtime DLLs (for example, one release and one debug) when using ACIS. When two different runtime DLLs are in use, several problems can occur. One problem is that file pointers can not be shared between two runtime DLLs. Each C runtime DLL has its own collection of file pointers (FILE*), and one C runtime DLL will experience an access violation if it tries to work with anothers file pointer. Another problem is that memory allocated by one C runtime DLL can not be deleted by another C runtime DLL, since each has its own memory heap.

A common case in which two different C runtime DLLs are used is the mixing of the debug and release versions of the C runtime DLLs. For example, if your application is built with the debug version of the C Runtime Library DLL (msvcrtd.dll), and your ACIS DLLs use the release DLL version (msvcrt.dll), then you will experience problems. This is a frequent source of access violations for save and restore.

You can determine which C runtime DLL is used by any DLL or executable file using the dump bin program, which is part of the Visual C++ distribution. For example, to check your application executable, use (substitute the correct name of your application):

dumpbin /imports application.exe | findstr /i dll

To check your ACIS binaries, use (substitute the correct name/version of your Kernel DLL):

dumpbin /imports SpaACIS.dll | findstr /i dll

If the result shows msvcrt.dll, that means the release DLL is used; if it shows msvcrtd.dll, that means the debug DLL is used (the added d means debug version). If one is using the release DLL and the other is using the debug DLL, you need to change either your application or your ACIS binaries so that they use the same C runtime DLL.

[Top]