Hoe C-functies te structureren in een herbruikbare bibliotheek met hulpprogramma’s

10

Je hebt wat code geschreven. Het werkt. Maar nu wil je die rand() -generator of die bubble_sort -routine in een heel ander project gebruiken. Kopiëren en plakken is lui. Het is ook broos. Wanneer u één versie bijwerkt, moet u elk exemplaar van de code opsporen.

De professionele zet? Bouw een bibliotheek.

In het C-ecosysteem is een bibliotheek geen magische zwarte doos. Het zijn gewoon twee bestanden met verschillende hoeden. Je hebt een headerbestand (.h ) en een bronbestand (.c ) nodig. De header vertelt de rest van de wereld welke functies er bestaan. Het bronbestand doet feitelijk het werk.

De interface bouwen: util.h

Het headerbestand fungeert als contract. Het bevat niet de logica. Het bevat de beloften. Constanten, typen en functieprototypes.

Maak een bestand met de naam util.h.

Die ‘externe’ zoekwoorden doen zwaar werk. Ze zeggen tegen de compiler: “Zoek hier niet naar de implementatie. Ik zal hem later vinden tijdens het linken.” Als je vastzit aan een oudere compiler die ouder is dan de moderne C-standaarden, verwijder dan de parameters uit bubble_sort. Oude compilers zijn zo kieskeurig.

De machines verbergen: util.c

Nu voor de daadwerkelijke code. Sla dit op als util.c.

Let op de include-richtlijn. We gebruiken aanhalingstekens (“util.h”) in plaats van punthaken ( `). Het verschil is belangrijk. Citaten kijken in uw huidige directory. Hoekhaken kijken in systeemmappen. Dit bestand is lokaal. Het hoort hier.

Hier is het subtiele gedeelte: rand_seed. Het bevindt zich in util.c. Het staat niet in util.h. Dit is informatie die zich in actie verbergt. Code die deze bibliotheek gebruikt, kan rand() aanroepen, maar kan de Seed niet rechtstreeks aanraken. De staat is ingekapseld. Voor strikte handhaving kunt u het trefwoord ‘statisch’ vóór de definitie van de variabele plaatsen. Dat houdt het stevig vast. Geen externe toegang. Periode.

De bibliotheek gebruiken: main.c

Schrijf nu het programma dat het gebruikt. Sla dit op als main.c.

Korter? Ja. Schoner? Absoluut. Het maakt het hoofdprogramma niet uit hoe rand() getallen genereert. Er is alleen een nummer nodig. Die scheiding is het hele punt.

Compileren en koppelen

Hoe zet je deze afzonderlijke bestanden om in een actief uitvoerbaar bestand? Je volgt de driestappendans.

Compileer eerst de bibliotheekbron in een objectbestand. Ervan uitgaande dat u op een UNIX-achtig systeem werkt dat GCC gebruikt:

Over de -c -vlag kan hier niet worden onderhandeld. Het vertelt de compiler om te stoppen na het produceren van het objectbestand. Er wordt util.o aangemaakt. Dit bestand bevat machinecode, maar is onvolledig. Het heeft geen ‘hoofd’-functie. Het kan niet op zichzelf draaien. Het is een onderdeel, geen product.

Stel vervolgens uw hoofdprogramma samen:

Dit genereert main.o. Nogmaals, alleen machinecode. Zit nog steeds vast zonder de logica van de bibliotheek.

Koppel ze ten slotte aan elkaar.

Deze opdracht neemt beide objectbestanden en voegt ze samen in één uitvoerbaar bestand met de naam main. Nu heb je een compleet programma. Voer het uit met ./main (of gewoon main als je Windows gebruikt of als je het in je pad hebt).

Het zijn veel stappen voor twee functies. Maar stel je voor dat je dit doet voor een project met vijftig bestanden. Je compileert elk .c -bestand één keer. Je koppelt ze aan elkaar. Een functie in de bibliotheek wijzigen? Compileer alleen dat bestand opnieuw. Opnieuw koppelen. De rest blijft onaangeroerd.

Makefiles automatiseren dit