Výroba sdílených knihoven (shared libraries) a jejich následné použití z Python'u se poměrně značně liší podle jazyka, ve kterém danou knihovnu napíšete. V dalším upozorním na specifické vlastnosti konkrétních jazyků:
PS: Za pomoc s kódy pro C++ a vysvětlení chování překladačů děkuji Míru Šimkovi.
S knihovnami v jazyce C je práce zdaleka nejsnažší, protože ty jsou přímo podporovány modulem ctypes. Ale i tak máme k dispozici několik různých scénářů:
gcc [-O] -shared mylib.c -o mylib.dll
exportovány automaticky všechny (a přímo pod svými jmény).
__declspec(dllexport)
, budou exportovány pouze tyto.
__attribute__((visibility("default")))
, ale musíte změnit způsob překladu na gcc -fvisibility=hidden -shared mylib.c -o mylib.so
.
Příklad pro gcc a základní typ int
:
S knihovnami v jazyce C++, je práce téměř stejná jako s knihovnami v jazyce C – víceméně se jen liší způsob exportu jmen funkcí. Při překladu pomocí g++ [-O] -shared mylib.cc -o mylib.dll
platí:
static
jsou privátní (lokální) pro danou knihovnu a neexportují se.
extern "C"
jsou na knihovně viditelné pod svým skutečným jménem.
PS: V MS Visual C++ je to trošku jinak – neexportuje se nic, pokud tak nepřikážeme. Přitom funkce označené _declspec(dllexport)
vyjdou ven zamanglované, funkce označené extern "C" _declspec(dllexport)
pak nezamanglované.
Příklad pro g++ a základní typ int
:
Pomineme-li „oblíbené“ trable s mapováním necéčkovských typů, rozpadá se použití sdílených knihoven v jazyce D na tři základní případy:
Déčko v mnoha ohledech kopíruje dobré vlastnosti Céčka a ty méně dobré se snaží napravit. V nejjednodušším možném případě exportu sdílené knihovny za pomoci prefixu export
..
..vygeneruje Déčko sympaticky malou knihovnu, avšak jména funkcí jsou přístupná pod podtržítkem a ještě navíc zamanglovaná.
O fous komplexnější signatura (signature) funkcí a stejný způsob překladu..
..způsobí, že knihovna zůstane stejně sympaticky maličká a jména funkcí již nebudou zamanglovaná, stále se však před nimi bude nacházet podtržítko.
Pokud budete chtít volat funkce přímo pod jejich originálními názvy a hlavně to celé udělat pěkně čistě a blbuvzdorně, musíte k vlastnímu zdrojovému kódu mylib.d..
..přidat definiční soubor exportu mylib.def,
..vhodný „wrapper“ dll.d..
..a změnit způsob kompilace:
Ukažme si případ číslo 2 – jméno s podtržítkem – pro triviální typ int
:
Knihovny v jazyce Haskell se velmi podobají poslednímu typu knihoven jazyka D – pro úspěšné volání funkcí ze sdílené knihovny musíme nejen zdrojový kód v Haskellu vybavit seznamem exportovaných funkcí, ale také doobalit „wrapperem“ z Céčka. Navíc nemají k dispozici céčkovskou „zkratku“ pro těch několik základních typů, takže pro všechny funkce budete muset před jejich voláním v Python'u nadefinovat typy argumentů a návratové hodnoty.
Celkově tedy musíte připravit vlastní zdrojový kód v Haskell'u mylib.hs,
..přidat pomocnou knihovnu v Céčku StartEnd.c
..a celé to vybuildit pomocí:
Jak se s výslednou knihovnou zachází, viz následující slajd.
Příklad pro GHC 7.6.3:
print mylib.hello('hello')
, protože řetězec v něm byla vlastně sekvence bajtů (v případě potřeby vyhodnocená ve výchozím kódování), pro Python 3.x musíte z řetězce sekvenci bajtů (v příslušném kódování) vyrobit sami. Jestli jdou unicodové řetězce rovnou předat nějak rozumně, zatím nevím…
Knihovny v jazyce Ada se narozdíl od Déčka a Haskellu nechají přeložit velmi snadno – stačí požadované funkce označit jako exported. Ale jejich volání z Python'u je třeba doplnit o „spravovací“ nastavení před použitím knihovny a po ukončení práce s ní. Při zavedení knihovny jako
Jinak jsou ale funkce z adovského modulu přístupné přímo pod definovanými jmény a žádné překvapení nás nečeká.
Příklad podle http://www.inspirel.com/articles/Ada_Python_Binding.html:
Pro balíček..
..a jeho implementaci..
..dostaneme při překladu pomocí gnatmake -Pada_module
s následujícím gnat-skriptem..
..tento výsledek: