NPRG0 4 1 Programování v C++ Programování v C

Post on 06-Jan-2016

81 views 4 download

description

NPRG0 4 1 Programování v C++ Programování v C. David Bednárek Filip Zavoral. C vs. C++. V ývoj 1970-3 první verze C , spole č n ý v ý voj s UNIXem , jádro v C 1978 Kerninghan, Ritchie: The C Progr amming Language 1980 AT &T - " C with Classes" - PowerPoint PPT Presentation

Transcript of NPRG0 4 1 Programování v C++ Programování v C

NPRG041Programování v C++

Programování v C

David BednárekFilip Zavoral

Vývoj◦ 1970-3 první verze C, společný vývoj s UNIXem, jádro v C◦ 1978 Kerninghan, Ritchie: The C Programming Language◦ 1983 Rick Mascitti: poprvé název C++◦ 1985 Stroustrup: The C++ Programming Language◦ 1998 ISO/ANSI norma C++◦ 1999 ISO/ANSI norma C - 'C99'◦ 2011+ C++11/14/17

zásadní rozšíření jazyka - lambda, r-values, generic prog., ...

Proč C v 21. století◦ jádra OS, drivery, knihovny◦ GPU, many-core◦ embedded devices, 'pračky'◦ údržba sw

C vs. C++

... neboli co v C není

OOP◦ classes, inheritance, member functions, constructors and

destructors, virtual functions, access control, pointers to members, static members

Syntax◦ templates, smart pointers, exceptions, references, overloading,

default arguments, namespaces, new/delete, casting, friend, inline, RTTI, auto, lambda, rvalues, concepts, ..., ..., ...

Libraries◦ containers, iterators & algorithms◦ strings◦ streams

C++ jako ostrá nadmnožina C

bool

struct & enum tags

implicitní konverze - enum, void *

main - return 0;

Odlišnosti C a C++

struct S { int x;};

S s;

struct S { int x;};

struct S s;

typedef struct S_ { int x;} S;

S s;

bool b = true; typedef enum bool_ { FALSE, TRUE} bool;bool b = TRUE;int b2 = a > 1;_Bool b = TRUE;

C99

enum E { NULA };enum E e = NULA;int x = e;int* p = malloc(sizeof( int));

enum E { NULA };E e = NULA;int x = (int)e;int* p = (int*)malloc(sizeof(int));

int main(){ ...}

int main(){ ... return 0;}

C ⊈ C++

Pole a ukazatele, aritmetika ukazatelů

T a[n]; pole prvků typu T T *p = &a[i]; ukazatel p ukazuje na prvek pole p+j; p+=j; ++ppřičtení - posun o j prvků v rámci

pole p-j odečtení - posun zpět p1-p2 odečtení ukazatelů - počet prvků mezi

int a[5]; int *p;

a[2] = 20; p = &a[2];

a[0] = *p - 15; ++p; *p = 30;

0 1 2 3 4

? ? 20 ? ?

5 ? 20 30 ?

p

p

reference na prvek pole

inkrementace ukazatele

posun na další prvek

a

reference na prvek pole

stejně jako iterátory

p = &a[1]; *(p+3) = 40;

Operátor []

p[i] *(p+i)

&p[i] p+i

a &a[0]

Automatické konverze pole-ukazatel◦ identifikátor pole se chová jako ukazatel na nultý

prvek Pole nelze přiřazovat ani předávat hodnotou

◦ p = a je ekvivalentní p = &a[0]

5 ? 20 30 40

ppřičtení čísla k ukazateli posun o n prvků

identifikátor pole je ukazatelna svůj nultý prvek

indexování pole (ukazatele) je 'jen' jiný zápis přístupu přes ukazatel

Pole a ukazatele, aritmetika ukazatelů

Řetězec - pole znaků (char) zakončené nulou◦ konvence, knihovny

"Ahoj"

X proměnná 'X' znaková konstanta - celočíselná hodnota "X" řetězec - ukazatel

Řetězce

'A' 'h' 'o' 'j' '\0'

Každý řetězec musí být vždy ukončen nulou

'A' 'h' 'o' 'j' '\0'

vždy myslet na koncovou nulu !

pozor na uvozovky a apostrofy !

char buffer[4];strcpy( buffer, "Ahoj");

'\0' = 0

kód znaku v použitém kódování

(ASCII, CP1250, ISO8859-2, EBCDIC, ...)

char s1[] = "Uno";

const char *s2 = "Due";

puts( "Uno");

