[C/C++] Automatisch genereren van header-files?*

Pagina: 1
Acties:

  • kasper_vk
  • Registratie: Augustus 2002
  • Laatst online: 08-04-2025
Waarschijnlijk storen veel C/C++ proggers zich regelmatig aan het verschijnsel genaamd header files; waar ik dan op doel is de redundantie die dat met zich mee kan brengen:
  • header file met pre-declarartie van functie, struct, classes e.d.
  • steeds weer #ifndef - constructie om te voorkomen dat je headers dubbel door de compiler gaan en daarmee fouten veroorzaken
Onder meer vanwege (het ontbreken van) die redundatie prog ik liever in Java, maar daar kun je gewoonweg niet altijd hetzelfde (even krachtig) mee bereiken als in C :'( .

Ik loop daarom al een tijdje met de volgende gedachte:
Waarom gebruik/schrijf ik geen programma dat uit mijn C-code de structs, pre-declaraties e.d. zelf in een header-file zet?
Automatische header file generatie dus, voordat de boel door de compiler gaat.

Echter, ik heb nog geen mensen gesproken of topics gevonden waaruit blijkt dat dit gedaan wordt en wat de ervaringen daarmee zijn.

Wat ik graag wil weten:
  • Wat zouden de voors en tegens zijn van het automatisch genereren van header files?
  • Welke complicaties kunnen optreden?
  • welke moeilijkheid zie ik (wellicht) over het hoofd?

The most exciting phrase to hear in science, the one that heralds new discoveries, is not 'Eureka!' but 'That's funny...'


  • Michali
  • Registratie: Juli 2002
  • Laatst online: 22-03 18:12
Is het niet zo dat sommige IDE's d juist de header files gebruiken voor het automatisch listen van de member functies en variabelen? Het ligt er dan natuurlijk aan of je dit gebruikt of niet, maar toch. En headers zijn overigens best fijn om van een class oid snel een overzicht te krijgen van hoe die in elkaar zit en wat de mogelijkheden zijn, zonder de gehele code te hoeven doorspitten.

Noushka's Magnificent Dream | Unity


  • Juup
  • Registratie: Februari 2000
  • Niet online
Ehhh.... gewoon doen. Dan zie je vanzelf of het gaat. Of ben je meer zo'n theoreticus die het eerst helemaal uitgezocht wil hebben?
Ik zou het trouwens wel doen in een taal die regexp's heeft en andere gemakkelijke string functies (Perl, Ruby, Python)

Een wappie is iemand die gevallen is voor de (jarenlange) Russische desinformatiecampagnes.
Wantrouwen en confirmation bias doen de rest.


  • kasper_vk
  • Registratie: Augustus 2002
  • Laatst online: 08-04-2025
Michali schreef op 13 januari 2004 @ 11:06:
Is het niet zo dat sommige IDE's d juist de header files gebruiken voor het automatisch listen van de member functies en variabelen? Het ligt er dan natuurlijk aan of je dit gebruikt of niet, maar toch. En headers zijn overigens best fijn om van een class oid snel een overzicht te krijgen van hoe die in elkaar zit en wat de mogelijkheden zijn, zonder de gehele code te hoeven doorspitten.
Ik gebruik geen type-ahead aavullingen e.d. van de IDE; maar op zich een goed punt, daar ik had bijvoorbeeld niet bij stilgestaan.
Juup schreef op 13 januari 2004 @ 11:06:
Ehhh.... gewoon doen. Dan zie je vanzelf of het gaat. Of ben je meer zo'n theoreticus die het eerst helemaal uitgezocht wil hebben?
Ik zou het trouwens wel doen in een taal die regexp's heeft en andere gemakkelijke string functies (Perl, Ruby, Python)
Nou, ik denk dat het 'even schrijven' van zo'n programma wel eens vies kan tegevallen, dus daarom liever eerst een gezonde discussie / wat theorie erover voordat ik mijn tijd ga verdoen of allerlei zaken over het hoofd zie. Maar mijn intensie is wel om het te gaan maken, wanneer er geen grote bezwaren of onpractische aspecten aanzitten.
Overigens wel jammer dat ik niet bekend met de talen die je suggereert; i.v.m. die regexp's ;( .

