Meny
Är gratis
registrering
Hem  /  Internet/ Illustrerad handledning på Macromedia Flash MX. Flash soname delade bibliotek

Illustrerad handledning om Macromedia Flash MX. Flash soname delade bibliotek

Tidigare nämnde vi delade bibliotek som en av fördelarna med personsöknings- och segmentminneshanterare framför bas- och bankchefer. Vid grundläggande adressering måste bilden av varje process uppta sammanhängande områden i både det fysiska och logiska adressutrymmet. Under dessa förhållanden är det omöjligt att implementera det delade biblioteket. Men även när man använder sidadressering är det inte så enkelt.

Användningen av delade bibliotek och/eller DLL:er (i det här fallet är skillnaden mellan dem inte grundläggande) förutsätter någon form av montering vid tidpunkten för inläsning: den körbara modulen har olösta adressreferenser och namnen på de bibliotek den behöver. När de laddas laddas dessa bibliotek och länkar löses. Problemet här är att när ett bibliotek laddas måste det flyttas genom att konfigurera om absoluta adressreferenser i dess kod och data (se kapitel 3). Om biblioteket är konfigurerat till olika adresser i olika processer kommer det inte längre att delas (Fig. 5.14)! Om delade bibliotek kan ha olösta länkar till andra bibliotek, förvärras problemet bara genom att lägga till externa länkar till de flyttbara länkarna.

Ris. 5.14... Motstridiga DLL-mappningsadresser

På äldre Unix-system som använde absolut laddningsbara moduler av formatet a.ut Delade bibliotek skickades också i absolut modulformat, inställda på fasta adresser. Varje bibliotek har ställts in på ITS-adress. Leverantören av de nya biblioteken var tvungen att komma överens om denna adress med systemutvecklarna. Detta var väldigt opraktiskt, så det fanns väldigt få delade bibliotek (särskilt förutom de som följde med operativsystemet).

En mer acceptabel lösning på detta problem implementeras i OS / 2 2.x och Win32 (båda dessa arkitekturer är utveckling av system med ett enda adressutrymme). Tanken är att tilldela ett adressområde för att ladda DLL:er och mappa detta område till adressutrymmena för alla processer. Således är alla DLL:er som laddas på systemet synliga för alla (Fig. 5.15).

