/*
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
$Id: Extest.c,v 1.5 2000/07/02 00:10:09 wesc Exp $

Extest.c - Python extension module example

created 00/02/23 by wesc, (c)2000 Cyberweb Consulting

after creating this source file, copying Modules/Makefile.pre.in,
creating Setup, and running 'make -f Makefile.pre.in boot' to
create the Makefile, running make results in the file...

compiled on Solaris using:
    % gcc -g -O2 -I/usr/local/include/python1.5 -DHAVE_CONFIG_H -c ./Extest.c
    % ld -G Extest.o -o Extest.so

compiled on SuSE Linux 6.3 using:
    gcc -fpic -O2 -m486 -fno-strength-reduce -I/usr/include/python1.5 -DHAVE_CONFIG_H -c ./Extest.c
    gcc -shared Extest.o -o Extest.so

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
*/

/* C header files */
#include <stdio.h>
#include <stdlib.h>

/* fac() -- Calculates 'n' factorial or n! rescursively        */
int fac(int n) {

    if (n < 2) return(1);        /* quit when value is 1        */
    return ((n)*fac(n-1));        /* recursive one level        */
}


/* reverse() -- Reverses a string in place via pointers        */
char *reverse(char *s) {

    register char t,                /* declare counters        */
                *p = s,
                *q = (s + (strlen(s) - 1));

    while (s && (p < q)) {        /* swap till halfway        */
        t = *p;
        *p++ = *q;
        *q-- = t;
    }
    return(s);                        /* return string anyway        */
}

/* void main() {                /* main() w/o Python        */
void test() {
    char s[BUFSIZ];
    printf("4! == %d\n", fac(4));
    printf("8! == %d\n", fac(8));
    printf("12! == %d\n", fac(12));
    strcpy(s, "abcdef");
    printf("reversing 'abcdef', we get '%s'\n", reverse(s));
    strcpy(s, "madam");
    printf("reversing 'madam', we get '%s'\n", reverse(s));
}


/* Extest module stuff                                        */

#include "Python.h"                /* add Python.h header        */

/* Python wrapper for fac()... returns factorial        */
static PyObject *
Extest_fac(PyObject *self, PyObject *args) {

    int num;                        /* holds incoming value        */

    if (!PyArg_ParseTuple(args, "i", &num)) return NULL;
    return (PyObject*)Py_BuildValue("i", fac(num));
}


/* Python wrapper for reverse()...
   returns regular *and* reversed strings as a tuple        */
static PyObject *
Extest_doppel(PyObject *self, PyObject *args) {
    char *orig_str;                /* incoming str        */
    char *dupe_str;                /* reversed str        */
    PyObject* retval;        /* return value        */

    if (!PyArg_ParseTuple(args, "s", &orig_str)) return NULL;
    retval = (PyObject*)Py_BuildValue("ss", orig_str, dupe_str=reverse(strdup(orig_str)));
    free(dupe_str);
    return retval;
}


/* Python wrapper for test()/main() */
static PyObject *
Extest_test(PyObject *self, PyObject *args) {
    test();
    return (PyObject*)Py_BuildValue("");
}


/* Define Python module functions/methods                */
static PyMethodDef
ExtestMethods[] = {
    { "fac", Extest_fac, METH_VARARGS },
    { "doppel", Extest_doppel, METH_VARARGS },
    { "test", Extest_test, METH_VARARGS },
    { NULL, NULL },
};


/* Initialize Extest Python module                        */
void initExtest () {
    Py_InitModule("Extest", ExtestMethods);
}

