public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* Explicit template instantiation and not exported symbols in the resulting DLL
@ 2011-08-09 12:44 Martin Lederhilger
  2011-08-11  6:12 ` Martin Lederhilger
  0 siblings, 1 reply; 3+ messages in thread
From: Martin Lederhilger @ 2011-08-09 12:44 UTC (permalink / raw)
  To: gcc-help

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

 



^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Explicit template instantiation and not exported symbols in the resulting DLL
  2011-08-09 12:44 Explicit template instantiation and not exported symbols in the resulting DLL Martin Lederhilger
@ 2011-08-11  6:12 ` Martin Lederhilger
  2011-08-11 10:15   ` Jonathan Wakely
  0 siblings, 1 reply; 3+ messages in thread
From: Martin Lederhilger @ 2011-08-11  6:12 UTC (permalink / raw)
  To: Martin Lederhilger; +Cc: gcc-help

Hello,

a better title would have been "Attributes for explicit template
instantiation are ignored after an implicit template instantiation
occurred".

There is also a small mistake in my example. The declaration for the
create function should look like "... inline A<int>* create() ...".

Now concentrating on case one of the example (not using the extern
template extension):
- I should note that this compiles fine with MSVC (although I do not
want to take it as a reference implementation and I cannot really use it
for other reasons).
- In my opinion it makes sense to give attributes on an explicit
template instantiation precedence.

What should I do in the case I receive no answer? Bugreport? Wishlist?

Maybe you can also point me to the code, where the attributes are
actually assigned in the GCC code. I already found the point, where the
warning is generated in attribs.c, but I do not really have a clue -
simply commenting that if block in the hope, that the attributes are
then assigned did not help, only the warning disappeared.

Thanks for your help,

Martin
-- 
=============================================================
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

 




^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Explicit template instantiation and not exported symbols in the resulting DLL
  2011-08-11  6:12 ` Martin Lederhilger
@ 2011-08-11 10:15   ` Jonathan Wakely
  0 siblings, 0 replies; 3+ messages in thread
From: Jonathan Wakely @ 2011-08-11 10:15 UTC (permalink / raw)
  To: Martin Lederhilger; +Cc: gcc-help

On 11 August 2011 07:11, Martin Lederhilger wrote:
>
> What should I do in the case I receive no answer? Bugreport? Wishlist?

A bug report, describing the behaviour you think is wrong and what the
correct behaviour would be (I'm not familiar enough with the semantics
of dllimport/dllexport to comment.)

I'm not sure why you're not happy to use the extern template extension
though - it's supported by MSVC and GCC (and other compilers) and is
closer to standard than __declspec, as it's part of C++11.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2011-08-11 10:15 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-08-09 12:44 Explicit template instantiation and not exported symbols in the resulting DLL Martin Lederhilger
2011-08-11  6:12 ` Martin Lederhilger
2011-08-11 10:15   ` Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).