Řetězcové proměnné a konstanty

'U' 'n' 'o' '\0'

'D' 'u' 'e' '\0'

s1:

s2:

Inicializovaná proměnná typu ukazatel++s2 se přesune na další znak

Inicializované pole (konstantní ukazatel)

++s1 nelze! anonymní globální proměnnáconst char[]

ekvivalent globální proměnné typu const char[ ] inicializované obsahem konstanty

... = { 'U', 'n', 'o', 0 };

Délka řetězce – různé implementace

int i = 0;while ( *s != '\0') { ++i; ++s;}return i;

int strlen ( const char* s){ int i = 0; while ( s[i] != '\0') { ++i; } return i;}

char *p = s;while (*p++) ;return p-s-1;

for( i=0; *s != '\0'; ++i) ++s;

for( i=0; *s != '\0'; ++i, ++s) ;

int i=0;while ( *s++ != '\0') ++i;

int i=0;while ( *s++) ++i;

přístup přes ukazatel

více inkrementací prázdné tělo

nezapomenout na ';' !!

složitější podmínka:test nenulovostiinkrementace

ukazatele

while(a!=0) while(a)podmínka je splněnapokud je nenulová

rozdíl ukazatelů = počet prvků mezi nimi

pozor na ± 1 !

Řetězce – chyby při kopírování

D o b r y d e n \0pozdrav

buf

char buf[6];char pozdrav[] = "Dobry den";strcpy( buf, pozdrav);

D o b r y d e n \0

vždy pozor na dostatek místafunkce nic nekontroluje !!!váš program provedl...

char *ptr;char pozdrav[] = "Ahoj";strcpy( ptr, pozdrav);

kopírování na neinicializovaný ukazatel !!!váš program provedl...

A h o j \0pozdrav

ptr?

A h o j \0ptr

neinicializovaný !!!

Naprosto chybné řešení◦ Nekontroluje přetečení pole buf◦ Vrací odkaz na lokální proměnnou, která v okamžiku návratu zaniká

Vracení řetězců - lokální proměnná

char * cele_jmeno( const char * jm, const char * prijm){ char buf[ 100]; strcpy( buf, jm); strcat( buf, " "); strcat( buf, prijm); return buf;}

string cele_jmeno( const string& jm, const string& prijm){ return jm + " " + prijm;}

Chybné řešení◦ Nekontroluje přetečení pole buf◦ Používá statickou proměnnou

zbytečně zabírá místo i v době, kdy funkce není vyvolána opakovaná volání ji sdílejí:

podmínka nikdy nebude splněna, protože strcmp vždy dostane stejné ukazatele na totéž pole buf

Vracení řetězců - statická proměnná

char * cele_jmeno( const char * jm, const char * prijm){ static char buf[ 100]; strcpy( buf, jm); strcat( buf, " "); strcat( buf, prijm); return buf;}

if ( strcmp( cele_jmeno( j1, p1), cele_jmeno( j2, p2)) )

Funkční řešení, ale nebezpečné◦ Nekontroluje přetečení pole buf◦ Pokud volající nemá spolehlivý horní odhad velikostí jména a

příjmení, nemůže tuto funkci bezpečně volat

◦ Většina C knihovenale funguje podobně

Vracení řetězců - parametr

void cele_jmeno( char * buf, const char * jm, const char * prijm){ strcpy( buf, jm); strcat( buf, " "); strcat( buf, prijm);}

void tisk( const char * jm, const char * prijm){ char buf[ 100]; cele_jmeno( buf, jm, prijm); puts( buf);}

Vracení řetězců - bezpečné řešeníint cele_jmeno( char * buf, size_t bufsize,

const char * jm,const char * prijm)

{ size_t lj = strlen( jm); size_t lp = strlen( prijm); if ( lj + lp + 2 > bufsize ) { /* error */ return -1; } memcpy( buf, jm, lj); buf[ lj] = ' '; memcpy( buf + lj + 1, prijm, lp); buf[ lj + lp + 1] = 0; return lj + lp + 1;}

void tisk( const char * jm, const char * prijm){ enum { N = 100 }; char buf[ N]; if( cele_jmeno( buf, N, jm, prijm) > 0) puts( buf);}

max velikost pole

kontrola korektnostivýsledku

kontrola velikosti polepozor na mezeru a konec!

kopírování jednotlivých částí

návrat výsledné délky

Kombinace typových konstrukcí

A * x[10] pole ukazatelů

A (* x)[10] ukazatel na pole

A * x() funkce vracející ukazatel

