Hlavní navigace

SWIG - Úvod

Jakub Matys

Popularita vysokoúrovňových interpretovaných jazyků, jako je Python, Ruby nebo Java, stále roste. Se zvyšující se výkoností počítačů se zlepšuje i rychlost programů. Pokud však stále není dostačující, můžeme to řešit kompilací určitých rizikových modulů do binární podoby. Pomoci by nám měl projekt zvaný SWIG.

Nespornou výhodou interpretovaných skriptovacích jazyků je jejich přenositelnost a jednoduchost, což z nich činí mocné nástroje. Protože je však jejich kód prováděn interpretem z textového souboru nebo bajtového kódu, nedosahují takových výkonů jako překládané programy. Řešením tohoto „neduhu“ může být dynamické nahrávání binárních knihoven jako modulů jazyka. Při psaní modulu musíte řešit dvě věci – samotnou logiku rozšíření a rozhraní mezi modulem a interpretem. Můžeme se podívat na příklad modulu jazyka Python.

Samotná logika modulu:

/* Vypocet nejvetsiho spolecneho delitele dvou kladnych celych cisel x a y */
int gcd(int x, int y) {
    int g;
    g = y;
    while (x > 0) {
        g = x;
        x = y % x;
        y = g;
    }
    return g;
}

/* Vytisk urcitych dat */
void print_data(char *name, char *email, char *phone) {
    printf("Name    : %s\n", name);
    printf("Email   : %s\n", email);
    printf("Phone   : %s\n", phone);
} 

Rozhraní modulu:

/* modul "spam" */
/* Zahrnuti Pythonskeho C API */
#include "Python.h"

/* Vnejsi deklarace */
extern int gcd(int,int);
extern void print_data(char *, char *, char *);

/* Wrapper pro funkci gcd() */
PyObject *spam_gcd(PyObject *self, PyObject *args) {
    int x, y, g;
    /* Ziskani pythonskych argumentu */
    if (!PyArg_ParseTuple(args, "ii", &#x, &y)) {
        return NULL;
    }
    /* Zavolani funkce jazyka C */
    g = gcd(x, y);
    return Py_BuildValue("i", g);
}

/* Wrapper pro funkci print_data() */
PyObject *spam_print_data(PyObject *self, PyObject *args, PyObject *kwargs) {
    char *name = "None";
    char *email = "None";
    char *phone = "None";
    static char *argnames[] = {"name", "email", "phone", NULL};

    /* Ziskani pythonskych argumentu */
    if (!PyArg_ParseTupleAndKeywords(args, kwargs,"|sss", argnames, &name, &email, &phone)) {
        return NULL;
    }
    /* Zavolani funkce jazyka C */
    print_data(name, email, phone);
    return Py_BuildValue("");
}

/* Tabulka metody zobrazujici nazvy na wrappery */
static PyMethodDef spammethods[] = {
    {"gcd", spam_gcd, METH_VARARGS},
    {"print_data", spam_print_data, METH_VARARGS | METH_KEYWORDS },
    {NULL, NULL}
};
/* Funkce pro inicializaci modulu */
initspam(void) {
    Py_InitModule("spam", spammethods);
} 

Tento kousek kódu byl převzat z knihy „Python: Referenční programátorská příručka“ od Davida M. Beazleyho, který je též autorem SWIGu.

Takovéto řešení je poněkud těžkopádné, nejenže musíte vymyslet samotný modul, ale musíte ho ručně „spojit“ s interpretem. Tento problém přichází řešit projekt zvaný SWIG (Simplified Wrapper and Interface Generator). Tento program/knihovna umožňuje rozšiřování a zapouzdřování jazyků, jako jsou: Allegro CL, C#, Chicken, Guile, Java, Modula-3, Mzscheme, OCAML, Perl, PHP, Python, Ruby a Tcl.

SWIG byl poprvé použit v roce 1995 v Theoretical Physic Division Los Angeleské National Laboratory pro vytvoření uživatelského rozhraní k simulačnímu programu superpočítače. Vědci velmi často měnili kód simulace, použili proto skriptovací jazyk. Samotný simulační program musel být kvůli rychlosti napsán v překládaném jazyce. SWIG byl tedy použit k „provázání“ těchto jazyků.

Aktuální verze je 1.3.25 a můžete ji stáhnout z prdownloads­.sourceforge.net/swig/sw­ig-1.3.25.tar.gz?dow­nload. Kompilace se provádí klasickým „trojhmatem“ ./configure && make && make install. Skriptu configure můžete předat argumenty, kterými vypnete anebo zapnete podporované jazyky (samozřejmě můžete měnit ještě další volby).

A jak tedy SWIG pracuje? Máme vytvořený zdrojový kód modulu (viz např. první příklad) a soubor rozhraní SWIGu (SWIG interface file), který má příponu  i.

// spam.i
%module spam

int gcd(int,int);
void print_data(char *, char *, char *); 

Příkazem swig -python spam.i vytvoříme wrappery modulu. A můžeme překládat …

# swig -python spam.i
# gcc -c spam.c spam_wrap.c -I/usr/include/python2.3/ -I/usr/lib/python2.3/config/
# ld -shared spam.o spam_wrap.o -o spam.so 

Máme za sebou první modul Pythonu, příště si povíme ještě o dalších možnostech nástroje SWIG.

Našli jste v článku chybu?
14. 7. 2005 7:56
Teda, nedá mi to a trošku si rýpnu: Basic na osmibitech je tedy taky kompilovaný? Protože v operační paměti samozřejmě není uložen přímo zdroják (je to moc objemné a interpretace by byla neskutečně pomalá), ale pouze tokeny jednotlivých příkazů. "Kompilace" se provádí pro každý řádek po jeho odentrování (resp. v té době ještě "odreturnování").
9. 11. 2005 10:53
Myslel jsem, že Smalltalk má JIT od konce osmdesátých let... :-D High Performance Smalltalk, VM ve VisualWorks, dříve ObjectWorks nebo ObjectStudio nebo tak nějak, pokud se nepletu.