Archived:Creating C PySymbian extensions using Carbide.c++
First, install the Nokia S60 Platform SDKs for Symbian OS, which can be found here. (In this tutorial we used the S60 3rd Edition, FP2 v1.1 SDK). These SDKs contain some files needed to compile the extension. However, they do not contain Python files, such as python.h and python222.lib. To add these important files, install the PySymbian SDKs on an installed S60 SDK. First, get PythonForS60_X_X_X_SDK_3rdEd.zip here, where X is the version of the package (in this tutorial we used PySymbian v1.4.5). Next, unzip the contents of the internal zip file (named sdk_files.zip) into the SDK folder (in this case, C:\S60\devices\S60_3rd_FP2_SDK_v1.1). This operation will add Python files to the D:\S60\devices\S60_3rd_FP2_SDK_v1.1\epoc32 folder.
After installing the SDK and Python files, install Carbide.c++, which is an excellent integrated development environment (IDE) to create C/C++ software for the S60 platform. The Carbide.c++ installation file can be found here.
Importing the example
Now, get the example package here and unzip it.
Open Carbide.c++ and go to File->;Import. Chose Symbian OS->;Symbian OS Bld.inf file and click the Next button.
Browse the bld.inf file, which is in the group folder located in the unzipped example package and click Next.
Choose Phone Release (GCCE) and click Next and Finish.
Now you can see the example files.
This is a very simple example showing an empty information note.
Analysing the example
The project includes, the most important files to be analyzed here are none.h and none.cpp.
In the none.h file we have included a few useful header files.
- e32base.h: For CBase;
- e32std.h: For descriptors;
- aknnotewrappers.h: For notes (remember, our example uses an information note);
- Python.h: For Python issues;
- symbian_python_ext_util.h: For error handling.
// Include Files
#include // CBase
#include // TBuf
// Class Definitions
class Cnone : public CBase
// new functions
IMPORT_C static Cnone* NewL();
IMPORT_C static Cnone* NewLC();
public: // new functions, example API
IMPORT_C void ShowConfirmationNote();
private: // new functions
private: // data
#endif // __NONE_H__
Other items in this file are constructors and methods definitions, such as the ShowConfirmationNote() method.
In the none.cpp file you can see the include statement of none.h. Going down, you’ll see the ShowConfirmationNote() method, which only calls the ExecuteLD() method of a CAknInformationNote object. This function does what we want (the execution of an empty information note), but it cannot be called directly from Python. Thus, you must create a function that is callable from Python. This function receives Python parameters, converts these parameters to C language, calls Symbian C++ methods, and returns a Python object to the caller.
#include "none.h" // Cnone
#include "none.pan" // panic codes
// Member Functions
EXPORT_C Cnone* Cnone::NewLC()
Cnone* self = new (ELeave) Cnone;
EXPORT_C Cnone* Cnone::NewL()
Cnone* self = Cnone::NewLC();
// note, CBase initialises all member variables to zero
EXPORT_C void Cnone::ShowConfirmationNote()
CAknInformationNote* dialog = new(ELeave)CAknInformationNote();
static PyObject* show_note(PyObject* /*self*/, PyObject* args)
Cnone* obj = Cnone::NewL();
static const PyMethodDef none_methods =
"show_note", (PyCFunction)show_note, METH_VARARGS, "shows a note."
Py_InitModule("none", (PyMethodDef*) none_methods);
The show_note function receives two PyObject parameters. The first is the self parameter and the second is the tuple containing arguments. In the body of this function we call the ShowConfirmationNote method into a TRAP. The TRAP pulls a nonzero error code into an integer if an error has occurred. The SPyErr_SetFromSymbianOSErr(error) statement is called if an error has occurred. It just converts Symbian OS errors to Python errors. If no errors occurred, the note will be displayed and the function will return a Py_None.
Next, we have a PyMethodDef, which is a table containing Python function names to their C function implementations. It also has a flag telling the interpreter the calling convention to be used for the C function. Normally it should always be "METH_VARARGS" or "METH_VARARGS | METH_KEYWORDS". If you wish to add more functions, you will need to add these functions to this table.
The next function is init_none(). This function passes the method table to the interpreter in the module's initialisation function. The initialisation function must be named initname(), where name is the name of the module and should be the only non-static item defined in the module file. It calls the function Py_InitModule, which receives the module name and table name described above.
Building the example
First, using Carbide.c++, go to the group folder and open none.mmp file. In the Overview tab we have Target name (none.pyd), Target type (DLL), and UID 2 (must be 0x1000008d).
Open the Libraries tab and add euser.lib, python222.lib, avkon.lib, eikcdlg.lib, and eikctl.lib libraries.
Open the Options tab and add these paths to System includes (under Compiler Settings): \epoc32\include, \epoc32\include\libc and \epoc32\include\python. Also add these capabilities: LocalServices, NetworkServices, ReadUserData, UserEnvironment, and WriteUserData.
Go to menu Project->Properties. Then expand the Carbide.c++ option and select Build Configurations.
On the SIS Builder tab, click the Add button and browse the ‘.pkg’ file (which is under sis folder). Choose the Output File Name and select the Don't sign sis file. Click the OK button.
Go to menu Project->Freeze Exports. Finally, go to menu Project->Build Project.
If everything runs without problems, the sis file will be created and placed inside the sis folder.