The most exciting phrase to hear in science, the one that heralds new discoveries, is not 'Eureka!' but 'That's funny...'


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Jaaap: Ik zou het trouwens wel doen in een taal die regexp's heeft en andere gemakkelijke string functies (Perl, Ruby, Python)
Lijkt me niks. Als je source code moet gaan analyseren moet je niet met reguliere expressies gaan klooien, maar je tools baseren op een context-vrije grammatica van de programmeertaal waarin de source code is geschreven. Programma transformaties of analyses die gebaseerd zijn op reguliere expressies zijn gedoemd om te floppen omdat programmeertalen niet regulier zijn: je kan dus nooit goed een stukje source code interpreteren met reguliere expressies.

Als je zo'n programma transformatie wilt implementeren moet je de source code parsen. Deze parser moet dus gebaseerd zijn op een context-vrije grammatica. Er zijn voor vrijwel alle programmeertalen waarin je het tooltje zou willen implementeren wel parser generators. Zoek maar eens op een parser generator tools voor jouw favoriete taal, waarbij het dan uiteraard wel zo handig is als er al een C grammatica is.

Als je eenmaal een goede representatie van de source code hebt kan je die transformeren naar een header file. Deze header file zal in een vergelijkbare structuur gerepresenteerd worden als de oorspronkelijk source file na het parsen: een abstracte syntax boom. Deze boom moet je nog pretty printen naar text, dus kijk ook naar het bestaan van een pretty printer.

Op de Universiteit Utrecht wordt een vak Programma Transformatie gegeven. Wat jij hier zegt was een aardige beginnersopgave geweest. We gebruiken bij dit vak de Stratego transformatie taal en de Stratego/XT toolset. Als je die toepast (en kent) is dit probleem vrij goed op te lossen: er is al een C grammatica, een pretty printer, en een goede taal om de transformatie in te implementeren.

[ Voor 3% gewijzigd door mbravenboer op 13-01-2004 11:28 ]

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • kasper_vk
  • Registratie: Augustus 2002
  • Laatst online: 08-04-2025
mbravenboer schreef op 13 januari 2004 @ 11:21:
[...]
Lijkt me niks. Als je source... ... met reguliere expressies.

Als je zo'n programma transformatie wilt implementeren moet je de source code parsen. Deze parser moet dus gebaseerd zijn op een context-vrije grammatica. Er zijn voor vrijwel alle programmeertalen waarin je het tooltje zou willen implementeren wel parser generators. Zoek maar eens op een parser generator tools voor jouw favoriete taal, waarbij het dan uiteraard wel zo handig is als er al een C grammatica is.

Als je eenmaal een goede representatie van de source code hebt kan je die transformeren naar een header file. Deze header file zal in een vergelijkbare structuur gerepresenteerd worden als de oorspronkelijk source file na het parsen: een abstracte syntax boom. Deze boom moet je nog pretty printen naar text, dus kijk ook naar het bestaan van een pretty printer.

(handige links, ga ik bekijken, bedankt)
Ik ben op zich bekend met transformaties, daarover heb ik ook een vak gehad in mijn opleiding en ik heb er zelf wel eens mee gespeeld, maar ik ben dus geen 'expert'.

Het lijkt mij dat je niet een volledige Abstract Syntaxt Tree nodig hebt, aangezien je alleen geinteresseerd bent in de functie-headers en structs. Expressies en andere contrcuties die je alleen in de functie definities tegenkomt hoef toch niet geheel te parsen?
--> ik zou dus proberen de functie-headers en structs te parsen (die staan redelijk dicht bij de root van de AST) en alle code die verder bij de root vandaan ligt door het 'tellen' van { en } gewoon overslaan.

The most exciting phrase to hear in science, the one that heralds new discoveries, is not 'Eureka!' but 'That's funny...'


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
kasper_vk: Het lijkt mij dat je niet een volledige Abstract Syntaxt Tree nodig hebt, aangezien je alleen geinteresseerd bent in de functie-headers en structs. Expressies en andere contrcuties die je alleen in de functie definities tegenkomt hoef toch niet geheel te parsen?
Idd, dat is wel een goed punt. Toch maakt het niet zo veel uit als ze wel geparsed worden als er toch al een grammatica hebt. Als er nog geen grammatica is, is het een goed idee om voor deze toepassing een zogenaamde island grammar te maken: zo'n grammatica definieert alleen de globale structuur van een source file en negeert andere onderdelen die niet relevant zijn.

