[VS.NET/ C++] Precompiled headers

Pagina: 1
Acties:

  • Edsger
  • Registratie: December 2000
  • Laatst online: 02-08 17:39
vraag 1) wat is het nut van precompiled headers?
Ik gok erop deze het compilatie proces versnellen.

vraag 2) waarom is het zo, dat telkens als ik een header met bijbehorende .cpp file aan mijn project toevoeg, ik een foutmelding krijg dat mijn precompiled header fout is. :?

De eerste keer gebeurt dat niet, want dan is deze .pch file nog niet gegenereerd. Maar daarna krijg ik elke keer de fatal error dat deze file corrupt is. Het enige dat dan nog helpt is of handmatig de pch file keer op keer verwijderen, of in de compiler opties voor die file geforceerd de optie precompiled headers uitzetten.

Ik vind dit nogal vervelend, omdat ik een header/.cpp file gemaakt heb mij helpt debug uitvoer te genereren die ik in elk project gebruik.

Waar kan dit aan liggen?

Thanx! _/-\o_

All your quantifications are belong to me!


  • .oisyn
  • Registratie: September 2000
  • Nu online

.oisyn

Moderator Devschuur®

Demotivational Speaker

1) idd :)

2) Mja, de precompilation gaat altijd wat vervelend. Het beste is precompilation op 'auto' te zetten, en alle headers die je geprecompiled wil hebben gewoon toevoegen aan je project (zoals windows.h, dat scheelt echt enorm). De rest gaat automatisch :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Edsger
  • Registratie: December 2000
  • Laatst online: 02-08 17:39
Volgens mij heb je me zojuist iets duidelijk gemaakt, waar ik eigenlijk niet om vroeg, maar wat me wel heel wat duidelijk maakt.

Is het zo dat files die je aan je VS project toevoegt, dat alles met deze files "geoptimaliseerd" wordt bij het compilen. Maar als je ze niet toevoegd en alleen maar inlcude, dat ze met rust gelaten worden?

Zo ja, dan zou ik deze debug files van mij graag niet "echt" aan het project toevoegen maar alleen includen, ware het niet dat ik dan altijd een foutmelding krijg "Unexpected end of file"....

All your quantifications are belong to me!


  • .oisyn
  • Registratie: September 2000
  • Nu online

.oisyn

Moderator Devschuur®

Demotivational Speaker

Edsger schreef op 16 January 2003 @ 22:31:
Is het zo dat files die je aan je VS project toevoegt, dat alles met deze files "geoptimaliseerd" wordt bij het compilen. Maar als je ze niet toevoegd en alleen maar inlcude, dat ze met rust gelaten worden?
dat is alleen als precompilation op auto staat
in vs6 stond dat standaard zo, in vs.net is het standaard uit geloof ik
Zo ja, dan zou ik deze debug files van mij graag niet "echt" aan het project toevoegen maar alleen includen, ware het niet dat ik dan altijd een foutmelding krijg "Unexpected end of file"....


die error krijg je alleen bij expliciete precompilation dacht ik

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Edsger
  • Registratie: December 2000
  • Laatst online: 02-08 17:39
Ooh sorry.
Ik begin dingen door elkaar te halen. 8)7 O-)

Die foutmelding krijg je alleen als je bepaalde header files niet include.

Nee, wanneer ik van mijn log.h en log.ccp de files niet include in het project, maar wel gewoon in de code, dan krijg ik unresolved links en daarom ben ik genoodzaakt de files te includen.

Is er niet een mogelijkheid om de precompiled headers "gewoon" te laten werken. Wat is de oorzaak van dit soort problemen? Hij heeft net zelf de precompiled header aangemaakt. Waarom zou de compiler de volgende keer dan opeens gaan klagen dat het niet werkt? |:(

[ Voor 82% gewijzigd door Edsger op 16-01-2003 22:47 ]

All your quantifications are belong to me!


  • Edsger
  • Registratie: December 2000
  • Laatst online: 02-08 17:39
btw... .oisyn
leuke signature
maar je hebt zoveel posts en overal zit dezelfde typo in. randum = random
of was dat met opzet :-)

All your quantifications are belong to me!


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 24-08 22:38
Als je project niet al te groot is en je systeem van deze tijd kun je met een gerust hart die precompiled headers uitzetten.

