Exporting And Importing Templates

From RAD Studio
Jump to: navigation, search

Go Up to C++ Specifics Index


The declaration of a template function or template class needs to be sufficiently flexible to allow it to be used in either a dynamic link library (shared library) or an executable file. The same template declaration should be available as an import and/or export, or without a modifier. To be completely flexible, the header file template declarations should not use __export or __import modifiers. This allows the user to apply the appropriate modifier at the point of instantiation depending on how the instantiation is to be used.

The following steps demonstrate exporting and importing of templates. The source code is organized in three files. Using the header file, code is generated in the dynamic link library.

  1. Exportable/Importable Template Declarations
    The header file contains all template class and template function declarations. An export/import version of the templates can be instantiated by defining the appropriate macro at compile time.
  2. Compiling Exportable Templates
    Write the source code for a dynamic link library. When compiled, this library has reusable export code for templates.
  3. Using ImportTemplates
    Now you can write a calling function that uses templates. This executable file is linked to the dynamic link library. Only objects that are not declared in the header file and which are instantiated in the main function cause the compiler to generate new code. Code for a newly instantiated object is written into main.obj file.

Explicitly Instantiating and Exporting Template Members from Exported Classes

When you export a class that contains template member functions from a DLL or a package (using the __declspec(dllexport) directive or the PACKAGE macro, respectively), these members must be explicitly instantiated and exported. Otherwise, consumers of the exported class might run into unresolved external errors regarding the template member.

Example:

mypackage.h:
#define PACKAGE __declspec(package)
class PACKAGE X
{
public:
  int foo();
  template<typename T>
  int bar(T *p)
  {
    return *p;
  }
};


mypackage.cpp:
#include "mypackage.h"
int X::foo()
{
  return 7;
}

The above resides in a C++ package.

The following app invoking the bar member gets an unresolved external:

myapp.cpp:

#include "mypackage.h"

int g = 6;

int main()
{
  X x;
  x.foo();
  return x.bar(&g);
}
 Error:
 Error: Unresolved external 'int X::bar<int>(int*)' referenced from C:\USERS\ADMIN_000\APPDATA\LOCAL\TEMP\MYAPP-233656.O

To resolve the error, add the following line to mypackage.cpp:

template PACKAGE int X::bar<int>(int*);

The added line explicitly instantiates and exports the member template used by the myapp.cpp source.