Aangezien C/C++ al lang bestaat en veel gebruikt wordt, zijn er genoeg grammaticas en tools beschikbaar om meta programmas voor C/C++ te schrijven. Het is dus zonde van je tijd om een eigen grammatica of parser te gaan schrijven. Het zal alleen maar voor meer werk en meer bugs/beperkingen zorgen.

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

En waar wou je de documentie gaan plaatsen? Je moet dit doen in je c++ bestanden aangezien je headerfiles gegenereerd worden. Je gaat dan een beetje de java kant op waardoor je weer zulke lappers krijgt (tenzij je een IDE hebt die kan codefolden). En het up to date houden van die headerfiles gaat denk ik lastig worden als je ook in die headerfiles mag editen (ipv dat het een 'dom' bij product is)

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Alarmnummer: En het up to date houden van die headerfiles gaat denk ik lastig worden als je ook in die headerfiles mag editen (ipv dat het een 'dom' bij product is)
Je zou in de generator een overriding of weaving mechanisme kunnen implementeren die een bestaande header file samenvoegd met de gegenereerde source file. Deze techniek gebruik ik ook in een Java code generator, maar daar heb ik al weleens over verteld ;) .

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

mbravenboer schreef op 13 januari 2004 @ 11:52:
[...]
Je zou in de generator een overriding of weaving mechanisme kunnen implementeren die een bestaande header file samenvoegd met de gegenereerde source file.
Het lijkt me een vrij lastige klus. Je zit sowieso met allerlei consistentie problemen. Stel dat je een functie in je c++ bestand hebt gerenamed. Wat moet er dan gebeuren bij de headerfile? Hoe weet de generator dat er sprake is van een gerenamde functie ipv een nieuwe? Ik kan zo wel een tijdje doorgaan met allerlei onduidelijkheden. Het lijkt me erg lastig om dat goed voor elkaar te krijgen.

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Alarmnummer: Het lijkt me erg lastig om dat goed voor elkaar te krijgen.
Idd, maar die problemen spelen altijd bij het implementeren van software, dus moet je ze niet als tegenargumenten aanvoeren ;) . Als je een methodenaam aanpast in een Java klasse, moet je ook zorgen dat je die alle toepassingen van methode aanpast. Bij de generator speelt hetzelfde: als je een functie aanpast in je C file, moet je je header in je header file ook aanpassen om die nog op elkaar betrekking te laten hebben. Ook kan je in de merger natuurlijk checks implementeren of functies wel daadwerkelijk voorkomen in de implementatie, waardoor je hetzelfde effect krijgt als een compiler die waarschuwt voor een niet bestaande methode.

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • kasper_vk
  • Registratie: Augustus 2002
  • Laatst online: 08-04-2025
mbravenboer schreef op 13 januari 2004 @ 11:49:
[...]
Aangezien C/C++ al lang bestaat en veel gebruikt wordt, zijn er genoeg grammaticas en tools beschikbaar om meta programmas voor C/C++ te schrijven. Het is dus zonde van je tijd om een eigen grammatica of parser te gaan schrijven. Het zal alleen maar voor meer werk en meer bugs/beperkingen zorgen.
Klinkt uitermate verstandig; ga ik naar zoeken. Het wiel tweemaal uitvinden is (meestal) zonde, tenzij het een revolutionair nieuw design is van dat oude, vertrouwde wiel :7 ... kleine kans hier dus O-) .
Alarmnummer schreef op 13 januari 2004 @ 11:49:
En waar wou je de documentie gaan plaatsen? Je moet dit doen in je c++ bestanden aangezien je headerfiles gegenereerd worden. Je gaat dan een beetje de java kant op waardoor je weer zulke lappers krijgt (tenzij je een IDE hebt die kan codefolden).En het up to date houden van die headerfiles gaat denk ik lastig worden als je ook in die headerfiles mag editen (ipv dat het een 'dom' bij product is)
Documentatie: idd een goed punt en ik wil niet uitgaan van slimme / handige IDE's, aangezien ik die zelf ook niet altijd gebruik.
Wanner de header files alleen aangevuld/ gecorrigeerd zouden worden tijdens de automatische generatie, is het een optie om het commentaar te kopieren / verplaatsen naar de header file tijdens het maken / bijwerken van de headers.

Het leek mij alleen niet de bedoeling om de header files aan te mogen passen; althans in eerste instantie niet om het eenvoudig te houden. Dus de documentatie is inderdaad een onpractisch aspect aan het idee.

