templates exported from a DLL and /CLR

  • Thread starter Vyacheslav Lanovets
  • Start date
V

Vyacheslav Lanovets

Hi All!

In native mode I can export class template from a DLL this way:
template <typename T> class TSuperType
{
public:
T doSomething();
};

....

template class __declspec (dllexport) TSuperType<int>;

And I can import it this way in another module:
template class __declspec (dllimport) TSuperType<int>;

But when I enable CLR support on both modules and recompile I get LNK2028
and LNK2019 errors about missing doSomething(). I don't have any explicit
calling convention anywhere and _both_ modules are compiled with /CLR. What
can I do?



TestCLRXportTemplates.obj : error LNK2028: unresolved token (0A00001C)
"public: int __thiscall TSupertType<int>::getData(void)"
(?getData@?$TSupertType@H@@$$FQAEHXZ) referenced in function "int __cdecl
wmain(int,wchar_t * * const)" (?wmain@@$$HYAHHQAPA_W@Z)

TestCLRXportTemplates.obj : error LNK2019: unresolved external symbol
"public: int __thiscall TSupertType<int>::getData(void)"
(?getData@?$TSupertType@H@@$$FQAEHXZ) referenced in function "int __cdecl
wmain(int,wchar_t * * const)" (?wmain@@$$HYAHHQAPA_W@Z)

C:\Documents\Visual Studio
2005\Projects\Test\TestCLRXportTemplates\Debug\TestCLRXportTemplates.exe :
fatal error LNK1120: 2 unresolved
 
B

Bruno van Dooren

In native mode I can export class template from a DLL this way:
template <typename T> class TSuperType
{
public:
T doSomething();
};

...

template class __declspec (dllexport) TSuperType<int>;

this will generate a compiler warning (C4661) with VS2005 because there is
no suitable definition for doSomething. i.e. there is no implementation of
that function, only a declaration. I assume that you implement that function
where you typed '...'?
I.e.
template <typename T> T TSuperType<T>::doSomething()
{
return T(); //or do something useful here
}
template class __declspec (dllexport) TSuperType said:
And I can import it this way in another module:
template class __declspec (dllimport) TSuperType<int>;

did you add the lib file of your dll to the linker input of your
application? otherwise the linker will not find the implementation of the
methods in your template and you will get those errors when building the
application.
Once the linker input is OK, and with all the methods defined before the
dllexport, the code compiles and links without a problem with /clr set.

--

Kind regards,
Bruno van Dooren
(e-mail address removed)
Remove only "_nos_pam"
 
V

Vyacheslav Lanovets

Yes, I implemented doSomething() to "return T();" just before
__declspec(dllexport) directive.

#include "templ.h"
template <typename T>
T TSuperType<T>::doSomething()
{
return T();
}
template class __declspec (dllexport) TSuperType<int>;

I have both projects in one solution and I just set dependencies between
them.
It compiles, links and works perfectly without /clr switch.
But it complains with /clr switch.
 
B

Bruno van Dooren

I have both projects in one solution and I just set dependencies between
them.
It compiles, links and works perfectly without /clr switch.
But it complains with /clr switch.

I did the same, but I also had to explicitly specify the lib file of the dll
as an additional linker input.
Doing that makes it work. not doing that results in the linker errors you
posted.
To be honest I don't know if it is a bug or a feature...

--

Kind regards,
Bruno van Dooren
(e-mail address removed)
Remove only "_nos_pam"
 
B

Bruno van Dooren

Thank you for you help.

I did some additional testing, and I think I know why it is like this.

If your dll is unmanaged, it is reasonable to expect that it would contain
exports.
if another project depends upon it, it is therefore reasonable to feed the
lib file into the linker command for the application. That is why 'Link
library dependencies' is set by default.

if you specify the /clr switch for the dll, the assumption that it will
contain unmanaged exports is no longer valid.
it could just as well be a classlib. in that case (no native exports) there
will be no lib file because there are no import directives to generate. If
there is no lib file, the build of your app would fail since it would expect
it to be there.

So on one hand, it is not unreasonable that the lib file is not
automatically fed into the linker command of the app (since the dependency
could be a managed one instead of an unmanaged one). On the other hand, the
flag 'Link library dependencies' is still set to yes, so you would expect it
to do so, regardless of the build options of the dll.
It seems that VS ignores the 'Link library dependencies' option for mixed
mode dlls

If that is so they should at least have mentioned it in the documentation
for 'Link library dependencies'
Anyway I have validated it, but only rated it as an annoyance because VS
errs on the safe side and it is trivial to work around

--

Kind regards,
Bruno van Dooren
(e-mail address removed)
Remove only "_nos_pam"
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top