Overigens, als je stdafx.h include in je custom source krijg je die foutmelding ( unexpected end .. ) niet met precompiled headers aan. Heeft iets te maken met een precompiled header directive waar ie naar zoekt.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 24-08 23:08
Voor wat het waard is: ik zet ze altijd uit. Ik heb er in 't begin (jaren terug) ook last mee gehad en toen begreep ik ook niet wat er mis was. Als je een weekje met KDevelop en de GNU C++ compiler hebt gewerkt, werkt Visual C++ toch al heerlijk snel, met of zonder precompiled headers. :) Een echte oplossing is het natuurlijk niet.

[ Voor 3% gewijzigd door Soultaker op 17-01-2003 10:10 ]


  • Edsger
  • Registratie: December 2000
  • Laatst online: 02-08 17:39
farlane schreef op 17 January 2003 @ 09:00:
Overigens, als je stdafx.h include in je custom source krijg je die foutmelding ( unexpected end .. ) niet met precompiled headers aan. Heeft iets te maken met een precompiled header directive waar ie naar zoekt.
Ik wil juist weten waar het mee te maken heeft ;)
Dus of iemand mij daar het antwoord op kan geven, zou ik daar zeer dankbaar voor zijn. _/-\o_

All your quantifications are belong to me!


  • SWfreak
  • Registratie: Juni 2001
  • Niet online
Als je de foutmelding wil weghalen, moet je naar de solution-explorer gaan, rechts klikken op de cpp-file van je custom source en daar Properties ofzo van selecteren. Dan kun je bij de C++-options onder precompilation de pre-compiled header definieren. Die zal standaard op stdafx.h staan, maar als je dit verandert naar de header van de custom source gaat het goed. Dan krijg je die error-message niet meer en hij maakt zelf een pch voor je custom source.
Waar ze het voor gebruiken weet ik niet, maar het zal het compileer-proces wel vergemakkelijken....

Hoop dat dit het antwoord is wat je zocht?

  • .oisyn
  • Registratie: September 2000
  • Nu online

.oisyn

Moderator Devschuur®

Demotivational Speaker

Edsger schreef op 16 januari 2003 @ 22:56:
btw... .oisyn
leuke signature
maar je hebt zoveel posts en overal zit dezelfde typo in. randum = random
of was dat met opzet :-)


typo? waar? O-)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Edsger
  • Registratie: December 2000
  • Laatst online: 02-08 17:39
Ik heb nog een klein probleempje. Het gaat om deze foutmelding:

Cgtest error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall CGlRenderer::CGlRenderer(void)" (__imp_??0CGlRenderer@@QAE@XZ) referenced in function "public: __thiscall CCgTestApp::CCgTestApp(void)" (??0CCgTestApp@@QAE@XZ)

Ik heb op MSDN en hier op GOT, heel wat afgelezen en geleerd over dll's laden. Maar het bovenstaande lijkt mij in tegenspraak. Het idee achter de __declspec(dllimport) is naar mijn idee dat de compiler (linker) juist niet gaat zoeken naar een file waar de functies geimplementeerd staan toch?

Ik wil dus gebruik maken van de (Afx)LoadLibrary functie in mijn MFC applicatie om deze dan te linken naar mijn Win32 dll (niet MFC) en daarna mijn geexporteerde klasse aan te kunnen roepen in de MFC applicatie. Daarvoor heb ik gewoon de standaard Macro's gebruikt die in VC daarvoor beschikbaar zijn. Vervolgens heb ik de header geinclude in de MFC app. En dan krijg ik de bovenstaande foutmelding. Ik wil dus geen gebruik maken van library's en .def files.

Heb ik het nou verkeerd begrepen? Dit moet toch gaan?

PS: Zou een MFC App misschien niet dynamisch zo kunnen linken naar een win32 dll?

All your quantifications are belong to me!


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 24-08 22:38
Als je met loadlibrary wilt werken moet je voor de functies eerst functiepointer maken die je mbv GetProcAddress laat wijzen naar de functie in je dll.

Op die manier hoef je niet te linken met je dll tijdens het linkproces. ( Runtime dynamic linking )

dllimport en dllexport zijn volgens mij voor Loadtime dynamic linken ( Je linkt je app met de .lib van een dll )

Naar mijn idee is het toch makkelijker om een .def bestand te maken, dat werkt tenminste.

[ Voor 41% gewijzigd door farlane op 18-01-2003 18:24 ]

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • Edsger
  • Registratie: December 2000
  • Laatst online: 02-08 17:39
Ik exporteer geen afzonderlijke functies, maar een hele klasse. Dit werkte bij mij eerder wel, en zo staat het ook in de header van de door VC predefined .h file:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// The following ifdef block is the standard way of creating macros which make exporting 
// from a DLL simpler. All files within this DLL are compiled with the GLRENDERER_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see 
// GLRENDERER_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#ifdef GLRENDERER_EXPORTS
#define GLRENDERER_API __declspec(dllexport)
#else
#define GLRENDERER_API __declspec(dllimport)
#endif

