views:

232

answers:

2

Hello,

Environment: Visual Studio 9, C++ without managed extensions.

I've got a third-party library which exports a fully-specialized template class MyClass<42> defined in MyClass.h. It gets compiled into a helper loader .lib and a .dll file. The .lib file contains compiled code for this specialization, and necessary symbols. The MyClass.h looks like this:

template<UInt D>
class MyClass {
public:
    MyClass() {...};
    virtual ~MyClass() {};
}

Now I'd like to use this library. If I include the MyClass.h in a Client.cpp and then compile it, I'll get second copy of these symbols in the Client.obj file. I can get rid of these symbols by defining all the member of that specialization as "extern". My Client.cpp looks like this:

#include <ThirdParty/MyClass.h>

extern template class MyClass<42>;
extern template MyClass<42>::MyClass<42>();
extern template MyClass<42>::~MyClass<42>();

void MyFunction(MyClass<42>& obj) {...}

The problem is that I cannot get rid of the virtual destructor this way. For the virtual destructor I get an almost standard LNK2005 error:

ThirdPartyd.lib(ThirdPartyd.dll) : error LNK2005:
    "public: virtual __thiscall MyClass<42>::~MyClass<42>(void)"
    (??1?$MyClass@$01@@@UAE@XZ) already defined in Client.obj

What should I do?

+1  A: 

I believe Visual studio uses template specialization in dlls for some stl constructs. string comes to mind,

I had a quick look at the header file, and it looks like it's using

__declspec(dllimport)

on the declaration of a bunch of specializations. It does not seem that it does so for the whole class though.

From this discussion it sounds like it is possible to declare the whole class as exported, but does not say how.

Sorry for the not-so-complete answer, but hopefully, this can help you explore other venues.

Bahbar
+1 I'm glad you gave even such a small tip.
liori
A: 

It seems that for virtual methods it is necessary to define them as both extern and __declspec(dllimport) at the same time:

extern template __declspec(dllimport) MyClass<42>::~MyClass<42>();

This made my linker happy enough to link my code properly.

I would be very glad if some expert described why is so, or at least pointed to some article explaining this case.

liori