[C++] template-class met een declspec wil niet

Pagina: 1
Acties:

  • MisterData
  • Registratie: September 2001
  • Laatst online: 26-08 21:52
Beetje wazige titel, maar ik zal het proberen uit te leggen. Ik heb een class CLinkedList gemaakt (ja ik weet het, ik kan ook std::list gebruiken) en die heeft een template, zodat ik alles in dat ding kan stoppen wat ik wil:

C++:
1
2
3
template<class T> class CLinkedList {
// zooi
};


Ga ik dit compileren in MSVC6 (in een DLL projectje) dan gaat alles goed, en geeft VC alleen een warning in de trant van 'class CLinkedList must have a DLL interface to be used by clients' (nummertje C4251). Allemaal goed dus, geen syntaxfouten. Maar, ik wil deze class juist wel gebruiken buiten de DLL. Dus, zet ik er een __declspec(dllexport) in:

C++:
1
2
3
__declspec(dllexport) template<class T> class CLinkedList {
 // zooi
};


Nu krijg ik van VC eerst de volgende error:
'__declspec(dllexport ) ' : ignored on left of 'int' when no variable is declared
en verder nog een aantal errors (dat de class CLinkedList niet bestaat). Zet ik de declspec tussen template<class T> en class CLinkedList in:
C++:
1
template<class T> __declspec(dllexport) class CLinkedList {
error C2059: syntax error : '<end Parse>'
En dan krijg ik nog es 309 :7 errors van andere classes die in die .h file zijn gedeclareerd. Wie weet hoe het wel moet?

[ Voor 6% gewijzigd door MisterData op 24-12-2002 12:10 . Reden: spastisch typen is niet goed ]


Verwijderd

IMHO heb je geen class gemaakt, maar een template. En een template kan niet gecompileerd worden, dus kun je daar ook geen lib van maken, of zie ik dat verkeerd :?
Pas als je je template instatieert krijg je een class en die zou je in je een lib kunnen zetten...toch :?

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Volgens mij kan dit niet. Tenminste niet zoals jij wilt, je kan geen generic class in een DLL gooien. Je kan volgens mij wel explicit template instantiations exporteren. Dus zoiets:

code:
1
__declspec(dllexport) template class CLinkedList<int>;


Hoewel ik dat niet zeker weet.


En als je explicit linking (dynamic loading) wilt gebruiken, dat kan je sowieso geen C++ class exporteren. Dit is een goed voorbeeld hoe je het zou knnen aanpakken: http://www.codeguru.com/mfc/comments/1156.shtml

[ Voor 29% gewijzigd door Zoijar op 24-12-2002 12:29 ]


  • MisterData
  • Registratie: September 2001
  • Laatst online: 26-08 21:52
Zoijar schreef op 24 december 2002 @ 12:25:
Volgens mij kan dit niet. Tenminste niet zoals jij wilt, je kan geen generic class in een DLL gooien. Je kan volgens mij wel explicit template instantiations exporteren. Dus zoiets:

code:
1
__declspec(dllexport) template class CLinkedList<int>;


Hoewel ik dat niet zeker weet.


En als je explicit linking (dynamic loading) wilt gebruiken, dat kan je sowieso geen C++ class exporteren. Dit is een goed voorbeeld hoe je het zou knnen aanpakken: http://www.codeguru.com/mfc/comments/1156.shtml
C++ classes kun je wel exporteren toch :? Hoe doet bijvoorbeeld wxWindows of MFC dat dan? Ik zal nu es kijken of ik die instantie can die CLinkedList kan exporten :)

edit:// misschien moet ik dit maar es proberen: http://www.experts-exchan...Cplusplus/Q_20263546.html

edit://2/ Ik heb nu dit:
C++:
1
2
3
// Iets is in dit geval een class die in de lijst moet worden opgeslagen
extern template class __declspec(dllexport) CLinkedList<Iets>;
extern template class __declspec(dllexport) CLinkedListEntry<Iets>;


Ik krijg nu een stuk of 5 warnings, is dit wel de goede manier om het te doen?

[ Voor 26% gewijzigd door MisterData op 24-12-2002 12:43 ]


Verwijderd

MisterData schreef op 24 december 2002 @ 12:32:
C++ classes kun je wel exporteren toch :? Hoe doet bijvoorbeeld wxWindows of MFC dat dan? Ik zal nu es kijken of ik die instantie can die CLinkedList kan exporten :)
Maar een template is geen class... De instantie van een template is een class en die kun je exporteren...

  • MisterData
  • Registratie: September 2001
  • Laatst online: 26-08 21:52
Verwijderd schreef op 24 december 2002 @ 12:37:
[...]

Maar een template is geen class... De instantie van een template is een class en die kun je exporteren...
Dus volgens jou hoef ik die CLinkedList helemaal niet te exporteren aangezien ik 'em alleen gebruik als member-variabele van een andere class?

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
#define api __declspec(dllexport)
template<T> class CLinkedList {

};

api class Iets {

};

api class KlasseMetLijst {
     private:
         CLinkedList<Iets> mijnlijst;
};


Zoiets dus?

Verwijderd

MisterData schreef op 24 December 2002 @ 12:46:
Dus volgens jou hoef ik die CLinkedList helemaal niet te exporteren aangezien ik 'em alleen gebruik als member-variabele van een andere class?
Nee sterker nog, je kunt een template niet exporteren, omdat er niks te exporteren valt aan een template, het is immers niet te compileren tot een objectfile en een dll is niets anders dan een archief met verschillende (voorgecompileerde) objectfiles erin.
C++:
1
2
3
4
5
6
7
8
9
10
11
#define api __declspec(dllexport)
template<T> class CLinkedList {
};

