Obsah
1. Předávání polí mezi skriptem napsaným v Pythonu a knihovnou naprogramovanou v jazyku C
2. Funkce naprogramovaná v jazyku C, která akceptuje pole prvků typu float
3. Konstrukce pole na straně Pythonu s jeho předáním do céčkovské funkce
4. Překlad a spuštění dnešního prvního demonstračního příkladu
5. Nastavení hodnot prvků pole
6. Výsledek při spuštění druhého skriptu
7. Inicializace prvků pole přímo v konstruktoru
8. Mezní případ – pole s nulovým počtem prvků
9. Zpracování pole struktur v jazyku C
10. Inicializace pole struktur v Pythonu
11. Výsledek získaný po spuštění skriptu
13. Funkce naprogramovaná v C, která akceptuje jednu formu dvourozměrných polí
14. Konstrukce dvourozměrného pole v Pythonu s předáním tohoto pole do céčkovské funkce
15. Výsledek získaný po spuštění skriptů
16. Dvourozměrná pole s proměnným počtem řádků
18. Repositář s demonstračními příklady
1. Předávání polí mezi skriptem napsaným v Pythonu a knihovnou naprogramovanou v jazyku C
Na úvodní dva články [1][2] o propojení skriptů či celých aplikací naprogramovaných v Pythonu s nativními knihovnami (typicky naprogramovanými v jazyku C) s využitím balíčku cffi dnes navážeme. Popíšeme si, jak se do (nativních) céčkovských funkcí předávají pole.
Obrázek 1: Podle Tiobe jsou Python a C v současnosti nejaktivněji používané programovací jazyky (i když je statistika pochopitelně značně zkreslena tím, že některé starší či proprietární jazyky jsou využívány spíše uzavřenějšími komunitami).
Připomeňme si, že pole jsou v jazyku C jediným datovým typem, který se předává odkazem (referencí, tedy přes ukazatel) a nikoli hodnotnou. Navíc lze předpokládat, že pole mohou být rozsáhlá, což znamená, že jejich reprezentace na straně Pythonu by v ideálním případě měla být shodná s céčkovou reprezentací, aby například nebylo nutné konvertovat miliony prvků (u skalárních datových typů, například int či float by to nepředstavovalo větší problém). Taktéž by bylo vhodné, aby se s prvky pole dalo na straně Pythonu vhodným způsobem pracovat, ideálně podobně, jako s prvky n-tic nebo seznamů. Všechny tyto požadavky knihovny cffi splňuje.
2. Funkce naprogramovaná v jazyku C, která akceptuje pole prvků typu float
V této kapitole si ukážeme, jak by mohla vypadat jednoduchá funkce naprogramovaná v jazyku C, která akceptuje pole prvků typu float. Pole v céčku jsou vlastně „pouhé“ paměťové bloky, v nichž jsou za sebou (tedy bez výplní) uloženy hodnoty jednotlivých prvků. Žádné další informace pole neobsahuje, což znamená, že například délku pole (tedy počet prvků) musíme předat ve zvláštním parametru, popř. mít v poli nějaký prvek se speciální hodnotou tvořící zarážku (tak je tomu u polí znaků = řetězců).
Z tohoto důvodu funkce, která bude tisknout obsah pole, bude mít následující prototyp (hlavičku):
void print_array(float array[], int items);
Samotná implementace funkce, která vytiskne obsah pole typu float[], může vypadat například takto:
#include <stdio.h> #include "array_printer.h" extern void print_array(float array[], int items) { int i; for (i=0; i<items; i++) { printf("array item %d = %f\n", i, array[i]); } }
3. Konstrukce pole na straně Pythonu s jeho předáním do céčkovské funkce
Nyní je nutné na straně Pythonu vytvořit pole s prvky typu float. Při použití knihovny cffi je to až překvapivě snadné, protože takové pole se vytvoří příkazem:
array = ffi.new("float[10]")
Další postup je snadný – načteme dynamicky linkovanou knihovnu, zaregistrujeme prototyp (hlavičku) volané céčkové funkce a následně tuto funkci zavoláme:
ffi.cdef(load_header("array_printer.h")) array = ffi.new("float[10]") printer.print_array(array, len(array))
Úplný tvar výsledného pythonovského skriptu vypadá následovně:
import pathlib from cffi import FFI ffi = FFI() def load_header(filename): directory = pathlib.Path().absolute() header = directory / filename with open(header) as fin: return fin.read() def load_library(library_name): return ffi.dlopen(library_name) ffi.cdef(load_header("array_printer.h")) array = ffi.new("float[10]") printer = load_library("libaprinter.so") printer.print_array(array, len(array))
4. Překlad a spuštění dnešního prvního demonstračního příkladu
Céčkovou část ze druhé kapitoly přeložíme do dynamicky linkované knihovny takto:
$ gcc -Wall -ansi -c -fPIC array_printer.c -o array_printer.o $ gcc -shared -Wl,-soname,libaprinter.so -o libaprinter.so array_printer.o
A skript naprogramovaný v Pythonu se spustí následovně:
$ export LD_LIBRARY_PATH=. $ python3 call_via_cffi.py
Po spuštění tohoto příkladu by se měl zobrazit obsah pole, což je v tomto případě deset nulových prvků:
array item 0 = 0.000000 array item 1 = 0.000000 array item 2 = 0.000000 array item 3 = 0.000000 array item 4 = 0.000000 array item 5 = 0.000000 array item 6 = 0.000000 array item 7 = 0.000000 array item 8 = 0.000000 array item 9 = 0.000000
5. Nastavení hodnot prvků pole
Prvky pole vytvořeného v prvním demonstračním příkladu byly nulové, což pravděpodobně není pro naprostou většinu aplikací ideální :-). Jak je však možné pole nejenom vytvořit, ale i inicializovat jeho prvky? Knihovna cffi, resp. přesněji řečeno objekty vytvořené funkcí ffi.new, nám nabízí hned několik způsobů. Nejjednodušší je s takovým objektem pracovat jako se seznamem, což je možné:
array = ffi.new("float[10]") for i in range(len(array)): array[i] = 1.0 / (i+1)
Interně je vše řešeno poměrně jednoduše, protože v Pythonu je možné v případě potřeby implementovat vlastní variantu operátoru indexování, což se v praxi provádí předefinováním metod __getitem__ a __setitem__. Díky tomu lze s objektem, který jsme pojmenovali array, pracovat tak, jakoby se skutečně jednalo o pole, i když jeho vnitřní struktura je poměrně složitá.
6. Výsledek při spuštění druhého skriptu
Celý skript, který volá nativní céčkovou funkci print_array, si upravíme tak, že prvky pole budeme postupně, v programové smyčce, modifikovat. Nová podoba skriptu bude vypadat takto:
import pathlib from cffi import FFI ffi = FFI() def load_header(filename): directory = pathlib.Path().absolute() header = directory / filename with open(header) as fin: return fin.read() def load_library(library_name): return ffi.dlopen(library_name) ffi.cdef(load_header("array_printer.h")) array = ffi.new("float[10]") for i in range(len(array)): array[i] = 1.0 / (i+1) printer = load_library("libaprinter.so") printer.print_array(array, len(array))
A výsledky vypsané céčkovskou funkcí dokazují, že vše pracuje korektně:
array item 0 = 1.000000 array item 1 = 0.500000 array item 2 = 0.333333 array item 3 = 0.250000 array item 4 = 0.200000 array item 5 = 0.166667 array item 6 = 0.142857 array item 7 = 0.125000 array item 8 = 0.111111 array item 9 = 0.100000
7. Inicializace prvků pole přímo v konstruktoru
Knihovna cffi navíc umožňuje inicializovat prvky pole přímo v konstruktoru ffi.new. V případě, že ve druhém parametru této funkce předáme seznam nebo n-tici, přiřadí se prvkům nově vznikajícího pole postupně jednotlivé prvky z této n-tice nebo seznamu:
array = ffi.new("float[10]", (1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 0)) ... array = ffi.new("float[10]", [1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 0])
Přitom ovšem není nutné předat stejný počet prvků, jako má mít výsledné pole. Například v dalším demonstračním příkladu se explicitně nastaví hodnoty prvních pěti prvků desetiprvkového pole (ostatní prvky budou mít výchozí hodnotu):
import pathlib from cffi import FFI ffi = FFI() def load_header(filename): directory = pathlib.Path().absolute() header = directory / filename with open(header) as fin: return fin.read() def load_library(library_name): return ffi.dlopen(library_name) ffi.cdef(load_header("array_printer.h")) array = ffi.new("float[10]", (1.1, 2.2, 3.3, 4.4, 5.5)) printer = load_library("libaprinter.so") printer.print_array(array, len(array))
Výsledek by nyní měl vypadat takto:
array item 0 = 1.100000 array item 1 = 2.200000 array item 2 = 3.300000 array item 3 = 4.400000 array item 4 = 5.500000 array item 5 = 0.000000 array item 6 = 0.000000 array item 7 = 0.000000 array item 8 = 0.000000 array item 9 = 0.000000
8. Mezní případ – pole s nulovým počtem prvků
Pro úplnost se ještě podívejme na to, zda je možné na straně Pythonu vytvořit pole s nulovým počtem prvků a následně toto pole předat do céčkovské funkce:
import pathlib from cffi import FFI ffi = FFI() def load_header(filename): directory = pathlib.Path().absolute() header = directory / filename with open(header) as fin: return fin.read() def load_library(library_name): return ffi.dlopen(library_name) ffi.cdef(load_header("array_printer.h")) array = ffi.new("float[0]") printer = load_library("libaprinter.so") printer.print_array(array, len(array))
Tento demonstrační příklad bude plně funkční a volaná céčkovská funkce nic nevypíše (ovšem ani nezhavaruje).
9. Zpracování pole struktur v jazyku C
V dalším textu si ukážeme, jakým způsobem se do funkcí naprogramovaných v jazyku C předávají pole, jejichž prvky jsou struktury (konkrétně uživatelské datové typy). Použijeme přitom strukturu vector_t reprezentující trojrozměrný vektor, s níž jsme se již seznámili minule:
typedef struct { double x; double y; double z; } vector_t;
Hlavička (prototyp) funkce, která bude akceptovat pole těchto struktur, může vypadat následovně:
void print_array(vector_t array[], int items);
A pro úplnost se ještě podívejme na jeden z možných způsobů implementace této funkce:
#include <stdio.h> #include "array_printer.h" extern void print_array(vector_t array[], int items) { int i; for (i=0; i<items; i++) { printf("array item %d = (%f, %f, %f)\n", i, array[i].x, array[i].y, array[i].z); } }
10. Inicializace pole struktur v Pythonu
Konstrukci pole s deseti prvky typu vector_t opět provedeme s využitím konstruktoru ffi.new. Potřebný příkaz bude vypadat následovně:
array = ffi.new("vector_t[10]")
Následně je již díky přetížení operátoru indexování možné přistupovat k jednotlivým prvkům, přičemž opět (rekurzivně) platí, že jednotlivé prvky se z pohledu Pythonu chovají tak, jakoby se jednalo o objekty s atributy x, y a z. Jednotlivé prvky tedy můžeme naplnit hodnotami:
for i in range(len(array)): array[i].x = i array[i].y = 2*i array[i].z = 1 / (1+i)
Úplný zdrojový kód takto upraveného skriptu bude vypadat následovně:
import pathlib from cffi import FFI ffi = FFI() def load_header(filename): directory = pathlib.Path().absolute() header = directory / filename with open(header) as fin: return fin.read() def load_library(library_name): return ffi.dlopen(library_name) ffi.cdef(load_header("array_printer.h")) array = ffi.new("vector_t[10]") for i in range(len(array)): array[i].x = i array[i].y = 2*i array[i].z = 1 / (1+i) printer = load_library("libaprinter.so") printer.print_array(array, len(array))
Následující kód je ovšem více idiomatický a ukazuje, že na straně Pythonu se se všemi hodnotami pracuje přes reference:
import pathlib from cffi import FFI ffi = FFI() def load_header(filename): directory = pathlib.Path().absolute() header = directory / filename with open(header) as fin: return fin.read() def load_library(library_name): return ffi.dlopen(library_name) ffi.cdef(load_header("array_printer.h")) array = ffi.new("vector_t[10]") for i, item in enumerate(array): item.x = i item.y = 2*i item.z = 1 / (1+i) printer = load_library("libaprinter.so") printer.print_array(array, len(array))
11. Výsledek získaný po spuštění skriptu
Po spuštění předchozího skriptu by se na terminál mělo vypsat těchto deset hodnot:
array item 0 = (0.000000, 0.000000, 1.000000) array item 1 = (1.000000, 2.000000, 0.500000) array item 2 = (2.000000, 4.000000, 0.333333) array item 3 = (3.000000, 6.000000, 0.250000) array item 4 = (4.000000, 8.000000, 0.200000) array item 5 = (5.000000, 10.000000, 0.166667) array item 6 = (6.000000, 12.000000, 0.142857) array item 7 = (7.000000, 14.000000, 0.125000) array item 8 = (8.000000, 16.000000, 0.111111) array item 9 = (9.000000, 18.000000, 0.100000)
12. Dvourozměrná pole
V této části článku se budeme zabývat problematikou konstrukce a předávání dvourozměrných polí z Pythonu do funkce naprogramované v jazyku C. Co se ovšem v kontextu jazyka C vlastně myslí pod pojmem „dvourozměrná pole“? Ve skutečnosti se může jednat o deklarace, které se od sebe odlišují jak způsobem uložení prvků, tak i způsobem jejich konstrukce (jak v C, tak i v Pythonu přes cffi).
Nejjednodušší, ovšem nejméně flexibilní jsou pole s předem známým počtem řádků a sloupců:
float a1[10][20];
Poněkud flexibilnější jsou (de facto) jednorozměrná pole obsahující ukazatele. Tyto ukazatele potom odkazují na jednotlivé řádky pole, které ovšem nemusí být stejně dlouhé (a pole tedy nebudou obdélníková). Navíc je nutné jednotlivé řádky explicitně alokovat:
float *a2[20];
Naopak můžeme deklarovat proměnnou, která je ukazatelem na pole deseti prvků. Nic nám však nebrání v tom, abychom alokovali celý blok paměti obsahující větší množství hodnot typu float[10], k nimž můžeme přistupovat jako k desetiprvkovým polím (výsledné dvourozměrné pole bude pravoúhlé):
float (*a3)[10];
A nakonec se někdy pod pojmem dvourozměrné pole skrývá „pouhý“ ukazatel na ukazatel na datový typ:
float **a4;
Toto je nejflexibilnější reprezentace pole, protože jak počet řádků, tak i počet sloupců je proměnný. Nevýhodou je, že kromě hodnot prvků se předává i vektor (jednorozměrné pole) ukazatelů na jednotlivé řádky.
13. Funkce naprogramovaná v C, která akceptuje jednu formu dvourozměrných polí
Podívejme se nyní na to, jak by mohla vypadat hlavička (prototyp) funkce, která akceptuje pole o libovolném počtu řádků, přičemž každý řádek bude obsahovat tři prvky:
#define COLUMNS 3
Bude se tedy jednat o obdélníkové pole:
void print_array(float array[][3], int rows);
Tuto funkci lze naprogramovat například následujícím způsobem:
#include <stdio.h> #include "array_printer.h" extern void print_array(float array[][COLUMNS], int rows) { int i, j; for (j=0; j<rows; j++) { float *row = array[j]; for (i=0; i<COLUMNS; i++) { printf("%3.2f ", row[i]); } putchar('\n'); } }
14. Konstrukce dvourozměrného pole v Pythonu s předáním tohoto pole do céčkovské funkce
Dvourozměrné pole, resp. přesněji řečeno jedna z možných variant tohoto pole zmíněná v předchozí kapitole, lze na straně Pythonu s využitím knihovny cffi zkonstruovat snadno:
array = ffi.new("float [10][3]")
Z pohledu Pythonu se jedná o jednorozměrnou strukturu, jejímiž prvky jsou trojice. To znamená, že první tři řádky tohoto pole můžeme naplnit například následujícím způsobem:
array[0] = (1,2,3) array[5] = (4,5,6) array[9] = (7,8,9)
Celý skript může vypadat následovně:
import pathlib from cffi import FFI ffi = FFI() def load_header(filename): directory = pathlib.Path().absolute() header = directory / filename with open(header) as fin: return fin.read() def load_library(library_name): return ffi.dlopen(library_name) ffi.cdef(load_header("array_printer.h")) array = ffi.new("float [10][3]") array[0] = (1,2,3) array[5] = (4,5,6) array[9] = (7,8,9) printer = load_library("libaprinter.so") printer.print_array(array, 10)
Můžeme ovšem naplnit i celé pole jediným přiřazením:
array = ((1,2,3), (4,5,6), (7,8,9), (0,0,0), (0,0,0), (1,2,3), (4,5,6), (7,8,9), (0,0,0), (0,0,0))
Opět si ukažme celý skript:
import pathlib from cffi import FFI ffi = FFI() def load_header(filename): directory = pathlib.Path().absolute() header = directory / filename with open(header) as fin: return fin.read() def load_library(library_name): return ffi.dlopen(library_name) ffi.cdef(load_header("array_printer.h")) array = ffi.new("float [10][3]") array = ((1,2,3), (4,5,6), (7,8,9), (0,0,0), (0,0,0), (1,2,3), (4,5,6), (7,8,9), (0,0,0), (0,0,0)) printer = load_library("libaprinter.so") printer.print_array(array, 10)
15. Výsledek získaný po spuštění skriptů
Pro úplnost se podívejme na výsledky běhu předchozích dvou skriptů. Nejprve skript, který naplní řádky 0, 5 a 9:
1.00 2.00 3.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 4.00 5.00 6.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 7.00 8.00 9.00
A následně si ukážeme výsledky běhu pythonovského skriptu, který naplní všechny řádky dvourozměrného pole:
1.00 2.00 3.00 4.00 5.00 6.00 7.00 8.00 9.00 0.00 0.00 0.00 0.00 0.00 0.00 1.00 2.00 3.00 4.00 5.00 6.00 7.00 8.00 9.00 0.00 0.00 0.00 0.00 0.00 0.00
16. Dvourozměrná pole s proměnným počtem řádků
V předchozím demonstračním příkladu jsme dvourozměrné pole konstruovali následujícím způsobem:
array = ffi.new("float [10][3]")
Víme již, že počet řádků může být při volání céčkovské funkce proměnný, takže by bylo dobré mít možnost konstrukce pole s proměnným počtem řádků, a to pochopitelně bez nutnosti „skládat“ řetězec posílaný konstruktoru. I to je v případě použití knihovny cffi možné:
array = ffi.new("float [][3]", rows)
Ukažme si tento koncept na následujícím příkladu:
import pathlib from cffi import FFI ffi = FFI() def load_header(filename): directory = pathlib.Path().absolute() header = directory / filename with open(header) as fin: return fin.read() def load_library(library_name): return ffi.dlopen(library_name) ffi.cdef(load_header("array_printer.h")) rows = 20 array = ffi.new("float [][3]", rows) array[0] = (1,2,3) array[rows//2] = (4,5,6) array[rows-1] = (7,8,9) printer = load_library("libaprinter.so") printer.print_array(array, rows)
Po spuštění takto upraveného skriptu získáme následující výsledky:
1.00 2.00 3.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 4.00 5.00 6.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 7.00 8.00 9.00
17. Obsah čtvrté části článku
Předávání struktur odkazem, popř. předávání polí (de facto taktéž odkazem) a řetězců do céčkovských funkcí má ještě jeden aspekt – střetává se zde svět virtuálního stroje Pythonu s automatickým správcem paměti se světem jazyka C, v němž kralují funkce typu malloc a free (a jejich různé varianty). Musíme tedy řešit i vlastnictví hodnot (ownership). A přesně tímto tématem se budeme zabývat příště.
18. Repositář s demonstračními příklady
Všechny Pythonovské skripty, které jsme si v dnešním i v obou předchozích článcích [1] [2] ukázali, naleznete na adrese https://github.com/tisnik/most-popular-python-libs. Následují odkazy na jednotlivé příklady (pro jejich spuštění je pochopitelně nutné mít nainstalovánu knihovnu cffi:
# | Příklad | Stručný popis | Adresa |
---|---|---|---|
1 | adder/adder.c | funkce psaná v C, která sečte své dva celočíselné parametry | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/adder/adder.c |
2 | adder/call_via_cffi1.py | zavolání céčkovské funkce přes cffi s korektními parametry | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/adder/call_via_cffi1.py |
3 | adder/call_via_cffi2.py | zavolání céčkovské funkce přes cffi s nekorektními parametry | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/adder/call_via_cffi2.py |
4 | adder/call_via_cffi3.py | zavolání céčkovské funkce přes cffi s nekorektními parametry | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/adder/call_via_cffi3.py |
5 | adder/call_via_cffi.sh | nastavení cest a spuštění všech tří předchozích Pythonovských skriptů | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/adder/call_via_cffi.sh |
6 | adder/call_via_ctypes1.py | zavolání céčkovské funkce přes ctypes s korektními parametry | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/adder/call_via_ctypes1.py |
7 | adder/call_via_ctypes2.py | zavolání céčkovské funkce přes ctypes s nekorektními parametry | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/adder/call_via_ctypes2.py |
8 | adder/call_via_ctypes3.py | zavolání céčkovské funkce přes ctypes s nekorektními parametry | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/adder/call_via_ctypes3.py |
9 | adder/call_via_ctypes.sh | nastavení cest a spuštění všech tří předchozích Pythonovských skriptů | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/adder/call_via_ctypes.sh |
10 | adder/make_library.sh | skript pro překlad céčkovské funkce a vytvoření dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/adder/make_library.sh |
11 | adder/clean.sh | skript pro smazání objektového souboru i dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/adder/clean.sh |
12 | greeter/greeter.c | funkce psaná v C, která na standardní výstup vytiskne řetězec | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter/greeter.c |
13 | greeter/call_via_cffi1.py | zavolání céčkovské funkce přes cffi s nekorektním parametrem | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter/call_via_cffi1.py |
14 | greeter/call_via_cffi2.py | zavolání céčkovské funkce přes cffi s korektním parametrem | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter/call_via_cffi2.py |
15 | greeter/call_via_cffi3.py | zavolání céčkovské funkce přes cffi s korektním parametrem | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter/call_via_cffi3.py |
16 | greeter/call_via_cffi.sh | nastavení cest a spuštění všech tří předchozích Pythonovských skriptů | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter/call_via_cffi.sh |
17 | greeter/call_via_ctypes1.py | zavolání céčkovské funkce přes ctypes s nekorektním parametrem | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter/call_via_ctypes1.py |
18 | greeter/call_via_ctypes2.py | zavolání céčkovské funkce přes ctypes s korektním parametrem | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter/call_via_ctypes2.py |
19 | greeter/call_via_ctypes3.py | zavolání céčkovské funkce přes ctypes s korektním parametrem | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter/call_via_ctypes3.py |
20 | greeter/call_via_ctypes.sh | nastavení cest a spuštění všech tří předchozích Pythonovských skriptů | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter/call_via_ctypes.sh |
21 | greeter/make_library.sh | skript pro překlad céčkovské funkce a vytvoření dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter/make_library.sh |
22 | greeter/clean.sh | skript pro smazání objektového souboru i dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter/clean.sh |
23 | swapper/swapper.c | céčkovská funkce prohazující obsah svých dvou parametrů předávaných referencí | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/swapper/swapper.c |
24 | swapper/call_via_cffi1.py | zavolání céčkovské knihovny z jazyka Python (korektní varianta) | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/swapper/call_via_cffi1.py |
25 | swapper/call_via_cffi2.py | zavolání céčkovské knihovny z jazyka Python (nekorektní varianta) | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/swapper/call_via_cffi2.py |
26 | swapper/call_via_cffi.sh | nastavení cest a spuštění Pythonovského skriptu | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/swapper/call_via_cffi.sh |
27 | swapper/make_library.sh | skript pro překlad céčkovské funkce a vytvoření dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/swapper/make_library.sh |
28 | swapper/clean.sh | skript pro smazání objektového souboru i dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/swapper/clean.sh |
29 | filler/filler.c | céčkovská funkce pro vyplnění části pole zadanou hodnotou | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/filler/filler.c |
30 | filler/call_via_cffi.py | zavolání céčkovské knihovny z jazyka Python | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/filler/call_via_cffi.py |
31 | filler/call_via_cffi.sh | nastavení cest a spuštění Pythonovského skriptu | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/filler/call_via_cffi.sh |
32 | filler/make_library.sh | skript pro překlad céčkovské funkce a vytvoření dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/filler/make_library.sh |
32 | filler/clean.sh | skript pro smazání objektového souboru i dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/filler/clean.sh |
33 | greeter_h/greeter.c | funkce psaná v C, která na standardní výstup vytiskne řetězec | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter_h/greeter.c |
34 | greeter_h/greeter.h | prototyp (předběžná deklarace) funkce greeter | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter_h/greeter.h |
35 | greeter_h/call_via_cffi4.py | zavolání céčkovské knihovny z jazyka Python | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter_h/call_via_cffi4.py |
36 | greeter_h/call_via_cffi.sh | nastavení cest a spuštění Pythonovského skriptu | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter_h/call_via_cffi.sh |
37 | greeter_h/make_library.sh | skript pro překlad céčkovské funkce a vytvoření dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter_h/make_library.sh |
38 | greeter_h/clean.sh | skript pro smazání objektového souboru i dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter_h/clean.sh |
39 | greeter_h2/greeter.c | funkce psaná v C, která na standardní výstup vytiskne řetězec | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter_h2/greeter.c |
40 | greeter_h2/greeter.h | prototyp (předběžná deklarace) funkce greeter obalená v testu na existenci symbolu/makra | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter_h2/greeter.h |
41 | greeter_h2/call_via_cffi5.py | zavolání céčkovské knihovny z jazyka Python | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter_h2/call_via_cffi5.py |
42 | greeter_h2/call_via_cffi.sh | nastavení cest a spuštění Pythonovského skriptu | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter_h2/call_via_cffi.sh |
43 | greeter_h2/make_library.sh | skript pro překlad céčkovské funkce a vytvoření dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter_h2/make_library.sh |
44 | greeter_h2/clean.sh | skript pro smazání objektového souboru i dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter_h2/clean.sh |
45 | greeter_h3/greeter.c | funkce psaná v C, která na standardní výstup vytiskne řetězec | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter_h3/greeter.c |
46 | greeter_h3/greeter.h | test na existenci symbolu/makra, pokud makro neexistuje, provede se vložení dalšího souboru | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter_h3/greeter.h |
47 | greeter_h3/_greeter.h | prototyp (předběžná deklarace) funkce greeter bez dalších informací | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter_h3/_greeter.h |
48 | greeter_h3/call_via_cffi5.py | zavolání céčkovské funkce z knihovny z jazyka Python | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter_h3/call_via_cffi5.py |
49 | greeter_h3/call_via_cffi.sh | nastavení cest a spuštění Pythonovského skriptu | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter_h3/call_via_cffi.sh |
50 | greeter_h3/make_library.sh | skript pro překlad céčkovské funkce a vytvoření dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter_h3/make_library.sh |
51 | greeter_h3/clean.sh | skript pro smazání objektového souboru i dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter_h3/clean.sh |
52 | greeter_build/greeter.c | funkce psaná v C, která na standardní výstup vytiskne řetězec | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter_build/greeter.c |
53 | greeter_build/greeter.h | prototyp (předběžná deklarace) funkce greeter bez dalších informací | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter_build/greeter.h |
54 | greeter_build/call_via_cffi7.py | skript pro překlad céčkovské funkce, vytvoření dynamicky linkované knihovny a zavolání funkce z této knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter_build/call_via_cffi7.py |
55 | greeter_build/clean.sh | skript pro smazání objektového souboru i dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/greeter_build/clean.sh |
56 | vector_printer/vector_printer.c | funkce psaná v C, která akceptuje jako svůj parametr strukturu | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/vector_printer/vector_printer.c |
57 | vector_printer/vector_printer.h | prototyp (předběžná deklarace) funkce print_vector bez dalších informací | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/vector_printer/vector_printer.h |
58 | vector_printer/call_via_cffi.sh | zavolání céčkovské funkce z knihovny z jazyka Python | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/vector_printer/call_via_cffi.sh |
59 | vector_printer/call_via_cffi.py | nastavení cest a spuštění Pythonovského skriptu | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/vector_printer/call_via_cffi.py |
60 | vector_printer/make_library.sh | skript pro překlad céčkovské funkce a vytvoření dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/vector_printer/make_library.sh |
61 | vector_printer/clean.sh | skript pro smazání objektového souboru i dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/vector_printer/clean.sh |
62 | vector_printer2/vector_printer.c | funkce psaná v C, která akceptuje jako svůj parametr ukazatel na strukturu | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/vector_printer2/vector_printer.c |
63 | vector_printer2/vector_printer.h | prototyp (předběžná deklarace) funkce print_vector bez dalších informací | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/vector_printer2/vector_printer.h |
64 | vector_printer2/call_via_cffi.sh | zavolání céčkovské funkce z knihovny z jazyka Python | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/vector_printer2/call_via_cffi.sh |
65 | vector_printer2/call_via_cffi.py | nastavení cest a spuštění Pythonovského skriptu | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/vector_printer2/call_via_cffi.py |
66 | vector_printer2/make_library.sh | skript pro překlad céčkovské funkce a vytvoření dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/vector_printer2/make_library.sh |
67 | vector_printer2/clean.sh | skript pro smazání objektového souboru i dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/vector_printer2/clean.sh |
68 | array_printer1/array_printer.c | funkce naprogramovaná v C, která akceptuje pole s prvky typu float | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer1/array_printer.c |
69 | array_printer1/array_printer.h | prototyp (předběžná deklarace) funkce print_array bez dalších informací | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer1/array_printer.h |
70 | array_printer1/call_via_cffi.py | zavolání céčkovské funkce z knihovny z jazyka Python | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer1/call_via_cffi.sh |
71 | array_printer1/call_via_cffi.sh | nastavení cest a spuštění Pythonovského skriptu | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer1/call_via_cffi.py |
72 | array_printer1/make_library.sh | skript pro překlad céčkovské funkce a vytvoření dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer1/make_library.sh |
73 | array_printer1/clean.sh | skript pro smazání objektového souboru i dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer1/clean.sh |
74 | array_printer2/array_printer.c | funkce naprogramovaná v C, která akceptuje pole s prvky typu float | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer2/array_printer.c |
75 | array_printer2/array_printer.h | prototyp (předběžná deklarace) funkce print_array bez dalších informací | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer2/array_printer.h |
76 | array_printer2/call_via_cffi.py | zavolání céčkovské funkce z knihovny z jazyka Python | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer2/call_via_cffi.sh |
77 | array_printer2/call_via_cffi.sh | nastavení cest a spuštění Pythonovského skriptu | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer2/call_via_cffi.py |
78 | array_printer2/make_library.sh | skript pro překlad céčkovské funkce a vytvoření dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer2/make_library.sh |
79 | array_printer2/clean.sh | skript pro smazání objektového souboru i dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer2/clean.sh |
80 | array_printer3/array_printer.c | funkce naprogramovaná v C, která akceptuje pole s prvky typu float | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer3/array_printer.c |
81 | array_printer3/array_printer.h | prototyp (předběžná deklarace) funkce print_array bez dalších informací | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer3/array_printer.h |
82 | array_printer3/call_via_cffi.py | zavolání céčkovské funkce z knihovny z jazyka Python | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer3/call_via_cffi.sh |
83 | array_printer3/call_via_cffi.sh | nastavení cest a spuštění Pythonovského skriptu | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer3/call_via_cffi.py |
84 | array_printer3/make_library.sh | skript pro překlad céčkovské funkce a vytvoření dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer3/make_library.sh |
85 | array_printer3/clean.sh | skript pro smazání objektového souboru i dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer3/clean.sh |
86 | array_printer4/array_printer.c | funkce naprogramovaná v C, která akceptuje pole s prvky typu float | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer4/array_printer.c |
87 | array_printer4/array_printer.h | prototyp (předběžná deklarace) funkce print_array bez dalších informací | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer4/array_printer.h |
88 | array_printer4/call_via_cffi.py | zavolání céčkovské funkce z knihovny z jazyka Python | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer4/call_via_cffi.sh |
89 | array_printer4/call_via_cffi.sh | nastavení cest a spuštění Pythonovského skriptu | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer4/call_via_cffi.py |
90 | array_printer4/make_library.sh | skript pro překlad céčkovské funkce a vytvoření dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer4/make_library.sh |
91 | array_printer4/clean.sh | skript pro smazání objektového souboru i dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer4/clean.sh |
92 | array_printer5/array_printer.c | funkce naprogramovaná v C, která akceptuje pole s prvky typu vector_t | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer5/array_printer.c |
93 | array_printer5/array_printer.h | prototyp (předběžná deklarace) funkce print_array bez dalších informací | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer5/array_printer.h |
94 | array_printer5/call_via_cffi.py | zavolání céčkovské funkce z knihovny z jazyka Python | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer5/call_via_cffi.sh |
95 | array_printer5/call_via_cffi.sh | nastavení cest a spuštění Pythonovského skriptu | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer5/call_via_cffi.py |
96 | array_printer5/make_library.sh | skript pro překlad céčkovské funkce a vytvoření dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer5/make_library.sh |
97 | array_printer5/clean.sh | skript pro smazání objektového souboru i dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer5/clean.sh |
92 | array_printer6/array_printer.c | funkce naprogramovaná v C, která akceptuje dvourozměrné pole s prvky typu float | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer6/array_printer.c |
93 | array_printer6/array_printer.h | prototyp (předběžná deklarace) funkce print_array bez dalších informací | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer6/array_printer.h |
94 | array_printer6/call_via_cffi.py | zavolání céčkovské funkce z knihovny z jazyka Python | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer6/call_via_cffi.sh |
95 | array_printer6/call_via_cffi.sh | nastavení cest a spuštění Pythonovského skriptu | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer6/call_via_cffi.py |
96 | array_printer6/make_library.sh | skript pro překlad céčkovské funkce a vytvoření dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer6/make_library.sh |
97 | array_printer6/clean.sh | skript pro smazání objektového souboru i dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer6/clean.sh |
98 | array_printer7/array_printer.c | funkce naprogramovaná v C, která akceptuje dvourozměrné pole s prvky typu float | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer7/array_printer.c |
99 | array_printer7/array_printer.h | prototyp (předběžná deklarace) funkce print_array bez dalších informací | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer7/array_printer.h |
100 | array_printer7/call_via_cffi.py | zavolání céčkovské funkce z knihovny z jazyka Python | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer7/call_via_cffi.sh |
101 | array_printer7/call_via_cffi.sh | nastavení cest a spuštění Pythonovského skriptu | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer7/call_via_cffi.py |
102 | array_printer7/make_library.sh | skript pro překlad céčkovské funkce a vytvoření dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer7/make_library.sh |
103 | array_printer7/clean.sh | skript pro smazání objektového souboru i dynamicky linkované knihovny | https://github.com/tisnik/most-popular-python-libs/blob/master/cffi/array_printer7/clean.sh |
19. Odkazy na Internetu
- TIOBE Index for May 2023
https://www.tiobe.com/tiobe-index/ - PYPL PopularitY of Programming Language
https://pypl.github.io/PYPL.html - CFFI documentation
https://cffi.readthedocs.io/en/latest/ - cffi 1.15.1 na PyPi
https://pypi.org/project/cffi/ - Python Bindings: Calling C or C++ From Python
https://realpython.com/python-bindings-overview/ - Interfacing with C/C++ Libraries
https://docs.python-guide.org/scenarios/clibs/ - Cython, pybind11, cffi – which tool should you choose?
http://blog.behnel.de/posts/cython-pybind11-cffi-which-tool-to-choose.html - Python FFI with ctypes and cffi
https://eli.thegreenplace.net/2013/03/09/python-ffi-with-ctypes-and-cffi - Propojení Go s Pythonem s využitím cgo a ctypes
https://www.root.cz/clanky/propojeni-go-s-pythonem-s-vyuzitim-cgo-a-ctypes/ - Propojení Go s Pythonem s využitím cgo a ctypes (2. část)
https://www.root.cz/clanky/propojeni-go-s-pythonem-s-vyuzitim-cgo-a-ctypes-2-cast/ - Programovací jazyk Rust: použití FFI pro volání funkcí z nativních knihoven
https://www.root.cz/clanky/programovaci-jazyk-rust-pouziti-ffi-pro-volani-funkci-z-nativnich-knihoven/ - Programovací jazyk Rust: použití FFI při předávání struktur
https://www.root.cz/clanky/programovaci-jazyk-rust-pouziti-ffi-pri-predavani-struktur/ - Programovací jazyk Rust: použití FFI pro volání funkcí z nativních knihoven (2. část)
https://www.root.cz/clanky/programovaci-jazyk-rust-pouziti-ffi-pro-volani-funkci-z-nativnich-knihoven-2-cast/ - Dynamic-link library
https://en.wikipedia.org/wiki/Dynamic-link_library - Úvod do jazyka C: Deklarace funkcí
https://www.fi.muni.cz/usr/jkucera/pb071/sl5.htm - Using standard library headers with CFFI
https://stackoverflow.com/questions/57481873/using-standard-library-headers-with-cffi - Preparing and Distributing modules
https://cffi.readthedocs.io/en/latest/cdef.html - C Arrays
https://www.programiz.com/c-programming/c-arrays - C Arrays
https://www.w3schools.com/c/c_arrays.php - Array of Structures in C
https://overiq.com/c-programming-101/array-of-structures-in-c/#google_vignette