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