A (* x)() ukazatel na funkci

A x[10]() pole funkcí - zakázáno

A (* x[10])() pole ukazatelů na funkci

A x()[10] funkce vracející pole - zakázáno

A (* x())[10] funkce vracející ukazatel na pole

čtení deklarací: od identifikátoru doprava, až to nepůjde, tak doleva

typicky se nepoužívápole = ukazatel na 1. prvek

int*(*pf[10])(void);

int*(*maso(int*(*p1)(void),int*(*p2)(void)))(void);

Kombinace typových konstrukcí

co to je za maso ???

int*(*pf[10])(void);int*(*maso(int*(*p1)(void),int*(*p2)(void)))(void);

typedef int* fce( void);fce * pf [10];fce * maso( fce* p1, fce* p2);

Kombinace typových konstrukcí

použitím typedefse výrazně zpřehlední kód

OOP v Cclass A {public: A() : x_(1) {} int f( int y) { return x_ + y; }private: int x_;};

A* a = new A;a->f(2);

typedef struct A_ { int x_;} A;

int A_init( A* a) { a->x_ = 1; }int A_f( A* a, int y) { return a->x_ + y; }

A* a = malloc( sizeof( A));A_init(a);A_f(a,2);

explicitní this

explicitní prefix nebo možnost kolize

nemožnost přetížení

beztypová alokace

absence ochrany

absencekonstruktorua destruktoru

explicitní inicializace

Pozdní vazba v Cclass A { virtual int f(void) { return 1; }};

class B : public A { virtual int f(void) { return 2; }}

A* a = new B;a->f();

typedef int fnc(void);typedef struct A_ { fnc* f_;} A;void A_init( A* a, fnc* f) { a->f_ = f; }int A_f( A* a) { return (*a->f_)(); }int A_f_body() { return 1; }int B_f_body() { return 2; }

A* a = malloc( sizeof( A));A_init( a, B_f_body);A_f( a);

VMTkonstruktor inicializace

VMT

virtual method

'odvozená metoda'

zavolá se B_f

ruční inicializace

Parametry příkazové řádky

C:\> myprog.exe -n -w a.txt b.txt

0

m y p r o g . e x e \0

- n \0

- w \0

a . t x t \0

b . t x t \0

argv

5argc

int main( int argc, char** argv)

pole řetězců(ukazatelů na char)

Počet parametrůvčetně názvu programu != počet ukazatelů v argv

vector<string> arg( argv, argv+argc);

int main( int argc, char** argv){ int n=0, w=0; while( *++argv && **argv=='-') { switch( argv[0][1]) { case 'n': n = 1; break; case 'w': w = 1; break; default: error(); } } if( !argv[0] || !argv[1]) error(); doit( argv[0], argv[1], n, w); return 0;}

options

usage: myprog [-n] [-w] fileA fileB

nastavení přepínače

zbývající parametry

výkonná funkce

p r g . e x e \0

- n \0

- w \0

a . t x t \0

b . t x t \0

0

argv

Zpracování příkazové řádky