// This class is exported from the glrenderer.dll
class GLRENDERER_API CGlRenderer {
public:
    CGlRenderer(void);
    static void Voorbeeld() {};
};


Hierbij hoef je geen getprocaddress uit te voeren (werkt ook niet). De Macro is er juist voor om aan te geven dat het om een imported functie gaat.

Als ik nu echter in mijn MFC file CGlRenderer::Voorbeeld() aanroep krijg ik de foutmelding van de linker.

All your quantifications are belong to me!


  • .oisyn
  • Registratie: September 2000
  • Nu online

.oisyn

Moderator Devschuur®

Demotivational Speaker

Link je wel met de .lib file die geproduceerd is tijdens het compileren van je dll?

farlane schreef op 18 January 2003 @ 18:16:
Als je met loadlibrary wilt werken moet je voor de functies eerst functiepointer maken die je mbv GetProcAddress laat wijzen naar de functie in je dll.
Dat gaat niet echt met C++ classes ;)
Naar mijn idee is het toch makkelijker om een .def bestand te maken, dat werkt tenminste.


__declspec (dllexport) werkt ook altijd. Het probleem is echter dat bij C++ functies de name gemangled is, waardoor je het niet kunt vinden met GetProcAddress (). Je functies declareren met external C linkage lost dat op (dus extern "C" ...)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Edsger
  • Registratie: December 2000
  • Laatst online: 02-08 17:39
Met de lib linken lukt wel. Het idee was echter om van te voren niet al de dll te "kiezen". Ik wil tijdens runtime gewoon een .dll file kunnen openen, en dan naar die file functie aanroepen te doen. Op het moment dat ik naar een lib file link, dan zoekt het programma tijdens het laden al naar de dll.
Ik hoop dat dit niet omschreven te vaag :? is... :)

All your quantifications are belong to me!


  • .oisyn
  • Registratie: September 2000
  • Nu online

.oisyn

Moderator Devschuur®

Demotivational Speaker

Mja, dat gaat niet zomaar. Je zult de DLL moeten laden met LoadLibrary (), en dan met GetProcAddress () kun je een pointer verkrijgen naar functies of variabelen in die DLL. Alleen dit werkt natuurlijk niet met methoden van classes. Ten eerste wordt hun naam gemangled (JouwKlasse::jouwFunc (int) heet dan iets van jouwFunc__P?ZJouwKlasse@I ofzoiets), en als je dan een pointer naar die functie heb heb je er nog geen reet aan, aangezien je de compiler niet echt wijs kan maken dat dat een methode is die werkt op de klasse JouwKlasse ipv een normale functie.

Daar zijn een aantal oplossingen voor. De eerste is een function-level proxy maken die de juiste methoden aanroept op jouw klasse, gegeven een object

Voor JouwKlasse::jouwFunctie bijvoorbeeld:

C++:
1
2
3
4
void __declspec (dllexport) JouwKlasse_jouwFunctie (JouwKlasse * j, int i)
{
    j->jouwFunctie (i);
}


en deze functie roep je dan aan vanuit jouw host applicatie

Een andere, en misschien mooiere, oplossing is om een klasse te definieren met allemaal virtual functies. De enige functie die je dan hoeft te maken is eentje die een instantie van jouw klasse aanmaakt, en de rest van de functieaanroepen kan gewoon omdat ze virtual zijn, en dus intern via function pointers verlopen

Een andere, misschien wat viezere oplossing, is gebruik te maken van delay loading van DLLs. Een DLL wordt dan niet geladen totdat je een functie aanroept die zich in de DLL bevindt. Als je dat weet kun je er dus voor zorgen dat de juiste dll wordt geladen door 'm bijvoorbeeld te kopieren naar de directory waar je app in staat en 'm dan te renamen naar die dll. Als je een andere wilt kun je m unloaden, die dll verwijderen, en een andere dll kopieren. Maar goed, dit is dus een nogal vieze oplossing ;)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Edsger
  • Registratie: December 2000
  • Laatst online: 02-08 17:39
De eerste oplossing is gewoon flauw he, dat zul je wel met me eens zijn. :)

De tweede oplossing vind ik mooi, het idee achter OO programmeren handhaaft zich dan tenminste. Mijn dank is groot _/-\o_

