Archived:Creating PySymbian 2.0 Extensions (Easy Approach)
The article is believed to be still valid for the original topic scope.
Article Metadata
Code Example
Article
Contents |
Overview
This article demonstrates that how one can create his own PySymbian 2.0 Extension in an easier way.
Introduction
By default, PySymbian offers a subset of Symbian C++ (equivalent) functions. There is a possibility that the function or feature required by the developer is not available in Python ,thats why, to fill this gap, the developer has an option to write down his own module or extension which is actually a dynamic library coded in Symbian C++ to extend Python functionality.
Installation
- Symbian^3 and the Qt SDK already have required Perl version (5.6.1.635). If you're using another SDK install these first to ensure that the required version of Perl is present. See here for more information.
- Download S60 SDKs for 3rd edition or 5th edition phones
- Download Carbide C++
- Download Python_2.0.0_SDK_3rdEdFP1.zip or Python_2.0.0_SDK_3rdEdFP2.zip.Extract it and than copy the EPOC folder to your S60 SDKs EPOC Folder.
- Download Python 2.5(Python for windows is actually required to run the Py_XT_Creator.py script developed to create Pys60 Extension templates for Carbide C++ in one-go.)
To get started with Symbian C++ , you can also follow these tutorials :
- Screencast : http://www.youtube.com/watch?v=K8rjcOJ_-cM&feature=watch_response
- Article: How do I start programming for Symbian OS?
- Article : http://www.developer.nokia.com/Resources/Tools_and_downloads/
Once every thing is installed properly and you can successfully build Hello World project, then you are ready to program your own PySymbian modules .
Py_XT_Creator
Py_XT_Creator is a Python script which creates PySymbian 2.0 extension templates in one-go and thus, remove a number of errors produce by beginners while creating extensions. I believe it will fix 40 % of the errors generated by beginners.
How to use Py_XT_Creator
Simply, follow the screencast to learn how to use this tool : http://www.youtube.com/watch?v=SSkhdK3zxhI
Download
Download PyXT Creator: File:Py XT Creator.zip
PySymbian Extension Template
Once you generate and import your own template in Carbide C++ after viewing the above screencast, you are ready to learn each file details:
- groups\bld.inf
- groups\my_module_name.mmp
Explained here : MMP file
- sis\my_module_name.pkg
This pkg file is use to create the SIS package for your module. Please, follow the screencast to know that how can u create your own SIS packages using this pkg file.
- python\my_module_name.py
This is a Python PYD wrapper which loads the my_module_name.pyd from sys\bin directory in phone and this wrapper gets loaded when we call "import my_module_name" in python.
- inc\my_module_name.h
This is a header file which must include the declaration of your Symbian C++ functions .
- src\my_module_name.cpp
This is the main source code file which includes all the function implementation.
PySymbian Extension Basic Parts
Mechanism
Lets take a simple case to understand the basic parts of PySymbian Extension.Suppose, we type in the interpreter:
import my_module_name
my_module_name.myadd(2, 3)
and we get an output :
5
When we entered the first line, "import my_module_name" than the module is initialized and the init_my_module function of the module is called (which we discussed just after this introduction) .On the second line, "my_module_name.myadd(2, 3)", we call a myadd function and pass two arguments . This function must be defined in the module source code , we must know that the two arguments must be parsed from Python (Object) Integers to Symbian C++ integer (datatypes/Objects) first , than they are assumed , build back to Python objects from Symbian C++ objects and returned .Thats the way , we get 5 at the end if we pass 2 & 3 as arguments. Lets discuss these 3 basic parts of python module, all of these parts reside in src\my_module_name.cpp file.
1- init Function
This function gets a call when the module is initialized .The body of this functions looks like this :
DL_EXPORT(void) init_ my_module_name()
{
Py_InitModule("_my_module_name", (PyMethodDef*) my_module_name_methods);
}
The first parameter of the Py_InitModule is the module name starts with "_" & second is the table of methods . Note: The initialization function must have name equivalent to init_my_module_name .
2- Methods Table
The method table is passed to the interpreter in the module initialization function. This table look like this :
static const PyMethodDef my_module_name[] =
{
{
/*first parameter is function name visible to Python interpreter ,actually it is
an alias of the real C++ function provided in second parameter.
*/
"myadd",(PyCFunction) addfunction,METH_VARARGS,"This is the ADD function."
},
{
0, 0
}
};
3- PyCFunctions
These function takes Python objects and returns a pointer to a Python object. The developers can set the number * type of parameters in these functions . Let us take a look at a simple function:
static PyObject* addfunction(PyObject* /*self*/, PyObject* args)
{
int val1 = 0;
int val2 = 0;
/*Parse the parameters of a function that takes only positional parameters into local variables.
For details of parsing integer, Unicode etc , goto :
http://docs.python.org/c-api/arg.html */
/*Specifically, this function has two parameters i.e two integer parameters , if the user enter a string or less than
2 parameters than an error is automatically generated in python.This step is also known as
Extracting Parameters in Extension Functions */
if (!PyArg_ParseTuple(args, "ii", &val1,&val2)){
return NULL;
}
val1 += val2;
/*Build Python Object from Symbian C++ Object
More details at :
http://computing.fnal.gov/docs/products/python/v1_5_2/ext/buildValue.html*/
return Py_BuildValue("i",val1);
}
Now, let us discuss the important part of these functions , in detail :
3.1 Extracting Parameters in Extension Functions
The arguments are actually passed as a Python tuple object.So, we have to decode the Python tuple object into the respective Symbian C++ datatypes using PyArg_ParseTuple() function. This function also defines the number and type of parameters available to an individual PyCFunction. Note: PyArg_ParseTuple() returns true (nonzero) if all arguments have the right type and its components have been stored in the variables whose addresses are passed. It returns false (zero) if an invalid argument list was passed. For more details about PyArg_ParseTuple , please visit : http://docs.python.org/c-api/arg.html
Let me write some parsing code snippets to help you out in your projects :
Python String Object to TPtrC8
char* s = NULL;
int lns;
//Parse Python String Parameter to Symbian C++ char and than TPtrC8
if (!PyArg_ParseTuple(args, "s#", &s,&lns)){
return NULL;
}
TPtrC8 mystring((TUint8*)s, lns);
//than u can copy the content pointed by this pointer into a modifiable buffer
TBuf<200> myBuf;
myBuf.Copy(mystring);
Python Unicode Object to TPtrC
char* s = NULL;
int lns;
if (!PyArg_ParseTuple(args, "u#", &s, &lns)){
return NULL;
}
TPtrC mystr((TUint16*)s, lns);
Python List Object to CDesCArray
PyObject* list;
if (!PyArg_ParseTuple(args, "O!", &PyList_Type, &list))
return NULL;
TInt error = 0;
int sz = PyList_Size(list);
CDesCArray *myarray = NULL;
if (sz > 1) {
if (!(myarray = new CDesCArrayFlat(sz))) return PyErr_NoMemory();
for (int i = 0; i < sz; i++) {
PyObject* s = PyList_GetItem(list, i);
if (!PyUnicode_Check(s))
return Py_False;
else {
TPtr buf(PyUnicode_AsUnicode(s), PyUnicode_GetSize(s),
PyUnicode_GetSize(s));
TRAP(error, myarray->AppendL(buf));
}
}
}
3.2 Building PyObject from Symbian C++ datatypes
PyObject *Py_BuildValue(char *format, ...);
This function is use at the time of returning from Symbian C++ function .It actually builds a PyObject from a Symbian C++ datatype. It recognizes a set of format units similar to the ones recognized by PyArg_ParseTuple(), but the arguments (which are input to the function, not output) must not be pointers, just values. It returns a new Python object, suitable for returning from a Symbian C++ function called from Python.
Let me write some building code snippets to help you out in your projects :
TBuf to Pointer Unicode Object
TBuf<200> mybuf(_L("Hello World"));
PyObject * PyU=Py_BuildValue("u#", mybuf.Ptr(), mybuf.Length() ) ;
TBuf8 to Pointer String Object
TBuf8<200> mybuf(_L8("Hello World"));
PyObject * PyStr=Py_BuildValue("s#", mybuf.Ptr(), mybuf.Size() ) ;
CDesCArray to Python Tuple Object
CDesCArray *myarray = new CDesCArrayFlat(10);
//fill the array by yourself, than write this code
PyObject *mytuple;
mytuple = PyTuple_New(myarray->Count());
TInt i =0;
for (i=0; i < myarray->Count(); i++) {
PyObject *str = Py_BuildValue("u#", (*myarray)[i].Ptr(), (*myarray)[i].Length());
PyTuple_SET_ITEM(mytuple, i, str);
}
return mytuple
Errors and Solutions
ImportError: dlopen:Load failed
This error is usually arises due to difference of capabilities in PySymbian shell/app and the extension(module) . The solution is quite simple, just set the capabilities of module (in the mmp file) equal to that of PySymbian shell.
If you are getting this error, while using your extension in a standalone application, then read here to fix it : Error Loading Extension Thread
Author
This page is authored by Sajid Ali Anjum (a.k.a SajiSoft).I will keep this page up-to-date with my findings.If u have any suggestion/feedbacks, feel free to post them in comment page.


Hamishwillee - Download link to Py_XT_Creator.zip is broken
Hi I can't find this zip any more. Can you upload to the wiki? I'd also suggest thorough review of this. The Active perl version for example cannot be downloaded any more.
Regardshamishwillee 06:19, 12 August 2011 (EEST)
Sajisoft - Broken links are fixed.
I reviewed the article and fixed the broken links.
Best Regards,
SajiSoftsajisoft 22:23, 15 September 2011 (EEST)