/* C_test.txt with lots of comments Newbie Documentation" for C extension, comments? Hi and thanks to all of you who gave very helpful suggestions. I've been successful in builing a (very) simple example C extension module for Python in Codewarrior. With apologies in advance for the length of this post I have included "documentation" on that process below for your perusal. It works and I think what I have said is _mostly_ right, but I would like comments back from anyone who can point out mistakes, possible additions, things to delete, etc. In particular, I am not at all sure if what I say about the naming of things is correct. I view this as a possible candidate for the Python FAQ to help newbies like me get started in this process. Things like merging two languages always include a number of nitty-gritty-gothca facts that one often finds by trial and error or, in my case, with generous help from people in this SIG. I think any newbie, even if non-Mac, could be helped by what you all suggested and I found out. Anyway, comments welcome and thanks, again. -- Lou Pecora In the following I develop two C functions for import to Python to calculate the square of a number and the square root of a number. Nothing fancy. These are just to get the basics understood. The C extension/module will actually be a shared library. I assume you are familiar with Codewarrior Projects and its settings in general, but even if you're using another compiler many of the items below will be true generally and the information should help you. You should read the Extensions documention to understand the use and necessity of some of the Python functions and defintions used and their argument formatting. Note the square root function (squareroot) is a Python function, i.e. it will show up in Python when C_test is imported, but the function it calls (mysqrt) is just a C function used within this module. It will NOT show up in Python. 1. Source code example and comments on them, including the naming of things 2. Codewarrior Project setting (those that matter) 3. Importing your C functions (extensions) into Python I develop two C functions. One to take a float number, square it and return a Python float number as the result and one to take a float number, take its square root and return a Python float number as the result. */ /* C_test.h Header to test of C modules for Python */ #include /* function prototypes */ void initC_test(); static PyObject *square(PyObject *self, PyObject *args); static PyObject *squareroot(PyObject *self, PyObject *args); double mysqrt(double z); /* end C_test.h */ /* C_test.c file to test imorting C modules to Python */ #include "C_test.h" #include /* Globals */ /* Set up the methods table */ static PyMethodDef C_testMethods[] = { {"square", square, METH_VARARGS}, {"squarert", squareroot, METH_VARARGS}, {NULL, NULL} /* Sentinel */ }; /* Test a simple C function, square */ /* Initialize the C_test functions */ void initC_test() { (void) Py_InitModule("C_test", C_testMethods); } /* square function */ static PyObject *square(PyObject *self, PyObject *args) { double x,y; if (!PyArg_ParseTuple(args, "d", &x)) return NULL; y=x*x; return Py_BuildValue("d", y); } /* squareroot function */ static PyObject *squareroot(PyObject *self, PyObject *args) { double x,y; if (!PyArg_ParseTuple(args, "d", &x)) return NULL; y=mysqrt(x); return Py_BuildValue("d", y); } /* my square root function, internal to C */ double mysqrt(double z) { return sqrt(z); } /* end C_test.c */ /* C_test.prj.exp initC_test The files' content. C_test.h: The header file for the source code C_test.c. It must contain the python.h header to enable you to use Python types (e.g. PyObject) to define your function. Passing things back and forth to Python must be done with Python defined objects (pointers to these, actually). If you have prototyping turned on you must include the prototypes of all the functions in C_test.c. Note, all Python callable functions MUST be typed as static, except the initialization routine (called here initC_test) which is just void. C_test.c: The source file. Include the header and any other C header files you need (math.h is used here). Set up the Python methods table. This is a structure (PyMethodDef) which is passed to Python by the initC_test function. It tells Python the names of your functions. E.g. in the line, {"square", square, METH_VARARGS}, Python will refer to the C function square as square. The names need not be the same, see below. METH_VARARGS tells Python how to pass the arguments. The routine PyArg_ParseTuple hands the Python variable to C in a form that C can handle. There are rules concerning this function (not hard). You should check the documentation on Extensions. The routine Py_BuildValue takes the C value and puts it into a Python object that can be returned to Python and used there. Similar rules apple for that conversion. See the documentation. C_test.prj.exp: Exports the name of the initialization function initC_test that is first called by Python upon import of the C_test module. That way Python knows to first call initC_test. No other function names should be in the .exp file. Naming things. I am not completely sure, but the following seems to be the case regarding naming of files, functions, projects, and modules. The only names that seem to matter are the name of the module (shared library) that Python will import and the name passed to Python to associate with the list of functions imported (see further on here). The actual module (shared library) needs to be of the form name.ppc.slb, where the name is replaced by the actual name you will use in Python to import the extensions, C_test in this case (see below). C_test is also the (mandatory?) name passed to the Python initializer in Py_InitModule. Other names can be set as you like so long as you are consistent and tell the systems involved (the compiler, Python, etc.). You can see this by tracing the names as they might be used. Examples: (1) the initialization function that Python runs when first importing the module has its name passed to Python by virtue of the .exp file so Python knows by that export from C_test.prj.exp file that it must first call initC_test. I could have called it junkC_test so long as I renamed it in the source code and header and .exp file. (2) Python know what names to use for each function from the init routine that calls Py_InitModule and passes the names associated with the C function. I associated "square" (the Python name) to the square function, but I associated "squarert" with the C function squareroot. Python will not get confused since the structure (C_testMethods) I defined tells Python what to call when handed a name. (3) The name for the functions (methods) structure can be any valid C variable so long as that is the name passed to Py_InitModule in the init routine (initC_test here). (4) The call to Py_InitModule also tells Python to associate C_test and the names (C_testMethods). Not completely sure about this association, but it is necessary. 2. Codewarrior Compiler Project Settings. Only those you need to set to something special are shown. Access Paths: Include your project's path and path to Python folder where PythonCore is (see below). PPC Target: Name set to C_test.ppc.slb or name.ppc.slb (replace name with the module name) Choose Project Type as Shared Library. Creator as Pyth Type as shlb PPC Linker: Initialization set to blank (nothing in the space) Main set to blank (nothing in the space) Termination set to blank (nothing in the space) PPC PEF: Export symbols set Use ".exp" file Code sorting set to None. Files : libraries. You must have C_test.c, C_test.prj.exp, PythonCore (a library supplied with Mac Python version), and, in this case because of the sqrt() C function, MathLib. 3. Importing into Python Getting the code in and using it. In Python (assuming your new C extension module is in another folder than the standard Python ones) type import sys sys.path.append("path to your new module's directory here") # sets path to your new module import C_test # or what ever your new module is named dir(C_test) # to see that the functions #actually got there In the above I assume you see NO error messages. If so, you are ready to use your new functions. */