×
Namespaces

Variants
Actions

Archived:Creating PySymbian 2.0 Extensions (Easy Approach)

From Nokia Developer Wiki
Jump to: navigation, search

Archived.pngArchived: This article is archived because it is not considered relevant for third-party developers creating commercial solutions today. If you think this article is still relevant, let us know by adding the template {{ReviewForRemovalFromArchive|user=~~~~|write your reason here}}.

The article is believed to be still valid for the original topic scope.


Article Metadata
Code ExampleArticle
Created: sajisoft (12 Apr 2010)
Last edited: hamishwillee (31 May 2013)

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


To get started with Symbian C++ , you can also follow these tutorials :

Note.pngNote: It is good to install SDKs and Carbide C++ in the same drive and you will see errors if your workspace directory is not in the same drive as of the SDKs or have spaces in the workspace directory name.

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

Note.pngNote: Please, do not modify the template folder that comes with Py_XT_Creator tool because it may cause issue with all other templates created by using this tool. BTW, its always good to keep a back-up.

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

Explained here : http://library.developer.nokia.com/index.jsp?topic=/S60_5th_Edition_Cpp_Developers_Library/GUID-35228542-8C95-4849-A73F-2B4F082F0C44/sdk/doc_source/ToolsAndUtilities94/Build-ref/bldmake-ref/bld.inf.guide.html

  • 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.

This page was last modified on 31 May 2013, at 04:07.
80 page views in the last 30 days.
×