Reputation: 1197
At the moment I'm working on implementing a managed wrapper in C++/CLI, for a native C library.
I have no hard experience with the language, and this week has been a sort of crash course while trying to complete my project. Although it has a few surprising and frustrating quirks, there are plenty of good articles floating around.
Background:
WrappedAvType
) declared in a Common.h
and the class members are implemented in a corresponding Common.cpp
, and they are both in the project root directory...\Common.h
to access the class declaration it containsCommon.h:
#pragma once
namespace LibavDotNet {
template<class T>
public ref class WrappedAvType abstract
{
public:
property bool IsDirty;
WrappedAvType();
WrappedAvType(T avObject);
~WrappedAvType();
virtual T Unwrap();
private:
T _avObject;
protected:
virtual void SetAvObject(T avObject);
};
}
Common.cpp:
#include "Common.h"
namespace LibavDotNet {
template<class T>
WrappedAvType<T>::WrappedAvType()
{
IsDirty = false;
}
template<class T>
WrappedAvType<T>::WrappedAvType(T avObject)
{
_avObject = avObject;
}
template<class T>
WrappedAvType<T>::~WrappedAvType()
{ }
template<class T>
T WrappedAvType<T>::Unwrap()
{
return _avObject;
}
template<class T>
void WrappedAvType<T>::SetAvObject(T avObject)
{
_avObject = avObject;
}
}
However I'm currently stumped (maybe blinded from staring at the code for too damn long...) with a peculiar problem: whenever I compile the project in its described state, I receive error LNK2020
indicating that it no token can be found for WrappedAvType
.
To confirm that the symbols were available in the generated binary, I used dumpbin /symbols Common.obj
and in fact there don't appear to be any:
Microsoft (R) COFF/PE Dumper Version 11.00.61030.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file Common.obj
File Type: COFF OBJECT
COFF SYMBOL TABLE
000 00CFEE66 ABS notype Static | @comp.id
001 80000191 ABS notype Static | @feat.00
002 00000000 SECT1 notype Static | .drectve
Section length 78, #relocs 0, #linenums 0, checksum 0
004 00000000 SECT2 notype Static | .debug$S
Section length 35C, #relocs 0, #linenums 0, checksum 0
006 00000000 SECT3 notype Static | .debug$T
Section length 7C, #relocs 0, #linenums 0, checksum 0
008 00000000 SECT4 notype Static | .cormeta
Section length 45C, #relocs 0, #linenums 0, checksum 0
String Table Size = 0x0 bytes
Summary
45C .cormeta
35C .debug$S
7C .debug$T
78 .drectve
If I include the class implementation directly with #include "..\Common.cpp"
in the other source files that need it (only one other so far), then the project compiles as expected.
At this point I have no idea what else to try and have searched for a solution for hours. I'd very much like to keep my headers with class declarations and source files with class implementations separate.
I fully expect this to be something minor that I've overlooked or that I'm just too green to notice. What am I missing?
Upvotes: 0
Views: 332
Reputation: 941455
template<class T>
This is a standard C++ problem, it doesn't have anything to do with C++/CLI. Templates do not have external linkage. The entire implementation of the template class must be present in the .h file. Which is why the #include worked.
Do keep the strong code smell in mind, templates are a pure C++ feature. Your wrapper isn't actually usable by any other .NET language, they don't support templates of course. Only ref classes that are declared with the generic keyword are usable.
Upvotes: 2