The most exciting phrase to hear in science, the one that heralds new discoveries, is not 'Eureka!' but 'That's funny...'


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

mbravenboer schreef op 13 januari 2004 @ 12:02:
[...]
Idd, maar die problemen spelen altijd bij het implementeren van software, dus moet je ze niet als tegenargumenten aanvoeren ;) .
De pragmaticus in me vraagt zich altijd meteen af wat er allemaal mis kan gaan. Een idee is meestal maar een fractie van de oplossing.
Als je een methodenaam aanpast in een Java klasse, moet je ook zorgen dat je die alle toepassingen van methode aanpast.
Ide`s die refactoring ondersteunen weten wat er gebeurt, een rename of een nieuwe functie. Deze kennis gaat verloren als je het met de hand gaat doen en daarna nieuwe headers gaat genereren.

[ Voor 3% gewijzigd door Alarmnummer op 13-01-2004 12:10 ]


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 22-05 16:53
Hmmm, normaal gesproken ga je eerst nadenken over de interface van je unit ( Dus de inhoud van je header file ) en daarna pas over de implementatie.

Je wil dus eigenlijk een skeleton cpp bestand genereren lijkt me.

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.


  • kasper_vk
  • Registratie: Augustus 2002
  • Laatst online: 08-04-2025
Farlane, op zich is dat de nette manier van werken, maar in de praktijk kom ik toch vaak tegen dat ik toch extra functies toevoeg tijdens het implementeren van andere; b.v. om de boel verder op te delen (decompositie).
Natuurlijk heb je, vindt ik, wel een goed punt, maar de praktijk is (bij mij iig) vaak anders.

Overigens heb ik nog niet bedacht hoe om te gaan met eigen header files.

Op zich dacht ik overigens aan het genereren van header-files en het reproduceren van de cpp files, aangevuld met de bijbehorende include(s).
Dus iets als:
CPP + H(eigen headers) --> CPP(aangevuld met includes) + H(eigen headers) + H(pre-declaraties)

De doel-bestanden gaan door de compiler, de oorspronkelijke niet.

The most exciting phrase to hear in science, the one that heralds new discoveries, is not 'Eureka!' but 'That's funny...'


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12:16

.oisyn

Moderator Devschuur®

Demotivational Speaker

kasper_vk schreef op 13 januari 2004 @ 11:00:
Waarschijnlijk storen veel C/C++ proggers zich regelmatig aan het verschijnsel genaamd header files; waar ik dan op doel is de redundantie die dat met zich mee kan brengen:
mwoa, niet echt eigenlijk :)
• steeds weer #ifndef - constructie om te voorkomen dat je headers dubbel door de compiler gaan en daarmee fouten veroorzaken
Mja, daar heb ik een IDE voor. Ctrl-shift-h en ik heb header guards in een file :) Is trouwens een macro die ik gemaakt heb voor visual studio .net. Ik weet niet of je die ook gebruikt, maar misschien wil je 'm dan wel hebben
Onder meer vanwege (het ontbreken van) die redundatie prog ik liever in Java, maar daar kun je gewoonweg niet altijd hetzelfde (even krachtig) mee bereiken als in C :'( .
Alarmnummer gaf het ook al een beetje aan; ik ken een aantal java'ers die het juist een minpunt vinden dat java geen headers heeft, omdat je dan niet duidelijk kunt zien hoe het skelet van een bepaalde class eruit ziet. Er is voor beide methoden dus wel wat te zeggen
Ik loop daarom al een tijdje met de volgende gedachte:
Waarom gebruik/schrijf ik geen programma dat uit mijn C-code de structs, pre-declaraties e.d. zelf in een header-file zet?
Automatische header file generatie dus, voordat de boel door de compiler gaat.
ook al gezegd, maar ook ik vind het een beetje omgekeerde wereld. Meestal wil je juist cpp files genereren uit header files, zodat je alleen nog maar de code in hoeft te tikken. Een handiger systeem lijkt me dan dat als je een methode aanpast, dat ie ook de header aanpast.

Denk er trouwens aan dat een header niet per se gekoppeld zit aan een cpp. Een header bevat alleen klasse-definities en functie- en variabele-declaraties. In welke cpp of lib file ze uiteindelijk geïmplementeerd worden zal de compiler een worst wezen. De linker gaat alleen piepen als ze uiteindelijk niet bestaan als ze gebruikt worden :)

[q]• Wat zouden de voors en tegens zijn van het automatisch genereren van header files?

tegen:
[list]• Aparte compilatie-stap in een imho toch al traag systeem
• Extra dependencies door deze extra stap (je verandert de code in een functie -> source file verandert -> header moet opnieuw worden gecompileerd -> alle source files die deze header includen moeten ook opnieuw worden gecompileerd, en dat terwijl er aan de klassedefinitie niets aan verandert hoeft te zijn)
• Het verschijnen van een functie of variabele in een header die ik daar eigenlijk helemaal niet had willen hebben

de voordelen gaf je zelf al, maar zoals je hierboven kunt lezen ben ik het op sommige punten niet helemaal met je eens :)

[q]• Welke complicaties kunnen optreden?
Het verschijnen van een functie of variabele in een header die ik daar eigenlijk helemaal niet had willen hebben ;)

En wat doe je met classes die niet volledig zijn geimplementeerd in die cpp file? Misschien is een bepaalde functie wel ergens anders gedefinieerd, verschijnt ie dan ineens niet in de klassedefinitie? En pure virtual functies? Die staan ook niet in een cpp file
• welke moeilijkheid zie ik (wellicht) over het hoofd?
zie boven :)

[ Voor 8% gewijzigd door .oisyn op 13-01-2004 15:31 ]

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.


  • kasper_vk
  • Registratie: Augustus 2002
  • Laatst online: 08-04-2025
Alles samenvattend kom ik totnutoe tot de conclusie dat een dergelijke generatie van header-files niet per sé genakkelijker is. Ik denk dat ik danook geen tijd ga steken om een dergelijk tool te zoeken of te maken, omdat het inderdaad veel complicaties met zich mee brengt:
  • headers voor lib's / waarvan ik zelf geen implementatie schrijf
  • extra compilatiestap, dus trager
  • waar laat je je commentaar
  • up-to-date houden van gegenereerde files is complex
  • een 'slimme' IDE lost de meeste ongemakken waarschijnlijk op
Terug naar mijn oorspronkelijke 'probleem', heeft .oisyn een oplossing aangedragen voor het steeds weer #ifndef-en om headers slechts eenmaal te includen.
Maar het dubbel opnemen van een functie-header (pre-declare en bij de definitie zelf) blijft me ergeren, want dat betekend altijd dubbel onderhoud. Het moeten pre-declaren van structs / classes als zij naar elkaar kunnen verwijzen is net zoiets, en ik had gehoopt dat tamelijk eenvoudig te kunnen oplossen.

Jammer, maar het is overduidelijk niet zo eenvoudig op te lossen als ik hoopte.
Thanx allen _/-\o_

The most exciting phrase to hear in science, the one that heralds new discoveries, is not 'Eureka!' but 'That's funny...'


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Ik wilde ook nog even een opmerking maken. Elementen zoals private, protected, public, static en virtual kun je ook niet uit de cpp file halen, dus moet je met de hand de gegenereerde header corrigeren.

Verwijderd

OlafvdSpek schreef op 14 januari 2004 @ 17:31:
Ik wilde ook nog even een opmerking maken. Elementen zoals private, protected, public, static en virtual kun je ook niet uit de cpp file halen, dus moet je met de hand de gegenereerde header corrigeren.
Dat zou je dan kunnen vermijden door een eigen soort preprocessor aan te maken in die header generator.
Zoiets als:
code:
1
2
3
4
5
6
7
8
9
10
11
#functiontype private
void whatever()
{
   // ...
}

#classtype private
void c::member()
{
  // ...
}

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12:16

.oisyn

Moderator Devschuur®

Demotivational Speaker

Hoe ga je je sourcefiles dan compilen? Ik zou het dan met een bepaalde comment-style doen

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.


Verwijderd

Ik weet niet hoor maar header files maken kost mij de minste tijd. Heb liever een proggie die de functies voor mij maakt... maja dan hoef ik niet meer te proggen 8)7

En als ik dan bij elke functie moet zetten of ie public/protected etc is dan kan ik dus net zo goed even de functie naam copy pasten naar de header file. Is toch zo gedaan ?

Zie het probleem niet zo.

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Daar ben ik het mee eens. Soms is het handig om automatisch functie prototypes aan te passen, maar met copy/paste is dat ook zo gedaan.
En als je ook code in de header zet wordt zo'n tool nog minder handig.
Pagina: 1