Hlavní navigace

Propojení Pythonu s nativními knihovnami s využitím balíčku cffi (3)

8. 6. 2023
Doba čtení: 30 minut

Sdílet

 Autor: Python
Ve třetí části článku o propojení Pythonu s nativními knihovnami s využitím balíčku cffi se budeme zabývat tím, jakým způsobem je možné do funkce naprogramované v jazyku C předat pole s prvky různých typů.

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

12. Dvourozměrná pole

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ů

17. Obsah čtvrté části článku

18. Repositář s demonstračními příklady

19. Odkazy na Internetu

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);
Poznámka: připomeňme si, že pole se v céčku předává odkazem, nikoli hodnotou.

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]")
Poznámka: ve skutečnosti se nevrátí přímo céčkové pole, ale objekt, který toto pole i s dalšími informacemi obsahuje. Jak uvidíme dále, je díky použití tohoto přístupu snadné s obsahem pole pracovat jak na straně Pythonu, tak i na straně programovacího jazyka C.

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))
Poznámka: povšimněte si, že díky tomu, že array je pythonovským objektem, můžeme délku pole získat snadno standardní funkcí len.

Ú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.

Poznámka: z mnoha důvodů může být více než výhodné skutečná dvourozměrná pole nepoužívat a zaměřit se na strukturu známou pod pojmem n-rozměrná pole. V této struktuře jsou prvky uloženy za sebou, ovšem navíc obsahuje i metadata o velikosti jednotlivých dimenzí. Poměrně dobrým a především rozšířeným příkladem implementace je ndarray z knihovny Numpy (s nímž knihovna cffi dokáže prakticky bez problémů pracovat).

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');
    }
}
Poznámka: povšimněte si, že počet sloupců musí být v tomto případě neměnný. Pokud se má měnit jak počet řádků, tak i počet sloupců, je nutné použít jiný „typ“ dvourozměrného pole.

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)
Poznámka: povšimněte si, že se naplnily řádky s indexy 0, 5 a 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:

root_podpora

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/ca­ll_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/ca­ll_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/ca­ll_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/ca­ll_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/ca­ll_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/ca­ll_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/ca­ll_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/ca­ll_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/ma­ke_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/gre­eter/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/gre­eter/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/gre­eter/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/gre­eter/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/gre­eter/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/gre­eter/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/gre­eter/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/gre­eter/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/gre­eter/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/gre­eter/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/swap­per/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/swap­per/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/swap­per/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/swap­per/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/swap­per/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/ca­ll_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/ca­ll_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/ma­ke_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/gre­eter_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/gre­eter_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/gre­eter_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/gre­eter_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/gre­eter_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/gre­eter_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/gre­eter_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/gre­eter_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/gre­eter_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/gre­eter_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/gre­eter_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/gre­eter_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/gre­eter_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/gre­eter_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/gre­eter_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/gre­eter_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/gre­eter_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/gre­eter_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/gre­eter_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/gre­eter_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/gre­eter_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/gre­eter_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/gre­eter_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/vec­tor_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/vec­tor_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/vec­tor_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/vec­tor_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/vec­tor_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/vec­tor_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/vec­tor_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/vec­tor_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/vec­tor_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/vec­tor_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/vec­tor_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/vec­tor_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_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/arra­y_printer7/clean.sh

19. Odkazy na Internetu

  1. TIOBE Index for May 2023
    https://www.tiobe.com/tiobe-index/
  2. PYPL PopularitY of Programming Language
    https://pypl.github.io/PYPL.html
  3. CFFI documentation
    https://cffi.readthedocs.i­o/en/latest/
  4. cffi 1.15.1 na PyPi
    https://pypi.org/project/cffi/
  5. Python Bindings: Calling C or C++ From Python
    https://realpython.com/python-bindings-overview/
  6. Interfacing with C/C++ Libraries
    https://docs.python-guide.org/scenarios/clibs/
  7. Cython, pybind11, cffi – which tool should you choose?
    http://blog.behnel.de/posts/cython-pybind11-cffi-which-tool-to-choose.html
  8. Python FFI with ctypes and cffi
    https://eli.thegreenplace­.net/2013/03/09/python-ffi-with-ctypes-and-cffi
  9. 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/
  10. 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/
  11. Programovací jazyk Rust: použití FFI pro volání funkcí z nativních knihoven
    https://www.root.cz/clanky/pro­gramovaci-jazyk-rust-pouziti-ffi-pro-volani-funkci-z-nativnich-knihoven/
  12. Programovací jazyk Rust: použití FFI při předávání struktur
    https://www.root.cz/clanky/pro­gramovaci-jazyk-rust-pouziti-ffi-pri-predavani-struktur/
  13. Programovací jazyk Rust: použití FFI pro volání funkcí z nativních knihoven (2. část)
    https://www.root.cz/clanky/pro­gramovaci-jazyk-rust-pouziti-ffi-pro-volani-funkci-z-nativnich-knihoven-2-cast/
  14. Dynamic-link library
    https://en.wikipedia.org/wiki/Dynamic-link_library
  15. Úvod do jazyka C: Deklarace funkcí
    https://www.fi.muni.cz/us­r/jkucera/pb071/sl5.htm
  16. Using standard library headers with CFFI
    https://stackoverflow.com/qu­estions/57481873/using-standard-library-headers-with-cffi
  17. Preparing and Distributing modules
    https://cffi.readthedocs.i­o/en/latest/cdef.html
  18. C Arrays
    https://www.programiz.com/c-programming/c-arrays
  19. C Arrays
    https://www.w3schools.com/c/c_a­rrays.php
  20. Array of Structures in C
    https://overiq.com/c-programming-101/array-of-structures-in-c/#google_vignette

Byl pro vás článek přínosný?

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.