De derde oplossing is inderdaad SMERIG. Jak... hmm... maar het werk! :P

Btw. is het niet een goed idee om in dit forum in de faq's iets te zetten over programmeren met dll's. Er zijn best veel topics over, maar dat komt omdat je met de vele mogelijkheden al snel door de bomen het bos niet meer kan zien. Als ik zo eens zoek wordt er regelmatig hetzelfde verteld, alleen dan elke keer net wat anders. Zoals in dit topic het geval is dat Klasses om de hoek kwamen kijken. Bovendien wordt het nog eens gerechtvaardigd omdat de documentatie van VS over dit onderwerp nogal her en der verspreid is. :r
Het is maar een idee... O-)

All your quantifications are belong to me!


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 24-08 22:38
Edsger schreef op 20 januari 2003 @ 12:17:
Btw. is het niet een goed idee om in dit forum in de faq's iets te zetten over programmeren met dll's. Er zijn best veel topics over .....
Dan moeten we ook een faq topic over LCD aansturen via paralelle poort maken, die komt veel vaker voor. >:)

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • .oisyn
  • Registratie: September 2000
  • Nu online

.oisyn

Moderator Devschuur®

Demotivational Speaker

BTW, een ding waarover je wel goed moet nadenken is memory management. Je kunt geheugen wat je hebt gealloceerd in je ene module niet zomaar vrijgeven in je andere, omdat ze beide hun eigen heap functies hebben. Ook hier zijn weer meerdere oplossingen voor (;)), met ieder z'n eigen voordelen en nadelen.

De eerste is om gewoon in zowel je executable als je dlls gebruik te maken van een dynamisch gelinkte runtime. Dit zorgt ervoor dat je executable van dezelfde standaard functies gebruik maken als je dll. Dit systeem werkt in principe zonder er iets voor te doen, behalve dan dat je in moet stellen dat ie de dynamisch gelinkte runtime moet gebruiken. Ook verkleint het je executable en dll's, aangezien de functies niet meer in die modules hoeven te staan.
Een nadeel is echter dat als de runtime veranderd is je nieuw gebouwde dll's niet meer compatible zijn met je oudere executable (of andersom). Zo kun je een VS6 executable niet laten samenwerken met een in VS7 gebouwde dll (ja het loopt natuurlijk wel, maar dan krijg je weer dezelfde geheugenproblemen).

Een andere optie is operator new, operator delete, malloc (), realloc () en free () te herdefinieren, en die door te geven aan je executable. Je geeft na het laden van je dll de pointers naar deze functies door (of via een callback object waarbij die functies virtual zijn ;)), zodat ze in de dll gebruikt kunnen worden. Nu zit je niet meer met het verschillende runtime conflict wat je eerder had, en dus kun je je dll's ook bouwen met een compleet andere compiler dan die waarmee je je exe hebt gebouwd.

Ik bedenk me trouwens ook nog een 3e alternatief, die overigens lijkt op de 2e, en ik weet ook niet of dat wel werkt (ga ik zo eens proberen). Je exporteert in je exe al die geheugenfuncties (of wrappers daarnaartoe, das misschien handiger), en je linkt je dll met de geproduceerde lib. In de DLL definieer je ze als declspec (dllimport), zodat ze bij het laden van de dll geimporteerd worden. Maar goed, misschien werkt dit niet eens, effe proberen :P

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
.oisyn schreef op 19 januari 2003 @ 20:20:
Een andere, misschien wat viezere oplossing, is gebruik te maken van delay loading van DLLs. Een DLL wordt dan niet geladen totdat je een functie aanroept die zich in de DLL bevindt. Als je dat weet kun je er dus voor zorgen dat de juiste dll wordt geladen door 'm bijvoorbeeld te kopieren naar de directory waar je app in staat en 'm dan te renamen naar die dll. Als je een andere wilt kun je m unloaden, die dll verwijderen, en een andere dll kopieren. Maar goed, dit is dus een nogal vieze oplossing ;)
Ehm, hoe dit werkt is in de MSDN vrij goed uitgelegd. VC6/7 kan het voor je opzetten. Dat is voornamelijk een handigheidje. Je kunt het ook vanuit andere compilers zelf doen, of anders dan het nu gebeurt. Dat laatste is gelukkig een stuk makkelijker; MSVC heeft hooks daarvoor:

http://www.microsoft.com/...&nav=/msj/1298/newnav.htm

[ Voor 5% gewijzigd door MSalters op 20-01-2003 19:39 . Reden: Toch ietsje moeilijker dan'k dacht. ]

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein

Pagina: 1