anthon007r
asked on
Migration of template class from unmanaged to managed
I have this template classes that make use of STL.
I'm trying to make a DLL or a class library project type in vs.net 2003.
I want my template classes be exposed by including it to the project so that when I need the functionality of my class, ill just add a reference to the DLL.
Please give me how-to's and examples.
Thanks.
I'm trying to make a DLL or a class library project type in vs.net 2003.
I want my template classes be exposed by including it to the project so that when I need the functionality of my class, ill just add a reference to the DLL.
Please give me how-to's and examples.
Thanks.
ASKER
thanks AlexFM, but what am I going to do now? Could you please elaborate the this:
class A<int> a; // A<int> is real class which can be compiled
because im having an error.. and how am i going to transform my classes so that it will be able to be exposed in DLL?
Does it mean I cannot use STL anymore?
Please help. Thanks.
class A<int> a; // A<int> is real class which can be compiled
because im having an error.. and how am i going to transform my classes so that it will be able to be exposed in DLL?
Does it mean I cannot use STL anymore?
Please help. Thanks.
Please show some code fragments, what classes do you want to export from Dll?
ASKER
ok here it is..
#include "TreeNode.h"
template<class Type>
class CTTree
{
public:
////// Constructors
CTTree();
////// Destructors
~CTTree();
////// Data members
CTTreeNode<Type>* m_root;
CTTreeNode<Type>* m_inOrderTraverser;
CTTreeNode<Type>* m_preOrderTraverser;
CTTreeNode<Type>* m_postOrderTraverser;
unsigned char m_chInOrderStat; // monitors InOrder traversals
unsigned char m_chPreOrderStat;
unsigned char m_chPostOrderStat;
enum E_TraversalType { e_ttInOrder = 1, e_ttPreOrder, e_ttPostOrder, e_ttAll }; //e_tt prefixed
enum E_TraversalStat { e_tsFirstTime = 1, e_tsLeftTraversal, e_tsRightTraveral, e_tsRootTraversal, e_tsFinished }; //e_ts prefixed
enum E_EnumerateLeafOrder { e_elLeftToRight = 1, e_elRightToLeft }; //e_el prefixed
////// Basic functions
bool hasE_TraversalStatus(unsig ned char chStat, E_TraversalStat e_tsStat);
void resetTraverse(E_TraversalT ype e_ttType);
CTTreeNode<Type>* getNodeInOrder(void);
CTTreeNode<Type>* getNodePreOrder(void);
CTTreeNode<Type>* getNodePostOrder(void);
CTTreeNode<Type>* getLeafPreOrder(void);};
////// Constructors
template<class Type>
CTTree<Type>::CTTree()
{
this->m_root = new CTTreeNode<Type>();
this->m_root->m_parent = 0;
this->m_root->m_leftChild = 0;
this->m_root->m_rightChild = 0;
this->m_root->m_iInfo = this->m_root->ROOT | this->m_root->RIGHT_THREAD ;
}
///// Destructors
template<class Type>
CTTree<Type>::~CTTree()
{
}
///// Basic Functions
template<class Type>
void CTTree<Type>::resetTravers e(E_Traver salType tType)
{
switch(tType)
{
case this->e_ttInOrder:
this->m_inOrderTraverser = this->m_root;
this->m_chInOrderStat = 0;
break;
case this->e_ttPreOrder:
this->m_preOrderTraverser = this->m_root;
this->m_chPreOrderStat = this->e_tsFirstTime;
break;
case this->e_ttPostOrder:
this->m_postOrderTraverser = this->m_root;
this->m_chPostOrderStat = 0;
break;
case this->e_ttAll:
this->m_preOrderTraverser = this->m_root;
this->m_chPreOrderStat = this->e_tsFirstTime;
this->m_inOrderTraverser = this->m_root;
this->m_chInOrderStat = 0;
this->m_postOrderTraverser = this->m_root;
this->m_chPostOrderStat = 0;
break;
default: ;
break;
}
}
template<class Type>
CTTreeNode<Type>* CTTree<Type>::getNodePreOr der(void)
{
switch(this->m_chPreOrderS tat)
{
case this->e_tsLeftTraversal:
// Search for leftChild, switch to it and return it ########################## #####
if(this->m_preOrderTravers er->m_left Child)
{
// go to traverser's left
this->m_preOrderTraverser = this->m_preOrderTraverser- >m_leftChi ld;
// return the traverser's address
return this->m_preOrderTraverser; // also assures next lines will not be executed
}
// shift to RightTraversal
this->m_chPreOrderStat = this->e_tsRightTraveral;
// intentionally no "break;" to make things go on
// break;
case this->e_tsRightTraveral:
// Search for rightChild ########################## ########## ########## ########## ##
if( !this->m_preOrderTraverser ->m_rightC hild )
{
this->m_chPreOrderStat = this->e_tsFinished;
break;
}
// while traverser's rightChild IS a thread
while(this->m_preOrderTrav erser->isI nfoAKindOf (this->m_p reOrderTra verser->RI GHT_THREAD ))
{ // find the thread pointing to node with rightChild
this->m_preOrderTraverser = this->m_preOrderTraverser- >m_rightCh ild;
}
// go to traverser's right which is NOT anymore a thread
this->m_preOrderTraverser = this->m_preOrderTraverser- >m_rightCh ild;
// check if leftChild exise_ts
if(this->m_preOrderTravers er->m_left Child)
{
// Switch mode then;
this->m_chPreOrderStat = this->e_tsLeftTraversal;
}
// return the traverser's address
return this->m_preOrderTraverser;
case this->e_tsFirstTime: // is necessary to output the root
this->m_chPreOrderStat = this->e_tsLeftTraversal;
return this->m_preOrderTraverser;
case this->e_tsFinished:
return 0;
default: ;
break;
}
return 0;
}
template<class Type>
CTTreeNode<Type>* CTTree<Type>::getNodeInOrd er(void)
{
return 0;
}
template<class Type>
CTTreeNode<Type>* CTTree<Type>::getNodePostO rder(void)
{
return 0;
}
template<class Type>
CTTreeNode<Type>* CTTree<Type>::getLeafPreOr der(void)
{
CTTreeNode<Type>* tmpNode;
for( tmpNode = this->getNodePreOrder(); tmpNode; )
{
if( tmpNode->isInfoAKindOf(tmp Node->RIGH T_THREAD) && // no rightChild
!tmpNode->m_leftChild ) // no leftChild
{
return tmpNode;
}
tmpNode = this->getNodePreOrder();
}
return 0;
}
that is one of those classes... my system is quite large so i can't put it all here..
Thanks again AlexFM.
#include "TreeNode.h"
template<class Type>
class CTTree
{
public:
////// Constructors
CTTree();
////// Destructors
~CTTree();
////// Data members
CTTreeNode<Type>* m_root;
CTTreeNode<Type>* m_inOrderTraverser;
CTTreeNode<Type>* m_preOrderTraverser;
CTTreeNode<Type>* m_postOrderTraverser;
unsigned char m_chInOrderStat; // monitors InOrder traversals
unsigned char m_chPreOrderStat;
unsigned char m_chPostOrderStat;
enum E_TraversalType { e_ttInOrder = 1, e_ttPreOrder, e_ttPostOrder, e_ttAll }; //e_tt prefixed
enum E_TraversalStat { e_tsFirstTime = 1, e_tsLeftTraversal, e_tsRightTraveral, e_tsRootTraversal, e_tsFinished }; //e_ts prefixed
enum E_EnumerateLeafOrder { e_elLeftToRight = 1, e_elRightToLeft }; //e_el prefixed
////// Basic functions
bool hasE_TraversalStatus(unsig
void resetTraverse(E_TraversalT
CTTreeNode<Type>* getNodeInOrder(void);
CTTreeNode<Type>* getNodePreOrder(void);
CTTreeNode<Type>* getNodePostOrder(void);
CTTreeNode<Type>* getLeafPreOrder(void);};
////// Constructors
template<class Type>
CTTree<Type>::CTTree()
{
this->m_root = new CTTreeNode<Type>();
this->m_root->m_parent = 0;
this->m_root->m_leftChild = 0;
this->m_root->m_rightChild
this->m_root->m_iInfo = this->m_root->ROOT | this->m_root->RIGHT_THREAD
}
///// Destructors
template<class Type>
CTTree<Type>::~CTTree()
{
}
///// Basic Functions
template<class Type>
void CTTree<Type>::resetTravers
{
switch(tType)
{
case this->e_ttInOrder:
this->m_inOrderTraverser = this->m_root;
this->m_chInOrderStat = 0;
break;
case this->e_ttPreOrder:
this->m_preOrderTraverser = this->m_root;
this->m_chPreOrderStat = this->e_tsFirstTime;
break;
case this->e_ttPostOrder:
this->m_postOrderTraverser
this->m_chPostOrderStat = 0;
break;
case this->e_ttAll:
this->m_preOrderTraverser = this->m_root;
this->m_chPreOrderStat = this->e_tsFirstTime;
this->m_inOrderTraverser = this->m_root;
this->m_chInOrderStat = 0;
this->m_postOrderTraverser
this->m_chPostOrderStat = 0;
break;
default: ;
break;
}
}
template<class Type>
CTTreeNode<Type>* CTTree<Type>::getNodePreOr
{
switch(this->m_chPreOrderS
{
case this->e_tsLeftTraversal:
// Search for leftChild, switch to it and return it ##########################
if(this->m_preOrderTravers
{
// go to traverser's left
this->m_preOrderTraverser = this->m_preOrderTraverser-
// return the traverser's address
return this->m_preOrderTraverser;
}
// shift to RightTraversal
this->m_chPreOrderStat = this->e_tsRightTraveral;
// intentionally no "break;" to make things go on
// break;
case this->e_tsRightTraveral:
// Search for rightChild ##########################
if( !this->m_preOrderTraverser
{
this->m_chPreOrderStat = this->e_tsFinished;
break;
}
// while traverser's rightChild IS a thread
while(this->m_preOrderTrav
{ // find the thread pointing to node with rightChild
this->m_preOrderTraverser = this->m_preOrderTraverser-
}
// go to traverser's right which is NOT anymore a thread
this->m_preOrderTraverser = this->m_preOrderTraverser-
// check if leftChild exise_ts
if(this->m_preOrderTravers
{
// Switch mode then;
this->m_chPreOrderStat = this->e_tsLeftTraversal;
}
// return the traverser's address
return this->m_preOrderTraverser;
case this->e_tsFirstTime: // is necessary to output the root
this->m_chPreOrderStat = this->e_tsLeftTraversal;
return this->m_preOrderTraverser;
case this->e_tsFinished:
return 0;
default: ;
break;
}
return 0;
}
template<class Type>
CTTreeNode<Type>* CTTree<Type>::getNodeInOrd
{
return 0;
}
template<class Type>
CTTreeNode<Type>* CTTree<Type>::getNodePostO
{
return 0;
}
template<class Type>
CTTreeNode<Type>* CTTree<Type>::getLeafPreOr
{
CTTreeNode<Type>* tmpNode;
for( tmpNode = this->getNodePreOrder(); tmpNode; )
{
if( tmpNode->isInfoAKindOf(tmp
!tmpNode->m_leftChild ) // no leftChild
{
return tmpNode;
}
tmpNode = this->getNodePreOrder();
}
return 0;
}
that is one of those classes... my system is quite large so i can't put it all here..
Thanks again AlexFM.
This is enough. It's impossible to export these classes from Dll. These classes should be supplied in h-files with full implementation code. Client (other programmer which uses these templates for instantiation) should have these h-files to compile his code.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thanks AlexFM for an idea.. but when I tried to include may header files that have codes for my classes, it generates a linker error (LNK2005)
this is my code for my class that generates an error if i tried to include
------------------
#pragma once
using namespace std;
class CTTreeNodeGreater : public greater< CTTreeNode< CSymbol<unsigned char> > >
{
public:
bool operator () ( CTTreeNode< CSymbol<unsigned char> > *nodeLeft,
CTTreeNode< CSymbol<unsigned char> > *nodeRight );
};
bool CTTreeNodeGreater::operato r () ( CTTreeNode< CSymbol<unsigned char> > *nodeLeft,
CTTreeNode< CSymbol<unsigned char> > *nodeRight )
{
if(nodeLeft->m_data.m_iFre quency > nodeRight->m_data.m_iFrequ ency ) // 1st level
return true;
else if(nodeLeft->m_data.m_iFre quency == nodeRight->m_data.m_iFrequ ency )
{
return (nodeLeft->m_data.m_Symbol > nodeRight->m_data.m_Symbol ); // 2nd level
}
else
return false;
}
--------------- end of header file
the error code is:
"error LNK2005: "public: bool __thiscall CTTreeNodeGreater::operato r()(class CTTreeNode<class CSymbol<unsigned char> > *, class CTTreeNode<class CSymbol<unsigned char> > *)(??RCTTreeNodeGreater@@Q AE_NPAV?$C TTreeNode@ V?$CSymobl @E@@@@0@Z) already defined in frmMain.obj
that's a super long error code :(
NOTE: no copy paste operation it may have some typos in there
this is my code for my class that generates an error if i tried to include
------------------
#pragma once
using namespace std;
class CTTreeNodeGreater : public greater< CTTreeNode< CSymbol<unsigned char> > >
{
public:
bool operator () ( CTTreeNode< CSymbol<unsigned char> > *nodeLeft,
CTTreeNode< CSymbol<unsigned char> > *nodeRight );
};
bool CTTreeNodeGreater::operato
CTTreeNode< CSymbol<unsigned char> > *nodeRight )
{
if(nodeLeft->m_data.m_iFre
return true;
else if(nodeLeft->m_data.m_iFre
{
return (nodeLeft->m_data.m_Symbol
}
else
return false;
}
--------------- end of header file
the error code is:
"error LNK2005: "public: bool __thiscall CTTreeNodeGreater::operato
that's a super long error code :(
NOTE: no copy paste operation it may have some typos in there
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
you're the man! great! it worked! hehe but that's weird.. I don't have to make it inline when it was on VS6.0. By the way thanks! But one last question, how about those static const members? e.g.:
struct CMyclass
{
static const float m_fData;
};
const float CArchiverHeader::m_fData = 1.0000;
now this one generates two error, one is just the same as the above (LNK2005) and a LNK1169
Thanks a lot AlexFM
struct CMyclass
{
static const float m_fData;
};
const float CArchiverHeader::m_fData = 1.0000;
now this one generates two error, one is just the same as the above (LNK2005) and a LNK1169
Thanks a lot AlexFM
const float CArchiverHeader::m_fData = 1.0000;
This line should be placed in one cpp file in the project. Don't place it in h-file.
This line should be placed in one cpp file in the project. Don't place it in h-file.
ASKER
actually, at first I tried including my class to frmMain.h and it generates an error.
Incidentally, I re-organized my codes and put my include declaration under stdafx.h
and the error is gone. So there's no really need for seperating it to a cpp file.
But why is this happening?
What's wrong with my headers being included in frmMain.h instead in stdafx.h?
Just want to clear it up why
Incidentally, I re-organized my codes and put my include declaration under stdafx.h
and the error is gone. So there's no really need for seperating it to a cpp file.
But why is this happening?
What's wrong with my headers being included in frmMain.h instead in stdafx.h?
Just want to clear it up why
ASKER
im asking to much hehe so here's the increase
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
now im confused :( i put back my header declaration to frmMain.h and its now working.. i dont know what i did to make it work, but it works without seperating the static const members to another cpp file.
By the ways thanks AlexFM =)
By the ways thanks AlexFM =)
If the line
const float CArchiverHeader::m_fData = 1.0000;
is part of h-file, it may work if this h-file is included to one cpp file in the project. But if you include this h-file to two or more cpp files, you get linker error "Variable is already defined in...".
const float CArchiverHeader::m_fData = 1.0000;
is part of h-file, it may work if this h-file is included to one cpp file in the project. But if you include this h-file to two or more cpp files, you get linker error "Variable is already defined in...".
ASKER
can't the "#pragma once" prevent it from being included in two or more cpp files?
#pragma once prevents h-file to be included twice into the same cpp file.
ASKER
AlexFM, I got some related question please follow this link, I know you could help me there =)
https://www.experts-exchange.com/questions/21222458/STL-in-class-library-project-DLL.html
https://www.experts-exchange.com/questions/21222458/STL-in-class-library-project-DLL.html
The reason of this that template class is not real C++ class. It is not compiled by C++ compiler, and cannot be written to .obj file and linked to library. C++ compiler only makes basic syntax check of templated class.
Template becomes real C++ class, which can be compiled and linked, only when it is instantiated in the client code. At this point compiler needs full template source code.
// This is not real class
template <class T>
class A
{
};
class A<int> a; // A<int> is real class which can be compiled