Explicit template instantiation and not exported symbols in the resulting DLL
Martin Lederhilger
ml@convergent-it.at
Tue Aug 9 12:44:00 GMT 2011
Hello,
I have a problem with explicit template instantiation and exporting it's symbols into a DLL. I am using gcc 4.5.2. The smallest possible example - which I came up with - looks like this:
Interface.h
-----------
#ifndef INTERFACE
#ifdef EXPORTS
#define INTERFACE __declspec(dllexport)
#else
#define INTERFACE __declspec(dllimport)
#endif
#endif
A.h
---
#ifndef A_H
#define A_H
#include "Interface.h"
class INTERFACE Base
{
public:
virtual ~Base();
virtual void doSomething() = 0;
};
template<class T>
class A : public Base
{
public:
virtual void doSomething();
};
//#define USE_EXTERN_TEMPLATE
#ifdef USE_EXTERN_TEMPLATE
extern template class INTERFACE A<int>; //not standard until new standard arrives
#endif
inline static A<int>* create()
{
return new A<int>();
}
#endif
A_imp.h (contains class template's implementation)
--------------------------------------------------
#include "A.h"
template<class T>
void A<T>::doSomething()
{
}
A.cpp (goes into the DLL)
-------------------------
#include "A_imp.h"
Base::~Base()
{
}
#ifdef USE_EXTERN_TEMPLATE
template class A<int>;
#else
template class INTERFACE A<int>;
#endif
main.cpp (goes into the EXE)
----------------------------
#include "A.h"
#include<typeinfo>
#include<iostream>
int main(int argc, char **argv) {
A<int> a;
a.doSomething();
std::cout << typeid(a).name();
return 0;
}
Makefile
--------
CXX=i686-mingw32-g++
all: app.exe
clean:
rm dll.dll app.exe
dll.dll: A.cpp
$(CXX) -Wall -shared -o dll.dll -DEXPORTS A.cpp
app.exe: main.cpp dll.dll
$(CXX) -Wall -o app.exe main.cpp dll.dll
--------
For case number one (USE_EXTERN_TEMPLATE is undefined), which I prefer, I get the following output:
make
i686-mingw32-g++ -Wall -shared -o dll.dll -DEXPORTS A.cpp
A.cpp:11:28: warning: type attributes ignored after type is already defined
i686-mingw32-g++ -Wall -o app.exe main.cpp dll.dll
/tmp/cc1vqmge.o:main.cpp:(.text+0x5a): undefined reference to `A<int>::doSomething()'
/tmp/cc1vqmge.o:main.cpp:(.rdata$_ZTV1AIiE[vtable for A<int>]+0x10): undefined reference to `A<int>::doSomething()'
collect2: ld returned 1 exit status
make: *** [app.exe] Error 1
It seems, that A<int> gets implicitly instantiated in the create function (*). Then when the compiler sees the explicit instantiation, it prints the warning that it ignores the dllexport attribute, and thus the symbols for A<int> are not exported. Thats why we receive the linker error for the application later. If the create function had not been in the code, then everything would work fine.
(*) - question 1: Can the class template be instantiated at this point? The class template itself should be defined, but it's methods are not, yet. Explicit instantiation only works, if the methods are also defined - is that correct?
For case number two (USE_EXTERN_TEMPLATE is defined), which instructs the compiler not to instantiate A<int> implicitly, I get the following output:
i686-mingw32-g++ -Wall -shared -o dll.dll -DEXPORTS A.cpp
i686-mingw32-g++ -Wall -o app.exe main.cpp dll.dll
/tmp/ccJxb3Ub.o:main.cpp:(.text+0x5f): undefined reference to `typeinfo for A<int>'
collect2: ld returned 1 exit status
make: *** [app.exe] Error 1
The warning disappears, and the symbols, which were missing in case one, are indeed in the generated DLL. But now the typeinfo for A<int> is missing (**).
(**) - question 2: Shouldn't be the typeinfo, also be in the DLL?
In principle I would like to use case one, since case two is an extension to C++ (until now). Is it somehow possible, that the compiler does not ignore the attributes for explicit templated instantiation? Exporting all symbols is also no possible solution for me, since the linker does not finish anymore, when I am creating builds with debugging information (the above example is a very trimmed version of my real problem).
I hope that somebody can help me.
Thank you in advance,
Martin Lederhilger
--
=============================================================
Martin Lederhilger
Convergent Information Technologies GmbH
Schulstrasse 2
A 4053 Haid
++43-720 720 522 (phone)
ml@convergent-it.at (email)
www.convergent-it.at (web)
=============================================================
Sitz: 4053 Haid, Ãsterreich, FB-Nr: FN317229p Landgericht Linz
Geschäftsführer Dr.-Ing Christof Eberst, UID: ATU64458134
More information about the Gcc-help
mailing list