Stora program kräver ofta färdiga bibliotek. Ett bibliotek är en samling av redan kompilerade funktioner (till exempel ett matematikbibliotek). Biblioteket efterfrågas vid länkning när exe-shnik genereras. Detta görs med alternativet -l: cc -o badmath badmath.o -lm Om du behöver ange sökvägen till ett icke-standardiserat bibliotek: cc -o badmath badmath.o -lm -L / usr / skräp / lib -lcrud Om biblioteksnamnet slutar på .a är det ett statiskt bibliotek. När ett statiskt bibliotek är länkat, kopierar länken helt enkelt hela bitar från den till den genererade exe-filen, som, som ett resultat, kan arbeta autonomt utan den. Om exe-shnik använder ett delat bibliotek, laddas koden endast efter behov. Bibliotek finns vanligtvis i katalogerna / lib och / usr / lib. Det bör inte finnas några statiska bibliotek i katalogen / lib. Namnet på det delade biblioteket inkluderar prefixet .so. För att avgöra vilka bibliotek programmet använder, måste du köra kommandot: ldd prog ld.so-lastaren laddar de delade biblioteken. Vägen till biblioteket kan ligga inuti exe-shnik. Om den inte finns där, tittar laddaren på filen /etc/ld.so.cache, som listar katalogerna. Det finns också en /etc/ld.so.conf-fil. Om du manuellt lade till sökvägen till filen /etc/ld.so.cache, måste du köra kommandot: ldconfig -v Det finns också systemvariabeln LD_LIBRARY_PATH. Det är ingen bra idé att lägga till sökvägar till filen /etc/ld.so.conf. Stora bibliotek går in i systemcachen och du kan få problem. Det bästa sättet är att sy sökvägen till biblioteket i exe-shnik: cc -o myprog myprog.o -Wl, -rpath = / opt / obscure / lib -L / opt / obscure / lib -lweird Med tillväxten av delade bibliotek är problem med dem möjliga på grund av överlappning etc. Att använda LD_LIBRARY_PATH är också problematiskt. Ett skript kan användas istället: LD_LIBRARY_PATH = / opt / crummy / lib export LD_LIBRARY_PATH exec / opt / crummy / bin / my_prog [e-postskyddad] Det huvudsakliga kompileringsverktyget i Unix är make. Den mest detaljerade beskrivningen ges i UNIX-programmeringsmiljön eller in Hantera projekt med make... Make har alltid ett mål - mål - som kan vara antingen en fil eller en etikett. Målet kan vara primärt och sekundärt. För att bygga ett mål, leta efter regler. Till exempel: OBJS = aux.o main.o # objektfiler alla: myprog myprog: $ (OBJS) $ (CC) -o myprog $ (OBJS) Det första målet - allt - är det huvudsakliga som standard. Regeln för det är myprog, som kan vara en annan regel, ett annat mål eller en fil. OBJS är ett makro för att bygga ett mål. Denna makefil kommer att producera följande utdata: cc -c -o aux.o aux.c cc -c -o main.o main.c cc -o myprog aux.o main.o make kan köras i kombination med kommandoalternativ, till exempel: make aux.o Gör alternativ: -n -f Ofta använda makron: CFLAGS - kompilatoralternativ LDFLAGS - länkalternativ make har flera standardmål: ren distclean installera test depend Makefile startar vanligtvis med antingen och inkluderar till exempel: X_INCLUDES = -I / usr / X11R6 / include X_LIB = -L / usr / X11R6 / lib -lX11 -Xt NG_INCLUDES = -I / usr / local / include PNG_LIB = -L / usr / local / lib -lpng Nästa är alternativen för kompilatorn och länken CFLAGS = $ (CFLAGS) $ (X_INCLUDES) $ (PNG_INCLUDES) LDFLAGS = $ (LDFLAGS) $ (X_LIB) $ (PNG_LIB) Då kan källkoden listas: UTIL_OBJS = util.o BORING_OBJS = $ (UTIL_OBJS) tråkigt.o TRITE_OBJS = $ (UTIL_OBJS) banalt.o PROGS = tråkigt banalt Och först nu finns det mål och regler: alla: $ (PROGS) tråkiga: $ (BORING_OBJS) $ (CC) -o [e-postskyddad]$ (BORING_OBJS) $ (LDFLAGS) banalt: $ (TRITE_OBJS) $ (CC) -o [e-postskyddad]$ (TRITE_OBJS) $ (LDFLAGS) Delade bibliotek är en grundläggande komponent i Unix-systemet. Standard C-biblioteket till exempel på Suse 9.1 är 1,3 MB stort. En kopia av detta bibliotek för alla program som använder det i / usr / bin kommer att ta mer än en gigabyte. Sådana bibliotek kräver inte bara diskutrymme utan också minne. Kärnan är utformad för att behålla en kopia av det delade biblioteket i minnet. Man bör komma ihåg att vid statisk länkning läggs bibliotekskoden statiskt till den körbara filkoden, och när du kör den behöver vi inte biblioteket - dess kod är redan länkad under kompileringen till kroppen av den körbara filen. Med dynamisk länkning länkas det delade biblioteket under körning.
Dynamisk länkning är den dominerande typen av länkande bibliotek. Bara standardbiblioteket består av över tusen systemsamtal. För riktigt fungerande program, den sk. Procedure Linkage Table (PLT) är en tabell som består av anrop till funktioner som anropas från delade bibliotek. Det första problemet som kan uppstå med detta är ett kompatibilitetsproblem. Med statisk kompilering löses detta problem vid kompilering. Med dynamisk länkning finns det ingen sådan garanti, eftersom vi kan uppdatera det delade biblioteket efter kompilering. I det här fallet är kontrollen versionsnumret - när den dynamiska länken försöker länka biblioteket kontrollerar den versionsnumret, och om numret inte stämmer överens är det inte länkat. Versionsnumret består av 2 delar - det stora (stora) numret och det sekundära (molltalet). Om huvudnumret är detsamma, bör det som regel inte vara några problem när du laddar biblioteket. Om vi ​​har biblioteket libexample.so kommer det att ha en länk till versionen libexample.so.N där N är det stora versionsnumret, från vilket det i sin tur kommer att finnas en länk till libexample.so.NM där M är det stora sekundära versionsnumret. I det här fallet kommer programmet att söka efter exakt den version N som det behöver.
I statiska bibliotek finns koden i filer med tillägget .a. För dynamiska bibliotek har filerna filtillägget .so. Det statiska biblioteksformatet genereras med hjälp av ar-verktyget, och formatet liknar det som tar-verktyget genererar. För dynamiska bibliotek på de senaste Linux-versionerna är detta format vanligtvis ELF-binärt. Den består av en rubrik och segment, som är indelade i sektioner. Vid länkning läggs kod från statiska bibliotek direkt till programmets körbara fil, och länkar från dynamiska bibliotek tas och läggs till PLT. När det är laddat, laddar programmet en dynamisk länk som laddar de nödvändiga biblioteken. När du dynamiskt länkar ett program kan du lägga till sökvägar för att söka efter bibliotek vid kompilering. För gcc ser denna syntax ut som -Wl, -R / path Om programmet redan är länkat kan du använda variabeln LD_LIBRARY_PATH. Du kan också köra ett speciellt wrapper-skript innan du startar programmet som specifikt konfigurerar bibliotekskatalogerna, vilket görs. , till exempel när du startar Mozilla. Den dynamiska länken får åtkomst till /etc/ld.so.conf-konfigurationen, som inkluderar en kataloglista. Men först kommer länken åt LD_LIBRARY_PATH. ldd (lista dynamiska beroenden)- Verktyg för felsökning av delade bibliotek. Den listar de delade biblioteken för en given modul, till exempel: ldd / bin / sh linux-gate.so.1 => (0xffffe000) libreadline.so.4 => /lib/libreadline.so.4 (0x40036000) libhistory.so.4 => /lib/libhistory.so.4 (0x40062000) libncurses.so.5 => /lib/libncurses.so.5 (0x40069000) libdl.so.2 => /lib/libdl.so.2 (0x400af000) libc.so.6 => / lib / tls /libc.so.6 (0x400b2000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
  • För nybörjare: Linux Journal-artikel "Linkers and Loaders" av Sandeep Grover
  • Boken "Linkers and Loaders" manuskript online.
  • Rekommenderad även 2002 av Ulrich Drepper med titeln "Hur man skriver delade bibliotek" (pdf). Bilder (pdf) och ett manus som nämns i bilderna

Bygga ett delat bibliotek

Låt oss skriva ett litet bibliotek som gör ingenting, nästan ingenting, förutom "hej världen". Första objektet:

/ * print1.c * / #inkludera void print1 (void) (printf ("1 \ n");)

På samma sätt, det andra objektet:

/ * print2.c * / #inkludera void print2 (void) (printf ("2 \ n");)

Låt oss kompilera:

gcc -Wall -g -c -fpic print1.c gcc -Wall -g -c -fpic print2.c

Skapa ett delat bibliotek:

gcc -shared -Wlsoname = libprint.so.1 -g \ -o libprint.so.1.0.1 print1.o print2.o

Vi gör en länk till biblioteket:

ln -sf libprint.so.1.0.1 libprint.so

För att andra ska kunna använda det här biblioteket måste du skriva en rubrik:

/ * print.h * / #ifndef PRINT_H #define PRINT_H void print1 (void); void print2 (void); #endif

Låt oss skriva ett testprogram:

/ * print.c * / #include "print.h" int main () (print1 (); print2 (); return 0;)

Låt oss kompilera det:

gcc -Vägg -g -L. -lprint -o print print.c

För att köra programmet måste länken berätta var biblioteket finns:

Överbelastningsfunktioner

Innan vi laddar ett bibliotek kan vi alltid tala om för laddaren var den ska börja söka och ladda det.

Låt oss lägga till en ny funktion till biblioteket vi just skrev. Denna funktion heter fopen.

/ * fopen.c * / #inkludera FIL * fopen (const char * fn, const char * läge) (printf ("fopen kallas \ n"); returnera NULL;)

Låt oss kompilera den här funktionen och lägga den i biblioteket:

gcc -Wall -g -c -fpic fopen.c gcc -shared -Wlsoname = libprint.so.1 -g \ -o libprint.so.1.0.2 print1.o print2.o fopen.o ln -sf libprint.so .1.0.2 libprint.so

Låt oss skriva ett program för att testa:

/ * print-2.c * / #include int main () (FILE * f; f = fopen ("abc", "r"); if (f == NULL) (printf ("1");) else (printf ("2"); fclose (f);) return 0;)

Låt oss kompilera detta program:

gcc -Wall -g -o print print.c

Vi måste starta den med följande prefix:

LD_PRELOAD =. / Libprint.so ./print

Om något görs fel kommer raden att visas: fopen anropad

Processen att skapa ett program.

Översättning till ryska: Vladimir Popov

Idag, i en miljö som ständigt utvecklas, är mjukvaruutvecklingsprocessen en produkt av utvecklingen av kompetens och erfarenhet som utvecklats av programmerare och utvecklare.

Denna process består av följande steg:

    Generera källkod på hög nivå i en textredigerare. Om vi ​​försöker passa in ett mycket stort program i en fil blir det svårt att hantera. Av denna anledning delas källkoden upp i funktionsmoduler som skapas från en eller flera källkodsfiler. Källkoden i dessa moduler behöver inte nödvändigtvis vara skriven på samma språk, eftersom vissa språk är bättre lämpade för att lösa ett specifikt problem än andra.

    Efter att filerna med programmets källkod har skapats måste de översättas till kodblock som kan exekveras av maskinen. Denna kod brukar kallas objektkod... Denna kod utför samma åtgärder som den ursprungliga koden, förutom att den är skriven på ett speciellt språk som kan köras direkt av maskinen. Processen att översätta källkod till objektkod kallas kompilering... Kompileringen görs i delar och kompilerar (beroende på kompilatorn) del av programmet och vanligtvis en eller flera filer på en gång. Den kompilerade objektkoden innehåller ett program, subrutin, variabler etc. - de delar av programmen som har översatts och är redo för nästa steg.

    Efter att alla programfiler med maskinkod har skapats måste de anslutas eller länkas med en operation som utförs av ett speciellt verktyg som heter länk... I detta skede "löses" alla referenser som modulens kod gör till kod som tillhör en annan modul (såsom anrop av en subrutin eller referenser till variabler som ägs eller definieras i en annan modul). Den resulterande produkten är ett program som kan laddas och köras direkt.

    Exekveringen av ett program utförs av en speciell typ av programvara, som är en väsentlig del av operativsystemet, i fallet med Linux är det exec () systemanropet. Den här funktionen hittar filen, allokerar minne till processen, laddar vissa delar av filens innehåll (som innehåller kod och initiala variabelvärden) och överför kontrollen till processorn vid "text"-punkten i programmet, vilket vanligtvis pekar på den körbara filen sig.

2.- Kort historik över processen att skapa programmet.

Processen att skapa ett program utvecklas ständigt, det är nödvändigt att uppnå den mest effektiva exekveringen av program eller den bästa användningen av systemresurser.

I början skrevs program direkt i maskinkod. Senare blev det klart att det var möjligt att skriva program på ett språk på högre nivå, eftersom den efterföljande översättningen till maskinkod kunde automatiseras på grund av översättningens systematiska karaktär. Detta ökade programmens prestanda.

Efter att ha lärt mig hur man kompilerar program (jag förenklade utvecklingen av kompilering, i själva verket var det ett mycket svårt steg, eftersom det är en mycket komplex process), började processen att skapa program att bestå av att skapa en fil med källkoden för program, kompilera det och slutligen köra det.

Det märktes snart att kompileringsprocessen är mycket mödosam och tar mycket resurser, inklusive maskintid, och att många av funktionerna som ingår i dessa program användes om och om igen i olika program. Dessutom, när någon ändrade en del av programmet, innebar kompileringen av den infogade koden att kompilera hela källkoden igen, inklusive en ny översättning av all oförändrad kod.

Av denna anledning började modulär kompilering användas. Dess innebörd var att dela upp programmet i å ena sidan huvudprogrammet och å andra sidan de funktioner som ofta användes om och om igen och som redan hade kompilerats och lagrats på en speciell plats (vi kommer att kalla detta är föregångaren till biblioteket).

Sedan blev det möjligt att utveckla program som stödjer dessa funktioner utan att lägga extra kraft på att koda dem om och om igen. Redan då var processen komplicerad på grund av det faktum att när man länkade program var det nödvändigt att kombinera alla delar och de måste vara kända för programmeraren (detta införde extra kostnader för att kontrollera möjligheten att använda en känd funktion som använder / kräver andra okända funktioner).

3.- Vad är ett bibliotek?

Problemet som beskrivs ovan ledde till skapandet av bibliotek. Detta är inget annat än en speciell typ av fil (för att vara exakt, ett arkiv, tar (1) eller cpio (1)) med speciella parametrar, vars format länkaren förstår, och när vi pekar den till ett biblioteksarkiv, LÄNKARE VÄLJER ENDAST DE MODULER SOM BEHÖVS PROGRAM och utesluter allt annat. En ny fördel har dykt upp. Nu var det möjligt att utveckla program som använder stora bibliotek av funktioner, och programmeraren behövde inte känna till alla beroenden av funktionerna i det biblioteket.

De bibliotek som vi har diskuterat hittills har inte kommit längre i utvecklingen. De har precis lagt till en fil, som ofta finns i början av arkivet, som innehåller modulbeskrivningar och identifierare som länken måste lösa utan att läsa hela biblioteket (och därmed eliminera behovet av att läsa biblioteket flera gånger). Denna process (att lägga till symboltabellen i biblioteksarkivet) i Linux utförs av kommandot ranlib (1). De bibliotek som hittills beskrivits är kända som STATIC LIBRARIES.

Framsteg skedde efter att det första multitasking-systemet dök upp: dela kod... Om två kopior av samma kod kördes på samma system skulle det vara önskvärt att båda processerna kunde dela samma kod, eftersom ett program vanligtvis inte modifierar sin egen kod. Denna idé eliminerar behovet av att allokera flera kopior i minnet, vilket frigör mycket minne på enorma fleranvändarsystem.

För att ta denna sista innovation ett steg längre, trodde någon (jag vet inte vem det var, men idén var jättebra ;-) att väldigt ofta använder många program samma bibliotek, men eftersom det är olika program, använder delar av biblioteken biblioteken. var inte nödvändigtvis samma delar som användes av ett annat program. Dessutom var huvudkoden annorlunda (de är olika program), så deras texter delades inte. Nåväl, vår hjälte trodde att om olika program som använder samma bibliotek kunde dela det här biblioteket sinsemellan, så kunde vi få lite minne. Nu fungerar olika program, med olika text, med samma bibliotekskod.

Men nu har processen blivit mer komplicerad. Det körbara programmet är inte helt länkat, men upplösningen av biskjuts upp tills programmet har laddats. Länkaren (ld (1) i fallet med Linux) känner igen delade biblioteksanrop och inkluderar inte deras kod i programmet. Systemet självt, kärnan, när exec () körs känner igen lanseringen av ett program som använder delade bibliotek och exekverar speciell kod som laddar delade bibliotek (allokerar delat minne för deras text, allokerar privat minne för biblioteksvärden, etc.). Nu utförs denna process när den körbara filen laddas och hela proceduren har blivit mycket mer komplicerad.

När länken möter ett vanligt bibliotek fortsätter den naturligtvis att bete sig som tidigare.

Ett delat bibliotek är inte ett arkiv som innehåller objektkoden, det är snarare en fil som innehåller själva objektkoden. När ett program kopplas till ett delat bibliotek undersöker länkaren inte biblioteket, vilka moduler som ska läggas till i programmet och vilka som inte ska. Den ser bara till att olösta länkar löses och bestämmer vad som ska läggas till i listan när biblioteket ingår. Det är möjligt att skapa ett arkiv ar (1) bibliotek för alla delade bibliotek, men detta görs ofta inte, eftersom delade bibliotek ofta är resultatet av att länka olika moduler, så biblioteket kommer att behövas senare, vid körning. Kanske är namnet delat bibliotek inte det mest lämpliga och det skulle vara mer korrekt att kalla det ett delat objekt (dock eftersom vi kanske inte förstås använder vi inte denna term).

4.- Typer av bibliotek.

Som vi sa, det finns två typer av bibliotek i Linux: statiska och delade. Statiska bibliotek är en samling moduler som kombineras till ett arkiv med hjälp av verktyget ar (1) och indexeras med verktyget ranlib (1). Dessa moduler lagras ofta i en fil som slutar med .a (jag använder inte termen förlängning eftersom Linux inte använder konceptet filtillägg). Länkaren känner igen slutet av .a-filen och börjar leta efter moduler som om det vore ett statiskt bibliotek, och väljer och lägger till de moduler som löser olösta referenser till programmet.

Till skillnad från statiska bibliotek är delade bibliotek inte arkiv, utan flyttbara objekt, utpekade med speciell kod (som betecknar dem som delade bibliotek). Länkaren ld (1) lägger, som redan nämnts, inte till moduler till programkoden, utan väljer de identifierare som tillhandahålls av biblioteket som tillåtna, lägger till de som krävs av själva biblioteket och fortsätter att arbeta utan att lägga till någon kod, förutsatt att att den nödvändiga koden redan har lagts till i huvudkoden. Länkaren ld (1) känner igen delade bibliotek genom att sluta med .so (inte .so.xxx.yyy, vi kommer att diskutera detta senare).

5.- Länkningsprocessen i Linux.

Varje program består av objektmoduler länkade till en körbar fil. Detta görs av länken ld (1) som används i Linux.

ld (1) stöder olika alternativ som ändrar dess beteende, men vi kommer att begränsa oss här till endast de som är relaterade till användningen av bibliotek i allmänhet. ld (1) anropas inte direkt av användaren, utan av gcc (1) kompilatorn själv i sitt slutskede. Lite kunskap om honom modus operandis hjälp oss att förstå hur vi använder bibliotek i Linux.

För att ld (1) ska fungera korrekt behöver den en lista med objekt som ska länkas till programmet. Dessa objekt kan specificeras i valfri ordning (*) så länge vi följer ovanstående konvention, som redan nämnts känns det delade biblioteket igen av ändelsen .so (inte .so.xx.yy) och det statiska biblioteket av .a (och naturligtvis är enkla objektfiler de vars namn slutar på .o).

(*) Detta är inte helt sant. ld (1) inkluderar endast de moduler som löser länkar vid tidpunkten för inkludering av biblioteket, därför, i en modul som ingår senare, kan det fortfarande finnas en länk som senare, eftersom den inte visas vid tidpunkten för inkludering av detta bibliotek , kan orsaka att ett kommando inkluderar de nödvändiga biblioteken ...

Å andra sidan tillåter ld (1) att standardbibliotek inkluderas tack vare alternativen -l och -L.

Men ... Vad menar vi med standardbiblioteket, vad är skillnaden? Nej. Bara att ld (1) letar efter standardbibliotek på vissa platser, medan de som beskrivs i parameterlistan som objekt söks efter med sina filnamn.

Som standard söker man efter bibliotek i katalogerna / lib och / usr / lib (även om jag har hört att det kan finnas ytterligare kataloger beroende på versionen / implementeringen av ld (1). -L tillåter oss att lägga till kataloger till de som söks med en vanlig bibliotekssökning. Den används genom att ange -L katalog för varje katalog vi vill lägga till. Standardbibliotek anges med alternativet -l Namn (där Namn anger biblioteket som ska laddas) och ld (1) kommer att söka, i lämplig ordning, i lämpliga kataloger efter en fil med namnet libName.so. Om den inte hittas kommer ett försök att göras att hitta libName.a, dess statiska version.

Om ld (1) hittar libName.so kommer det att länka det som ett delat bibliotek, medan om det hittar libName.a kommer det att länka moduler som härrör från det om de löser några olösta referenser.

Dynamisk länkning utförs när den körbara filen laddas av en speciell modul (i själva verket är denna specialmodul det delade biblioteket i sig) som heter /lib/ld-linux.so.

Det finns faktiskt två moduler för att länka dynamiska bibliotek: /lib/ld.so (för bibliotek som använder det gamla a.out-formatet) och /lib/ld-linux.so (för bibliotek som använder det nya ELF-formatet).

Det speciella med dessa moduler är att de måste laddas varje gång ett program länkas dynamiskt. Deras namn är standard (orsaken är att de inte kan flyttas från katalogen / lib, och deras namn kan inte ändras). Om vi ​​ändrar namnet /etc/ld-linux.so, slutar vi automatiskt använda alla program som använder delade bibliotek, eftersom denna modul ansvarar för att lösa alla länkar som inte löses under körning.

Den sista modulen stöds av existensen av filen /etc/ld.so.cache, som anger för varje bibliotek den mest lämpliga körbara filen som innehåller det biblioteket. Vi återkommer till detta ämne senare.

7.- soname. Körbara biblioteksversioner. Kompatibilitet.

Detta för oss till det mest förvirrande ämnet för delade bibliotek: deras versioner.

Vi ser ofta meddelandet "library libX11.so.3 not found", vilket gör oss förvirrade: med libX11.so.6-biblioteket kan vi inte göra någonting. Hur är det möjligt att ld.so (8) känner igen libpepe.so.45.0.1 och libpepe.so.45.22.3 och inte känner igen libpepe.so.46.22.3 omväxlande?

På Linux (och på alla operativsystem som använder ELF-formatet) identifieras bibliotek med sin distinkta teckensekvens: soname.

soname ingår i själva biblioteket, och denna sekvens bestäms när man länkar de objekt som utgör biblioteket. När du skapar ett delat bibliotek, för att ge ett värde till denna teckensträng, måste du skicka alternativet ld (1) (-soname<имя_библиотеки>).

Denna teckensekvens används av den dynamiska laddaren för att identifiera det delade biblioteket som ska laddas och för att identifiera den körbara filen. Det ser ut ungefär så här:
Ld-linux.so upptäcker att programmet kräver ett bibliotek och definierar dess sonamn. Sedan söks namnet i /etc/ld.so.cache och namnet på filen som innehåller detta bibliotek bestäms. Därefter jämförs det begärda sonamnet med namnet på det befintliga biblioteket, och om de är identiska behöver vi det! Om inte kommer sökningen att fortsätta tills den hittas, eller om den inte hittas kommer ett felmeddelande att visas.

Soname kan användas för att avgöra om biblioteket är lämpligt att ladda, eftersom ld-linux.so kontrollerar om det erforderliga sonamnet är detsamma som den nödvändiga filen. I händelse av skillnad kan vi få den berömda "libXXX.so.Y not found". Det är sonamnet som letas efter och felet som returneras bestäms av sonamnet.

Om vi ​​byter namn på biblioteket kan det bli mycket förvirring och själva problemet kvarstår. Men att ändra soname är inte heller en bra idé, eftersom det finns en konvention i Linux-gemenskapen för att tilldela soname:

Bibliotekets sonamn ska som standard identifiera motsvarande bibliotek och GRÄNSSNITTET för det biblioteket. Om vi ​​gör ändringar i biblioteket som endast påverkar den interna funktionaliteten, men gränssnittet förblir oförändrat (antal funktioner, variabler, funktionsparametrar), så kommer de två biblioteken att vara utbytbara och i allmänhet kommer vi att säga att ändringarna var små (båda bibliotek är kompatibla och vi kan ersätta det ena ovanpå det andra). Om detta händer ändras det binummer (som inte är en del av sonamnet) ofta och biblioteket kan bytas ut utan större problem.

Men när vi lägger till funktioner, tar bort funktioner och i allmänhet ÄNDRA GRÄNSSNITTET för biblioteket är det inte längre möjligt att säga att det här biblioteket är utbytbart med det föregående (till exempel ersätter libX11.so.3 med libX11. so.6 är en del av övergången från X11R5 till X11R6, när detta introducerar nya funktioner och därför ändrar gränssnittet). Att flytta från X11R6-v3.1.2 till X11R6-v3.1.3 kommer förmodligen inte att ändra gränssnittet och biblioteket kommer att ha samma sonamn - även om vi för att behålla den gamla versionen måste ge den ett annat namn (av denna anledning versionsnumret avslutar biblioteksnamnet, medan endast större nummer anges i sonamnet).

8.- ldconfig (8)

Som vi sa tidigare tillåter /etc/ld.so.cache ld-linux.so att konvertera sonamnet för filen som finns i biblioteket. Detta är en binär fil (för effektivitetens skull) som genereras av verktyget ldconfig (8).
ldconfig (8) skapar en symbolisk länk med biblioteksnamnet soname för varje DLL som finns i katalogerna specificerade i /etc/ld.so.conf. I det här fallet, när ld.so vill få namnet på en fil, vad den gör är att välja filen med önskat soname från kataloglistan. Och så det finns inget behov av att köra ldconfig (8) varje gång du lägger till ett bibliotek. Vi kör bara ldconfig när vi lägger till en katalog i listan.

9.- Jag vill göra ett dynamiskt bibliotek.

Innan vi börjar skapa ett dynamiskt bibliotek måste vi fundera på om det verkligen är nödvändigt. Dynamiska bibliotek orsakar systemöverbelastning av flera skäl:
    Laddar programmet utförs i flera steg; en för att ladda huvudprogrammet, resten för varje dynamisk länkbibliotek som detta program använder (vi kommer att överväga detta för motsvarande dynamiska länkbibliotek, eftersom denna sista punkt inte längre är en sällsynthet och blir en fördel).

    DLL-filer måste innehålla omplaceringsbar kod eftersom adressen som tilldelats en process i det virtuella adressutrymmet är okänd tills den laddas. I det här fallet tvingas kompilatorn reservera ett register för att lagra laddningspositionen för biblioteket och som ett resultat har vi ett register mindre för att optimera koden. Detta är inte ett sådant problem, eftersom den resulterande överbelastningen i de flesta fall inte är mer än 5% överbelastning.

För ett dynamiskt bibliotek är det mest acceptabla fallet när det ständigt används av något program (detta hjälper till att undvika urladdning av bibliotekstexten efter avslutad process som laddade den. Medan andra processer använder biblioteksmodulerna, finns den kvar i minnet) .

Det delade biblioteket är helt laddat i minnet (inte bara de moduler det behöver), så det måste användas i sin helhet för att vara användbart. Det värsta exemplet på att använda ett dynamiskt länkbibliotek är att bara använda en funktion, och 90 % av biblioteket används nästan aldrig.

C-standardbiblioteket är ett bra exempel på ett dynamiskt länkbibliotek (det används av alla program skrivna i C). Alla funktioner används i genomsnitt.

Ett statiskt bibliotek behöver inte inkludera sällan använda funktioner; så länge de finns i en egen modul kommer de inte att länkas till något program som inte kräver dem.

9.1.- Kompilera källkoder
Att kompilera källkod är exakt samma som för vanlig källkod, förutom att vi kommer att använda "-f PIC" (positionsoberoende kod).

Detta steg är grundläggande eftersom i ett statiskt bibliotek bestäms positionen för biblioteksobjekten under länkning, så det tar en bestämd tid. Detta steg var inte möjligt i de gamla a.out-binärerna, vilket resulterade i att varje delat bibliotek placerades på en fast position i det virtuella adressutrymmet. Som ett resultat kan konflikter uppstå när som helst om programmet ville använda två bibliotek och laddade dem i överlappande regioner av virtuellt minne. Det innebar att man tvingades upprätthålla en lista där alla som ville göra biblioteket dynamiskt var tvungna att deklarera ett antal adresser att använda så att ingen annan kunde använda det.

Som vi redan har noterat är det inte nödvändigt att registrera ett dynamiskt bibliotek i den officiella listan, eftersom när biblioteket laddas placeras det i den position som definieras för tillfället, trots att koden måste flyttas.

9.2.- Länka objekt till biblioteket
Efter att ha kompilerat alla objekt måste de länkas genom att ange ett alternativ som skapar ett dynamiskt laddningsbart objekt. gcc -shared -o libName.so.xxx.yyy.zzz -Wl, -soname, libName.so.xxx delat bibliotek. Låt oss ta itu med var och en separat:
    -delad.
    Detta talar om för länkaren att den i slutändan måste skapa det delade biblioteket och därför måste innehålla körbar kod i utdatafilen som motsvarar biblioteket.

    O lib Name.so.xxx.yyy.zzz.
    Detta är namnet på utdatafilen. Det är inte alls nödvändigt att följa namnkonventionen, men om vi vill att det här biblioteket ska bli en standard för framtida utveckling så är det bättre att följa det.

    Wl, -soname, lib Namn.so.xxx.
    Alternativet -Wl säger åt gcc (1) att följa alternativen (separerade med kommatecken) som är för länken. Denna mekanism används av gcc (1) för att skicka alternativ till ld (1). I exemplet skickar vi följande alternativ till länken:

-soname libName.so.xxx Det här alternativet ändrar bibliotekets sonamn, så det här biblioteket kommer att laddas när det efterfrågas av program som kräver det angivna sonamnet.
9.3.- Installera biblioteket
Tja, vi har redan motsvarande körbara fil. Nu, för att kunna använda den, måste den installeras på lämplig plats.

För att kompilera ett program som kräver vårt nya bibliotek måste vi använda följande kommando:

Gcc -o program lib Name.so.xxx.yyy.zzz eller, om biblioteket installerades i katalogen (/ usr / lib), räcker det: gcc -o program -l Namn (om biblioteket är i / usr / local / lib, lägg sedan till alternativet "-L / usr / local / lib"). Gör följande för att installera biblioteket:

    Kopiera biblioteket till katalogen / lib eller / usr / lib. Om du väljer att kopiera den till en annan plats (till exempel / usr / local / lib), kan du inte vara säker på att ld (1)-linkern hittar den automatiskt när du länkar dina program.

    Kör ldconfig (1) för att skapa en symbolisk länk libName.so.xxx.yyy.zzz till libName.so.xxx. I det här steget kommer vi att veta om vi har följt alla föregående steg korrekt och om biblioteket känns igen som dynamiskt. Detta steg påverkar bara laddningen av biblioteket under körning, inte länkningen av program.

    För att länken ska hitta biblioteket med alternativet -l, skapa en symbolisk länk från libName.so.xxx.yyy.zzz (eller libName.so.xxx, soname) till libName.so. För att denna mekanism ska fungera måste biblioteksnamnet matcha mönstret lib Name.so

10.- Skapa ett statiskt bibliotek

Om du å andra sidan behöver skapa ett statiskt bibliotek (eller du behöver två versioner för att kunna skapa statiskt länkade kopior), så måste du göra följande:

Obs: När du söker efter bibliotek, letar länken först efter en fil med namnet libName.so, och först sedan libName.a. Om vi ​​kallar båda dessa bibliotek (statiska och dynamiska versioner) samma namn, kommer det i allmänhet att vara omöjligt att avgöra vilket av de två som kommer att länkas i varje fall (dynamisk länkas alltid först, eftersom länken upptäcker det först).

Av denna anledning, om det är nödvändigt att ha två versioner av samma bibliotek, rekommenderas det alltid att namnge den statiska i formen libName_s.a, och den dynamiska libName.so. När du sedan länkar måste du ange:

Gcc -o program -l Namn_s för länkning med statisk version, medan för dynamisk version: gcc -o program -l Namn

10.1.- Kompilera källkoden
Du behöver inte vidta några speciella åtgärder för att kompilera källkoden. På samma sätt bestäms objektens position i länkstadiet, det är inte nödvändigt att kompilera med -f PIC-alternativet (även om det är möjligt att fortsätta använda det).
10.2.- Länka objekt till biblioteket
Ingen länkning görs för statiska bibliotek. Alla objekt arkiveras i en biblioteksfil med kommandot ar (1). Vidare, för att snabbt lösa symboler, är det tillrådligt att köra kommandot ranlib (1) på biblioteket. Även om det inte krävs, kan underlåtenhet att köra det här kommandot koppla bort moduler i den körbara filen, eftersom när länkaren bearbetar modulen under biblioteksskapandet löses inte alla indirekta beroenden mellan moduler omedelbart: säg, en modul i slutet av ett arkiv behöver en annan modul i i början av arkivet, betyder det att det tar flera passager genom samma bibliotek för att lösa alla länkar.
10.3.- Installera biblioteket
Det är tillrådligt att endast namnge statiska bibliotek i formatet libName.a om du bara vill ha statiska bibliotek. När det gäller två typer av bibliotek skulle jag rekommendera att kalla dem libName_s.a så att det är lättare att skilja mellan när man ska ladda ett statiskt bibliotek och när man ska ladda ett dynamiskt bibliotek.

Byggprocessen låter dig gå in i alternativet -static. Det här alternativet styr laddningen av /lib/ld-linux.so-modulen och påverkar inte bibliotekets sökordning, så om någon anger -static och ld (1) hittar ett dynamiskt bibliotek, kommer det att fungera med det (och inte fortsätt leta efter statiskt bibliotek). Detta kommer att leda till körtidsfel på grund av proceduranrop i ett bibliotek som inte är en del av den körbara filen - modulen för automatisk dynamisk laddning är inte länkad och därför kan processen inte exekveras.

11.- Jämförelse av statisk och dynamisk layout

Anta att vi vill skapa en distribution av ett program som använder ett bibliotek som vi kan distribuera endast statiskt inkluderat i programmet, och inte i någon annan form (ett exempel på det här fallet är applikationer byggda med Motif).

Det finns två sätt att skapa ett sådant program. Det första är att skapa en statiskt länkad körbar fil (med enbart .a-biblioteken och inte med en dynamisk laddare). Den här typen av program laddas en gång och kräver inga bibliotek från systemet (inte ens /lib/ld-linux.so). De har dock nackdelen att allt du behöver måste förvaras i en binär fil och därför är det oftast väldigt stora filer. Det andra alternativet är att skapa ett dynamiskt länkat program, det vill säga miljön där vår applikation ska köras måste ha alla motsvarande dynamiska bibliotek. Den körbara filen kan vara väldigt liten, även om det ibland är omöjligt att ha absolut alla bibliotek (till exempel finns det personer som inte har Motiv).

Det finns ett tredje alternativ, blandat, där vissa bibliotek är länkade dynamiskt och andra statiskt. I det här fallet skulle det vara logiskt att välja det motstridiga biblioteket i dess statiska form och alla andra i deras dynamiska form. Denna variant är en mycket vanlig form av mjukvarudistribution.

Du kan till exempel kompilera tre olika versioner av ett program enligt följande:

Gcc -statiskt -o program.statiskt program.o -lm_s -lXm_s -lXt_s -lX11_s \ -lXmu_s -lXpm_s gcc -o program.dynamiskt program.o -lm -lXm -lXt -lX11 -lXmu -lXpm gcc -o program. blandat program.o -lm -lXm_s -lXt -lX11 -lXmu -lXpm I det tredje fallet är endast Motivbiblioteket (-lXm_s) länkat statiskt, och alla andra länkas dynamiskt. Miljön som programmet kommer att köras i måste ha lämpliga versioner av biblioteken libm.so.xx libXt.so.xx libX11.so.xx libXmu.so.xx och libXpm.so.xx

Delat bibliotek eller delat bibliotekär en fil som är avsedd att delas mellan program. Modulerna som används av programmet laddas från separata delade objekt till minnet, istället för att kopieras av länken när den kopierar en enda körbar fil för programmet.

Delade bibliotek kan länkas statiskt, vilket innebär att referenser till biblioteksmoduler löses och moduler tilldelas minne när den körbara filen skapas. Men ofta fördröjs länkning av delade bibliotek tills de laddas.

Vissa äldre system som Burroughs MCP Multics har också bara ett format för körbara filer, oavsett om de är generiska eller inte. De har delat biblioteksfiler i samma format som körbara filer. Detta har två huvudsakliga fördelar: för det första kräver var och en bara en starthanterare, inte två (att ha en separat starthanterare ger ytterligare komplexitet). För det andra tillåter det också körbara filer att användas som delade bibliotek om de har en symboltabell. Typiska format för kombinerade körbara och delade bibliotek är ELF och Mach-O (båda på Unix) och (Windows).

I vissa äldre miljöer som 16-bitars Windows eller MPE för HP 3000, i kod med ett delat bibliotek var endast stackbaserad (lokal) data tillåten, eller andra betydande begränsningar infördes på den delade bibliotekskoden.

Delat minne

Bibliotekskoden kan delas i minnet med processer, såväl som på disken. Om virtuellt minne används kommer processer att köras på en fysisk sida med RAM, som mappas till olika processadressutrymmen. Detta har sina fördelar. Till exempel på OpenStep-systemet är applikationer ofta bara några hundra kilobyte stora och laddas snabbt; det mesta av deras kod fanns i bibliotek som redan var laddade av operativsystemet för andra ändamål.

Program kan dela RAM med hjälp av oberoende kod, som i Unix, vilket resulterar i en komplex men ändå flexibel arkitektur. Detta säkerställer att det finns en större sannolikhet för delning med hjälp av olika tekniker, som att i förväg kartlägga adressutrymmet och reservera sidor för varje delat bibliotek. Det tredje alternativet är lagring i en nivå Använd av IBM System / 38 och hans efterträdare.

I vissa fall kan olika versioner av delade bibliotek orsaka problem, särskilt när bibliotek med olika versioner har samma filnamn och används för olika applikationer installerade på systemet, var och en kräver en specifik version. Ett sådant scenario är känt som

Ett delat bibliotek låter dig använda symbolerna som det innehåller i flera filmer utan att kopiera dessa symboler till filmbibliotek. På grund av detta namnges de delade biblioteksobjekten Resurser(Tillgångar). I det här fallet används det delade biblioteket som en extern fil och läggs inte till i den skapade (eller redigerade) filmen.

Användning av delade bibliotek är tillrådligt, till exempel i följande fall:

  • när du använder samma ljudspår på flera sidor på webbplatsen;
  • när du använder texttecken i teckensnittet på flera sidor på webbplatsen;
  • när du vill tillhandahålla en enda källa för animationselement som används i flera scener i en film eller i flera filmer;
  • när du behöver ha ett centralt bibliotek med resurser för att göra det enklare att kontrollera de ändringar du gör.

Flash MX stöder två typer av delade bibliotek:

  • Körning- delat runtime-bibliotek; symboler som ingår i ett sådant bibliotek är tillgängliga för delning av flera filmer, men sådana symboler kan endast redigeras direkt i källfilmen;
  • Författartid- bibliotek som delas vid utvecklingstillfället; symbolerna som ingår i ett sådant bibliotek är tillgängliga för delning av flera filmer, och det är tillåtet att redigera innehållet i biblioteket i valfri delägarfilm.

För att de delade biblioteksresurserna ska vara tillgängliga i filmer som finns på en fjärrplats, måste Flash-filen med biblioteket exporteras till SWF-format och laddas upp till webbplatsen.

Kommentar
Tidigare version av Flash stöder endast det delade runtime-biblioteket
.

För att skapa ett delat bibliotek som Körning, nödvändigt:

  1. Bestäm dess resurser (symboler som ingår i den) i en separat film.
  2. Tillåt export av delade tecken.
  3. Ange webbadressen till webbplatsen där biblioteket ska finnas.
  4. Exportera Flash-filen med detta bibliotek till SWF-format och ladda upp till webbplatsen.

För att kunna använda delade bibliotekssymboler Körning i andra filmer ("medägare") är det nödvändigt att i var och en av dem skapa en länk till de delade karaktärerna.

Låt oss nu titta på stegen ovan mer i detalj.

När du har skapat ett delat bibliotek måste du ange vilka symboler som kan exporteras till andra filmer. Detta kräver följande steg:

  1. Välj symbolen från listan som du vill göra "delad".
  2. Välj kommandot i symbolens snabbmeny Länkar(Bindande).
  3. I den öppnade dialogrutan Symbolkopplingsegenskaper(Symbollänkningsparametrar), Fig. 10.12, kryssa i rutan Exportera för körtidsdelning(Tillåt export vid körning).
  4. I en textruta Identifierare ange namnet (identifieraren) på symbolen under vilken den kommer att exporteras till delägarfilmen; även om standardnamnet är bibliotekets symbolnamn, om det innehåller mellanslag, ta bort dem.
  5. I en textruta URL ange källfilmens internetadress (det vill säga SWF-filen för det delade biblioteket).
  6. Om den exporterade symbolen ska användas direkt från den första bildrutan i delägarfilmen, välj Exportera i första bildrutan.
  7. Om du vill göra den exporterade symbolen tillgänglig i ActionScript, välj Exportera för ActionScript.

Ris. 10.12... Dialogrutan Symbolinställningar för delat bibliotek

Att använda delade biblioteksresurser Körning i en delägarfilm krävs följande steg:

  1. Öppna biblioteket för den här filmen genom att välja från menyn Fönster kommando Bibliotek.
  2. Välj kommandot i rullgardinsmenyn för bibliotek Ny symbol; som ett resultat kommer en dialogruta att visas på skärmen Skapa ny symbol(Skapa en ny symbol), vars centrala del liknar dialogrutans format Symbolkopplingsegenskaper(fig. 10.13).
  3. I en textruta Identifierare ange namnet på symbolen som ska importeras till delägarfilmen.
  4. I en textruta URL ange källfilmens internetadress.


Ris. 10.13... Dialogruta för att ställa in parametrarna för det delade tecknet

Statiska och dynamiska bibliotek.

Bibliotek kallas "samlingar" av subrutiner eller objekt, som regel fokuserade på att lösa en uppsättning relaterade problem. Med tanke på deras organisation och användning är bibliotek statiska och dynamiska.

Statiska bibliotek (statiska bibliotek) kan vara en uppsättning källkoder, inkluderade av programmeraren i sitt program, eller i form av förkompilerade objektfiler, länkade samman vid kompileringstillfället. På Windows har dessa filer vanligtvis tillägget<.lib>... Som ett resultat av att länka till ett statiskt bibliotek innehåller programmet alla funktioner det använder, vilket ökar dess storlek, men gör det mer fristående.

Dynamiska bibliotek (delat bibliotek, dynamiskt länkbibliotek) laddas av operativsystemet på "efterfrågan" av ett program som körs redan under dess körning. Om det nödvändiga biblioteket redan har laddats in i minnet, utförs inte omladdningen. I det här fallet kan samma uppsättning funktioner eller biblioteksobjekt användas samtidigt av flera program som körs, vilket gör det möjligt att effektivt använda resurserna i RAM-minnet. Delade bibliotek på Windows har vanligtvis tillägget<.dll>.

För att använda biblioteket måste du tala om för kompilatorn att du måste ansluta den och anropa funktionen från biblioteket (med hjälp av lämplig rubrikfil), medan källtexten för funktionen inte behövs.

Skapa ett dynamiskt bibliotek.

I Microsoft Visual Studio liknar att skapa ett projekt för att bygga ett dynamiskt länkbibliotek den vanliga proceduren för att skapa ett projekt för en dum applikation. Projekttypen är Win32 Console Application, bara nu behöver du välja "DLL"-objektet i den nya projektguiden:

Om det inte finns något sådant i guiden kan du skapa ett vanligt konsolapplikationsprojekt och sedan ställa in dess typ i projektegenskaperna:

Konfigurationsegenskaper => Allmänt => Konfigurationstyp: Dynamic Library (.dll)

Declspec (dllexport) void display (const char * str);

#include "dlltest.h"

tom visning (const char * str)

Modifieraren __declspec (dllexport) tillåter biblioteket att exportera den angivna funktionen för användning av andra applikationer.

Som ett resultat av att bygga projektet, en dynamisk biblioteksfil med tillägget<.dll>och även en importbiblioteksfil med tillägget<.lib>... Importbiblioteket är avsett att underlätta efterföljande användning av det dynamiska biblioteket. Även om filtillägget för importbiblioteket är detsamma som standardtillägget för statiska bibliotek, bör de inte förväxlas.

Använda ett dynamiskt bibliotek.

Det finns två sätt att använda ett dynamiskt bibliotek i ett program. Implicit länkning innebär att man använder ett importbibliotek för att bestämma adresserna till de funktioner som tillhandahålls av biblioteket. Operativsystemet laddar DLL:n efter att programmets körbara fil har laddats. Den körbara filen anropar de exporterade DLL-funktionerna som om funktionerna fanns i själva den körbara filen.

Vid explicit länkning måste den körbara filen som använder DLL:n göra funktionsanrop för att explicit ladda och ta bort DLL:n och komma åt de exporterade DLL-funktionerna. Klientens körbara anropar de exporterade funktionerna med hjälp av en funktionspekare.

Oavsett vilken metod som väljs kan den körbara filen använda samma DLL. Dessutom är dessa mekanismer inte ömsesidigt uteslutande eftersom medan en körbar implicit länkar till en DLL, kan en annan vara explicit länkande.

Som ett exempel kommer vi att använda den implicita länkmekanismen (som den enklaste) för att ansluta det konstruerade enkla biblioteket.

Låt oss skapa ett separat projekt för en vanlig konsolapplikation (det är möjligt inom ramen för samma lösning som projektet för själva biblioteket). För att använda visningsfunktionen implementerad i biblioteket måste du:

    Anslut motsvarande rubrikfil "dlltest.h". För att göra detta, använd antingen sökvägen till filen direkt i #include-direktivet (om projekten finns i samma lösningsmapp är det bättre att använda en relativ sökväg), eller i projektegenskaperna lägg till sökvägen till denna rubrikfil i avsnittet

Konfigurationsparametrar => C / C ++ => Allmänt => Ytterligare inkludera kataloger

    Använd lämplig importbiblioteksfil. För att göra detta kan du använda ett direktiv av formuläret (här används den relativa sökvägen till den byggda lib-filen).

Alternativt kan du lägga till sökvägen till importbiblioteksfilen i projektegenskaperna under

Konfigurationsparametrar => Länkare => Ingång => Ytterligare beroenden

Låt oss nu skapa huvudprogramfilen med följande innehåll:

#pragma-kommentar (lib, "../Debug/dlltest.lib")

#include "dlltest.h"

display ("Hej");

system ("paus");

För att framgångsrikt starta programmet är allt som återstår att se till att motsvarande DLL är tillgänglig. När programmet startar kommer operativsystemet att leta efter alla nödvändiga biblioteksfiler i mappen från vilken programmet startades, samt i systemsökvägarna som definieras av miljövariabeln PATH. Följaktligen måste DLL-filen för det byggda biblioteket antingen finnas i samma mapp som den körbara filen för det anropande programmet, eller i en av mapparna som definieras i PATH.