PythonWrappers
From NRCwikis
This page will tell you how to write Python wrappers in Symbian.
First, read the Python Documentation on how to write python wrappers on PC. Most things there will apply to Symbian.
Next, you'll need to download the Symbian Python SDK from SourceForge. Grab the PythonForS60_1_4_0RC1_SDK_3rdEd_GCCE_selfsigned.zip (or ARMV5) file from the 1.4.rc1 version because the official release version does not contain the compiled libraries. Unzip the folder and copy the files to your Epoc32 folder in the SDK. You will now be able to link against python222.lib.
You can setup a project stub for a python dll by using the make_dll_stub.py python script. The usage is:
python make_dll_stub.py UID name e.g. python make_dll_stub.py 0xA00015D4 foo
Note that this has to be run using a Windows version of Python, such as ActivePython. This script with generate the makefile, pkg file, python stub files, and c++ wrapper stub files for your project.
Here's a simple (and hopefully compile-able) example of writing a Python wrapper for some c++ code. The symbian function multiplies two numbers together and returns the result.
/*
* Python header files should be included first
*/
#include <Python.h>
#include <symbian_python_ext_util.h>
/*
* Symbian function, for example something from a library you wrote.
*/
TInt32 MultiplyInts(TInt32 a, TInt32 b) { return a*b; }
/*
* Python wrapper for the Symbian function
*/
static PyObject* mymodule_MultiplyInts(PyObject* self, PyObject* args) {
TInt error;
TInt32 a, b, c;
if ( !PyArg_ParseTuple(args, "ii", &a, &b) ) {
return Py_BuildValue("s", "Cannot parse arguments.");
}
Py_BEGIN_ALLOW_THREADS;
// call our function and trap the error
TRAPD(err, c = MultiplyInts(a, b));
error = err;
Py_END_ALLOW_THREADS;
// now check for errors. If there was a leave, turn it into
// a python exception, otherwise make a python object with the
// result of the symbian function and return it.
PyObject* result;
if (error != KErrNone) {
result = SPyErr_SetFromSymbianOSErr(error);
} else {
result = Py_BuildValue("i", c);
}
return result;
}
/*
* Make a table of the module's exported methods.
*/
static const PyMethodDef mymodule_methods[] = {
{"MultiplyInts", (PyCFunction)mymodule_MultiplyInts, METH_VARARGS},
{0, 0} // sentinel
};
/**
* Finish setting up the types we need.
* Export the methods into a python module.
*/
DL_EXPORT(void) init_mymodule() {
PyObject* module = Py_InitModule("_mymodule", (PyMethodDef*) mymodule_methods);
if (!module) return;
}
/**
* Magic make a dll woodoo.
*/
#ifndef EKA2
GLDEF_C TInt E32Dll(TDllReason)
{
return KErrNone;
}
#endif
Ok, suppose you copied the above code into a file called PythonWrappers.cpp, if you have run the "make_dll_stub.py" script you will have a folder named "src" inside the project directory created by the script, place the .cpp file inside this. Now we need to build a python dll that we will install on the phone. The next stage is to create an mmp file, which will will look something like this (assuming the standard symbian project directory structure):
TARGET _mymodule.pyd TARGETTYPE dll TARGETPATH \system\libs SYSTEMINCLUDE \epoc32\include \epoc32\include\variant SYSTEMINCLUDE \epoc32\include SYSTEMINCLUDE \epoc32\include\libc SYSTEMINCLUDE \epoc32\include\python USERINCLUDE . ..\inc LIBRARY hal.lib LIBRARY euser.lib LIBRARY python222.lib LIBRARY estlib.lib CAPABILITY ReadUserData WriteUserData UserEnvironment LocalServices NetworkServices NOSTRICTDEF EXPORTUNFROZEN EPOCALLOWDLLDATA SOURCEPATH ..\src SOURCE PythonWrappers.cpp
Save this to, say, mymodule.mmp and place this file into the folder named "group" (this folder will be in the same directory as the "src" folder from above). Next we need to build it. In a console window navigate to the "group" folder and type the commands:
bldmake bldfiles abld build gcce urel Note: These are two seperate commands, type the first then execute it and then type the second and execute it.
You should get a bunch of warnings about unfrozen dlls, which is ok. Executing this command should produce a file called ABLD.bat in the "group" directory and _mymodule.pyd which will be placed inside the SDK directory.
Now we need to tell python how to load this module. Make (or open, if it is already present) a python folder in your project directory, and make a file mymodule.py with the following contents:
import imp
# Load the dll. This step will fail if signing permissions don't match up.
_mymodule=imp.load_dynamic('_mymodule', 'c:\\sys\\bin\\_mymodule.pyd')
#remove unnecessary names from namespace
del imp
# pull entire c module namespace into this one
from _mymodule import *
Now, we need to make a sis file that will install the library on the phone. Make a file mymodule.pkg inside the "sis" folder in your project directory, with the following contents:
&EN
#{"mymodule"},(0xA00015D4),1,0,0, TYPE=SA
%{"Vendor-EN"}
:"Vendor"
[0x101F7961], 0, 0, 0, {"S60ProductID"}
"$(EPOCROOT)\epoc32\release\$(PLATFORM)\$(TARGET)\_mymodule.pyd" -"!:\sys\bin\_mymodule.pyd"
"..\python\mymodule.py"-"c:\resource\mymodule.py"
Note, in the line above:
"$(EPOCROOT)\epoc32\release\$(PLATFORM)\$(TARGET)\_mymodule.pyd" -"!:\sys\bin\_mymodule.pyd"
You must replace each of $(EPOCROOT), $(PLATFORM) and $(TARGET) with real folder names, for example:
"C:\S60\devices\S60_3rd_FP2_SDK\epoc32\release\gcce\urel\_mymodule.pyd" -"!:\sys\bin\_mymodule.pyd"
Notice that once the sis file has been installed the python file goes to the resource directory and the actual dll goes to c:\sys\bin. This is the only configuration that is allowed, otherwise python will not find your module.
Ok, finally we are ready to make a python script, say test_mymodule.py
import mymodule a = 10 b = 2 c = mymodule.MultiplyInts(a, b) print c
Move this to e:\python on the phone, and hopefully running it will result in 20 printed on your screen. Phew! Now go read the Python Documentation to learn how to make more sophisticated wrappers.