int main( int argc, char** argv){ int n=0, w=0; int x = 0; char* f = 0; while( *++argv && **argv=='-') { switch( argv[0][1]) { case 'n': n = 1; break; case 'w': w = 1; break; case 'x': x = atoi( *argv+2; break; case 'f': f = *argv+2; break; default: error(); } } if( !argv[0] || !argv[1]) error(); doit( argv[0], argv[1], n, w, x, f); return 0;}

číselný parametr

usage: myprog [-n] [-w] [-x123] [-ffilename] fileA fileB

řetězcový parametr

- x 1 2 3 \0

- f f i l ...

argv

Zpracování příkazové řádky

int main( int argc, char** argv){ int n=0, w=0; int x = 0; char* f = 0; while( *++argv && **argv=='-') { switch( argv[0][1]) { case 'n': n = 1; break; case 'w': w = 1; break; case 'x': x = atoi( argv[0]+2); break; case 'f': if( argv[0][2]) f = *argv+2;

else f = *++argv; break;

default: error(); } } if( !argv[0] || !argv[1]) error(); doit( argv[0], argv[1], n, w, x, f); return 0;}

-ffile

usage: myprog [-n] [-w] [-x123] [-f filename] fileA fileB

-f file

- f \0

argv- f f i l ...

f i l e n ...

Zpracování příkazové řádky

≡ &(argv[0][2])

Variabilní argumenty

int sum( int num, ...) { int rv = 0; va_list argptr; va_start( argptr, num); for( ; num > 0; num--) { rv += va_arg( argptr, int); } va_end( argptr); return rv;} int answer = sum( 4, 4, 3, 2, 1);

opravdu '...'

speciální typ

inicializace

přístup

ukončení

#include <stdarg.h>typedef va_list ????va_start( va_list argptr, last_parm);va_arg( va_list argptr, type);va_end( va_list argptr );

korektnost parametrů musí zajistit uživatel

funkce

Náhrada v C++: Variadic Templates

typ !

int printf( const char * format, ...);◦ % [flags] [width] [.precision] [opt_pref] type ◦ %c - char - znak◦ %d - int - decimálně◦ %x - int - šestnáctkově◦ %ld - long◦ %f - double - s desetinnou tečkou◦ %g - double - s exponentem◦ %s - char * - řetězec

printf

fprintf( FILE*, sprintf( char*,swprintf( wchar_t*,_snprintf( char*, int n,_scprintf(...

místo width a/nebo precision znak *

hodnota následujícího parametru

width: min. počet míst na výstupuprecision: max. počet zpracovávaných

znaků

#include <stdio.h>printf( "Ahoj %s dnes je %d.%d.", "Babi", 8, 1);

shodu formátu a parametrů musí zajistit programátor

neshoda: nedefinované chování

printf

printf(":%c:%6d:%08X:%7.3f:%7.3f:\n", 'a', 17, 1234, -1234.56, -1234.5678);

printf(":%s:%6s:%6s:%-6s:%-6.3s:%.3s:\n","ahoj", "ahoj", "ahojbabi", "ahoj", "ahoj", "ahoj");

printf(":%*d:%-*.*s:\n", 6, 17, 6, 3, "ahoj");

printf(":%c:%c:%d:%s:\n", 0xffeedd41, "ahoj", "ahoj", 'a');

:a:▫▫▫▫17:000004D2:▫▫-1234.560:▫▫-1234.568:

:ahoj:▫▫ahoj:ahojbabi:ahoj▫▫:aho▫▫▫:aho:

:▫▫▫▫17:aho▫▫▫:

:A::78263451:●

Unhandled exception at 0x0041470c :Access violation reading location

0x00000061

#include <stdio.h>

FILE* fp;int c;

if( !(fp = fopen("c:\\f.txt", "r")))error();

while( (c = getc( fp)) != EOF)putchar( c);

fclose( fp);

Práce se soubory

typ 'soubor'(ukazatel na strukturu)

otevření souborukonvence dle OS

pozor na '\\' !!!

konstanta v stdio.hrůzná od všech možných dat

mode

soubor ex.

soubor neex.

seek

r R Error 0

w Del, W W 0

a W W End

r+ R/W Error 0

w+ Del, R/W R/W 0

a+ R/W R/W End

+: vždy čtení i zápis

a: otevřít na konci

r: soubor musí existovat

w: soubor se smaže

Textový soubor◦ konverze konců řádek ('\n') na platformově závislou vnější reprezentaci◦ typicky 0x0D 0x0A (Win) nebo 0x0A (Unix)◦ konverze je automatická, programátor se o to nemusí starat◦ vhodné pro ukládání lidsky čitelných dat◦ getc/putc, fgets/fputs, fprintf, ...◦ chování fseek/ftell na '\n' nedefinován - nepoužívat

Binární soubor◦ žádné konverze se neprovádí◦ v souboru je přesný binární obraz zapisovaných dat◦ vhodné pro ukládání vnitřních datových struktur◦ lidsky přímo nečitelné◦ typicky fread/fwrite, lze i getc/putc (přístup po bajtech)◦ fseek/ftell OK

Textové vs. binární soubory

FILE* fopen( const char* fname, const char* mode);int fclose( FILE* fp);int fprintf( FILE* fp, const char* format, ...);int getc( FILE* fp);int putc( int c, FILE* fp);char* fgets( char* buffer, size_t limit, FILE* fp);int fputs( const char* buffer, FILE* fp);

size_t fread( void* ptr, size_t size, size_t n, FILE* fp);size_t fwrite( const void* ptr, size_t size, size_t n, FILE* fp);long ftell( FILE* fp);int fseek( FILE* fp, long offset, int whence);

whence: SEEK_SET, SEEK_CUR, SEEK_END

int fflush( FILE *fp);

Funkce pro práci se soubory

funkce pro práci se standardním vstupem/výstupem int getchar( void); int putchar( int c); int printf( const char* format, ...);

char* gets( char* buffer);

standardní vstup/výstupFILE* stand. otevřený na čtení/zápis před vstupem do main

FILE *stdin;FILE *stdout;

getchar() getc(stdin)putchar(c) putc(c, stdout)

FILE* fp = stdout;if( ...) fp = fopen( "...", "r");c = getc( fp);

Souborový vs. standardní v/v

jednotný zápisna std výstup nebo

do souboru

Nikdy nepoužívat!Nelze ohlídat přetečení bufferu

všechny souborové funkce lze použít

i pro std. v/v

<string.h> <cstring>strlen, strcmp, stricmp, strcpy, strncpy, strcat, strchr, strrchr, strstr,memset, memcmp, memcpy, memchr<stdio.h> <cstdio>getchar, putchar, fopen, tmpfile, fclose, getc, putc, fgets, fputs, freadfwrite, ftell, fseek, printf, fprintf, vfprintf, fflush, ungetcFILE, stdin, stdout, EOF, SEEK_SET, ...<stdlib.h> <cstdlib>malloc, free, atoi, atof, strtol, qsort, rand, exit<ctype.h> <cctype>isalpha, isdigit, isxdigit, isalnum, isspace, ispunct, iscntrl, islower,isupper, tolower, toupper<math.h> <cmath>abs, floor, sin, sqrt, exp, exp, log, ...<time.h> <ctime>

time, gmtime, strftime, asctime, clock, ...

Knihovní funkce C

... a mnoho dalších<assert.h> <errno.h><limits.h> <locale.h>

<stdarg.h> <setjmp.h>

C++ namespace std

#define _ F-->00||F-OO--;

int F=00,OO=00;main(){F_OO();printf("%1.3f\n",4.*-F/OO/OO);}F_OO()

{

_-_-_-_

_-_-_-_-_-_-_-_-_

_-_-_-_-_-_-_-_-_-_-_-_

_-_-_-_-_-_-_-_-_-_-_-_-_-_

_-_-_-_-_-_-_-_-_-_-_-_-_-_-_

_-_-_-_-_-_-_-_-_-_-_-_-_-_-_

_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_

_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_

_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_

_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_

_-_-_-_-_-_-_-_-_-_-_-_-_-_-_

_-_-_-_-_-_-_-_-_-_-_-_-_-_-_

_-_-_-_-_-_-_-_-_-_-_-_-_-_

_-_-_-_-_-_-_-_-_-_-_-_

_-_-_-_-_-_-_-_

_-_-_-_

}

Co (a proč ) dělá tento program?

Je v C, nikoliv v C++

přednáška: Bednárek, Yaghob, Zavoral◦ pokročilá a vybraná témata◦ pokročilá práce se šablonami, generické programování◦ konkurence a paralelismus◦ novinky C++11/14/17/TS◦ externí knihovny, ..., ...

cvičení - samostatná práce◦ 3 DÚ během semestru◦ zadání, vypracování, opravení, feedback◦ body ↠ známka

NPRG059 - Pokročilé praktikum z objektového programování◦ Mgr - povinný pro obor Softwarové systémy◦ doporučený pro SZZ okruhy SW inženýrství a Vývoj software◦ absolvování (Pokročilé C++ && (Pokročilá Java || Pokročilý C#))◦ + kvalitní sw projekt C++/C#/Java

Pokročilé programování v C++

vlastní C moduly◦ obj, lib, dll/so◦ jak linkovat C a C++ moduly ◦ jak dělat společné C/C++ headery

cizí C knihovny◦ jak z C++ volat C knihovny◦ callback z C knihoven do C++◦ mandlování, volací konvence◦ dynamicky linkované knihovny

Interoperabilita

Překlad více modulů

.c

.h .h

CC .obj Link .exe

.obj.obj.obj.obj.obj.lib

.obj.obj.obj

kompilace jednoho modulu

knihovnyknihovní headeryvlastní headery

.cpp

.c.cpp

další moduly

Vytvoření vlastní knihovny

.c

.h .h

CC .obj Lib .lib

.obj.obj.obj

kompilace jednoho modulu

knihovní headeryvlastní headery

.cpp

.c.cpp

další moduly

C++ exe / C lib

CPPC .obj Link .exe

.obj .lib

zdrojový text / překladač C

exe.cpp

lib.c

lib.h

CC Lib

zdrojový text / překladač C++

C++ exe / C lib

CPPC .obj Link .exe

.obj .lib

exe.cpp

lib.c

lib.h

CC Lib

error LNK2019: unresolved external symbol ◦ "int __cdecl lib_fnc(int)" (?lib_fnc@@YAHH@Z) ◦ referenced in function _main what the ... ...

hell???

mangling◦ mandlování◦ znetvoření◦ name-decoration

syntaktická a sémantická informace o symbolu◦ zjednoznačnění identifikátoru◦ proměnná / funkce / operator / metoda◦ typy a typové konstrukce parametrů a návratové hodnoty◦ třída, další atributy (const, volatile, ...)◦ volací konvence

formát jednotně nedefinovaný◦ závislý na platformě, překladači, ...◦ obecně nepřenositelné

Mandlování int a;int a( void);int a( int, int);class a {};class a { int a; };class a { int a( int); };

C++ exe / C lib

/* pureclib.c */#include "pureclib.h"

int lib_x;

int lib_fnc( int x){ return old_x;}

/* pureclib.h */

#ifndef PURECLIB__H_#define PURECLIB__H_

extern int lib_x;int lib_fnc( int x);

#endif

// cppexe.cpp#include "pureclib.h"

int main(....){ int i = lib_fnc( 1);}

CPPC CC různé překladačerůzné jazyky

různá implementace

_lib_fnc ?lib_fnc@@YAHH@Z

Společné hlavičkové soubory

/* pureclib.c */#include "pureclib.h"

int lib_x;

int lib_fnc( int x){ return old_x;}

/* pureclib.h */

#ifndef PURECLIB__H_#define PURECLIB__H_

#ifdef __cplusplusextern "C" {#endif

extern int lib_x;int lib_fnc( int x);

#ifdef __cplusplus}#endif

#endif

// cppexe.cpp#include "pureclib.h"

int main(....){ int i = lib_fnc( 1);}

CPPC CC

symboly C

_lib_fnc _lib_fncCPPC - definovanéCC - nedefinované

způsob implementace volání funkcí◦ registry vs. zásobník◦ zachovávání registrů◦ pořadí předávání parametrů◦ návratová hodnota◦ příprava a úklid zásobníku

konkrétní konvence◦ není součástí normy - rozšíření

__cdecl - default for C and C++, varargs __stdcall - Win32 API functions __fastcall - arguments in registers, faster __thiscall - this __clrcall - C++/CLI, .Net, managed code

Volací konvence

mov eax, 1mov ebx, 2call ?f@@X

mov eax, [ebp+08] mov ebx, [ebp+04]...

f( 1, 2);

C++ callback

/* pureclib.c */#include "pureclib.h"

int lib_cb( int x, int (*cb_fnc)( int)){ return cb_fnc( x);}

/* pureclib.h */

#ifdef __cplusplusextern "C" {#endif

int lib_cb( int x, int (*cb_fnc)( int));

#ifdef __cplusplus}#endif // cppexe.cpp

#include "pureclib.h"

extern "C" int cpp_fnc( int x) { return x+1;}

int main() { lib_cb( i, cpp_fnc);}

CC očekává C funkci

extern "C" určuje i volací konvenci

callbackknihovní kód volá klientskou funkci

CC očekává C funkci

použití funkcí dodaných až za běhu není součástí normy

◦ použití na různých platformách ideově podobné ale nepřenositelné

◦ pomocí preprocesoru lze multiplatformní rozhraní ale netriviální

Windows◦ .dll◦ chová se jako .exe◦ vlastní zásobník, heap, standardní knihovny

Linux / Unix◦ .so◦ chová se jako .lib◦ balíček .o

Dynamicky linkované knihovny

more details:

http://www.symantec.com/connect/articles/dynamic-linking-linux-and-windows-part-one

...-part-two

Dynamicky linkované knihovny// dll.cpp

extern "C" __declspec(dllexport)int add( int a, int b) { return a + b;}

BOOL APIENTRY DllMain(....) { return TRUE;}

// exe_explicit.cpp HINSTANCE dll = LoadLibrary( TEXT("dll.dll"));if( dll == NULL) return 1;

typedef int dll_fnc(int, int);dll_fnc* add = (dll_fnc*) GetProcAddress( dll, "add");if( add == NULL) { FreeLibrary( dll); return 1;}

int result = add(1, 2);

FreeLibrary( dll);

// exe_import.cpp extern "C" __declspec(dllimport)int add(int a, int b); int result = add(1, 2);

explicit runtime linking

běžné volání

statické slinkovánís dll.lib

jen proxy, kód v .dll

load dll