api class Iets {
};

api class KlasseMetLijst {
     private:
         CLinkedList<Iets> mijnlijst;
};

Zoiets dus?
Lijkt mij wel ja. Maar het is (volgens mij en zoijar) ook mogelijk verschillende instaties van je template te exporteren, maar dan moeten het dus wel instaties van een template oftwel classes zijn.

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Je kan een class alleen statisch exporteren (implicit linking). Dus dan moet je je uiteindelijke programma linken met de .lib file die bij de DLL is geleverd, en als je programma start moet de DLL automatisch gevonden kunnen worden (door bv in de working dir of dll path te staan). Vandaar de naam "implicit linking", ie. het runtime linken met de dll gebeurt impliciet.

Maar veel programmas willen "plugins" ondersteunen. Die laden bij het begin van het programma dynamisch een dll in. Als deze niet gevonden wordt, kan het programma gewoon verder gaan en de desbetrefende plgin bv uitschakelen. Een voorbeeld is een applicatie die zowel opengl als direct3d ondersteuning heeft. Er kan eerst naar opengl32.dll worden gezocht, en als die niet gevonden wordt kan er als fall-back de d3d dll geladen worden. Dit kan alleen met explicit linking dlls.

Waarom je niet expliciet kan linken met een exported C++ class heeft te maken met name-mangling en pointer conversion. Je kan in principe geen pointer-to-member converteren naar een ander type, normale, pointer. Logisch want een pointer-to-member is 2 keer zo groot als een normale pointer.
De truck die ds veel gebruikt wordt is iets een functie die eerst een object creert, en die wordt dan impliciet als eerste deel van de pointer-to-member gebruikt. Veelal heet die functie "createInstance()" en is eingelijk een factory. COM(+) werkt bv op deze manier, en dus d3d en dergelijke ook.

edit:
---

Jouw MFC voorbeeld is een dll die impliciet gelinked wordt. Als de eind gebruiker geen MFC op z'n computer heeft dan doet het programma dat het gebruikt het niet. Je kan ook nog de hele zooi linken bij het compilen, dan bevat jouw programma zeg maar de dll en hoeft de eindgebruiker die dll niet te hebben. Het nadeel hiervan is dat je file groter wordt, en dat de gebruiker misschien wel een nieuwere versie van de dll heeft met bugfixes erin die nu niet gebruikt wordt.

[ Voor 16% gewijzigd door Zoijar op 24-12-2002 13:11 ]


  • MisterData
  • Registratie: September 2001
  • Laatst online: 26-08 21:52
Zoijar schreef op 24 December 2002 @ 12:58:
Je kan een class alleen statisch exporteren (implicit linking). Dus dan moet je je uiteindelijke programma linken met de .lib file die bij de DLL is geleverd, en als je programma start moet de DLL automatisch gevonden kunnen worden (door bv in de working dir of dll path te staan). Vandaar de naam "implicit linking", ie. het runtime linken met de dll gebeurt impliciet.

Maar veel programmas willen "plugins" ondersteunen. Die laden bij het begin van het programma dynamisch een dll in. Als deze niet gevonden wordt, kan het programma gewoon verder gaan en de desbetrefende plgin bv uitschakelen. Een voorbeeld is een applicatie die zowel opengl als direct3d ondersteuning heeft. Er kan eerst naar opengl32.dll worden gezocht, en als die niet gevonden wordt kan er als fall-back de d3d dll geladen worden. Dit kan alleen met explicit linking dlls.

Waarom je niet expliciet kan linken met een exported C++ class heeft te maken met name-mangling en pointer conversion. Je kan in principe geen pointer-to-member converteren naar een ander type, normale, pointer. Logisch want een pointer-to-member is 2 keer zo groot als een normale pointer.
De truck die ds veel gebruikt wordt is iets een functie die eerst een object creert, en die wordt dan impliciet als eerste deel van de pointer-to-member gebruikt. Veelal heet die functie "createInstance()" en is eingelijk een factory. COM(+) werkt bv op deze manier, en dus d3d en dergelijke ook.

edit:
---

Jouw MFC voorbeeld is een dll die impliciet gelinked wordt. Als de eind gebruiker geen MFC op z'n computer heeft dan doet het programma dat het gebruikt het niet. Je kan ook nog de hele zooi linken bij het compilen, dan bevat jouw programma zeg maar de dll en hoeft de eindgebruiker die dll niet te hebben. Het nadeel hiervan is dat je file groter wordt, en dat de gebruiker misschien wel een nieuwere versie van de dll heeft met bugfixes erin die nu niet gebruikt wordt.
Uiteindelijk wil ik mijn DLL inderdaad 'impliciet' linken met een applicatie. Ik zie inderdaad dat VC ook een .lib genereert. Kun je toevallig ook uitleggen waarvoor dat .exp-bestand is :?

Overigens lijkt het nu te werken. Ik heb de waarschuwing over 'class must have a dll-interface' maar gedisable'd met een pragma :)

edit:// de naam 'Dynamic Link Library' begint me nu ook duidelijk te worden :)

[ Voor 4% gewijzigd door MisterData op 24-12-2002 13:32 ]


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Pagina: 1