We love open source software and by opening up the Mosync SDK under the GPL license, we aim to give a large group of developers the opportunity to go mobile in a short time on both the Windows and OS X environments. We look forward to working together with you to create new, great applications in mobile, as well as receiving your contributions and suggestions on how to make Mosync even better!
Participation from our community is very important in the success of the MoSync Open Source project. We invite you to participate on many levels. These activities require a certain level of technical skill. As a MoSync community member, you as a user can contribute in many other ways; i.e. by participating in the forum or by blogging about MoSync on the Internet.
We'd really like to see what people have done with the MoSync SDK, and cordially welcome everyone to share their applications. You can find some of our own application on the Example Applications page, and some of our customer's applications on the Who's Using MoSync page.
Before you can contribute code to the MoSync SDK, we need you to do a couple of things:
Send your core patches for review to tony@mosync.com.
Report issues at our Jira Issue Tracker.
What follows are some additional tips on ways to make your bug report better so that someone will be able to help you.
There are the three basic elements of a bug report, this may be only to basic but bear with us. You need to tell us exactly what you did:
"I instructed the program to draw a polygon on the canvas",
what you expected to have happen:
"I expected a red polygon to appear on the screen", and lastly what actually happened
"I got a blue circle, flickering on screen".
The odds are good that if you've found a problem, someone else has found it, too. If you spend a few minutes of your time making sure that you're not filing a duplicate bug, that's a few more minutes someone can spend helping to fix that bug rather than sorting out duplicate bug reports.
Don't report an error message you don't understand as a bug. There are a lot of places you can ask for help in understanding what is going on before you can claim that an error message you do not understand is a bug.
This is a fine line to walk. But there are some general guidelines:
Yes, the MoSync developer community is global and include a great many people who can speak a great many languages. But if you were to report a bug in a language other than English, many (if not most) of the people who would otherwise help you won't be able to.
Every time a new version of a MoSync product is released, many bugs are fixed. If you're using a version of a product that is more than two revisions older than the latest version, you should upgrade to the latest version to make sure the bug you are experiencing still exists. (And it's not a bad idea to try upgrading even if your version is only a version behind the most current one.)
If you have encountered two bugs that don't appear to be related, create a new bug report for each one. This makes it easier for different people to help with the different bugs.
While commercial customers and partners can influence the direction and feature set of the MoSync Mobile SDK, you can too. Submit your feature request in the issue tracker.
Usability reports are feedback from the community about usage of (new) features in the real world. A usability report is a short account of the user's first impact on a newly tried feature, recording his/her expectations and the level of satisfaction achieved.
An usability report should have the following components.
These reports are like any other contribution very important to us.
Send your usability reports to miles.midgley@mosync.com.
The MoSync Issue Tracker is based on Jira and can be found here: jira.mosync.com. Jira allow users to see more than just one project at a time and ongoing work for up-and-coming releases and is integral in our development.
Note: Our oldIssue Tracker is still visible for archive purposes. We have imported all the issues from the old Google issue tracker. We are manually adding attachments, an ongoing task. If you were following an issue on the Goggle issue tracker you will have to resubscribe to that issue in Jira.
Note: To post or follow issues you will need to create a user ID on Jira.

Follow the instructions and log in.
Next you will be presented with a dashboard. This gives an overview of the MoSync project.

At the top right there is a button to create an issue. This screen allows you to define if this issue is a Bug or New Feature. These are currently the only two issue types open to users.

The following screen shows what we would like you to fill in as a minimum.

Issues are usually resolved in 7 stages:
| Open | A newly reported issue, no action taken yet |
| Accepted | A developer has accepted the issue and will soon start working on it |
| In Progress | A developer is working on the issue |
| Resolved | The developer feels that the issue has been dealt with. |
| Code Review | The code is read is ready for code review. |
| Waiting QA | The code has been merged and QA can build and verify the issue is resolved. In most cases the fix will be in the next nightly build. |
| Verified | The QA department has checked the solution and has agreed that it is fixed |
Some things to keep in mind before reporting an issue:
If you have suggestions for improving MoSync, enter it as an issue into the Jira issue tracker. Provide as much information as you like. We love feedback, and we are more than happy to let our user base help us determine the direction of development.
If you are missing a feature in MoSync, why not write it up? The development team keeps a close watch on the Issue Tracker so your queries and posts will usually be attended to within a few days. We are committed to providing the best possible user experience. Help us make MoSync the most powerful mobile development solution on the planet!
These instructions describe how to build a Windows installation package for the MoSync SDK. The completed installation package is an .exe file, just like our featured releases and our nightly builds.
To build the full installation package, you will need a Windows machine, a Mac OS X machine, and a Linux machine. If you omit the iPhone and Moblin runtimes, you can build a partial package on just the Windows machine.
(Instructions for building the MoSync SDK from source on OS X are also available.)
To build the MoSync Eclipse IDE, the MoSync libraries, and the MoSync tools, you will need a computer running Windows (Windows XP, Windows Vista, or Windows 7) and capable of running Visual Studio C++ 2005.
To build the MoSync runtimes you will need:
If you don’t need the iPhone and Moblin runtimes, everything can be built on the Windows machine.
1. Download the source tarball (.tar.bz2) of our current feature release from our website or from our open-source project repository:
Alternatively, get the source tarball for our latest nightly build from our website:
or through TortoiseGit:
git clone https://github.com/MoSync/MoSync.git c:\mb\MoSync-trunk git clone https://github.com/MoSync/Eclipse.git c:\mb\Eclipse
2. Unpack the source tarball into (or, if you have installed TortoiseGit, check it out to):
C:\mb
3. Download target-platform.zip which contains everything needed to build the Eclipse-based IDE. Put the zip-file in:
C:\mb\eclipse\com.mobilesorcery.sdk.product\build
Important! Make sure you install and configure the dependencies in the order listed below. If you do not, terrible things may happen!
4. Download and install Microsoft® Visual Studio® 2005 and apply Service Pack 1. Make sure that you install the runtime MT (Multi Threaded) DLL.
5. Add the following paths to Visual Studio:
\mb\mosync-trunk\tools\ReleasePackageBuild\build_package_tools\include \mb\mosync-trunk\libs \mb\mosync-trunk\libs\MAStd
\mb\mosync-trunk\tools\ReleasePackageBuild\build_package_tools\lib
6. Find the file:
C:\mb\mosync-trunk\tools\ReleasePackageBuild\build_package_tools\include\msvc\stdint.h
Copy it to the directory:
C:\Program Files\Microsoft Visual Studio 8\VC\include\
7. Download and install the following Visual Studio SDKs:
8. Find the files:
C:\Program Files\Windows CE Tools\wce500\Windows Mobile 5.0 Smartphone SDK\Include\Armv4i\gdiplus*.h
Copy them to:
C:\Program Files\Microsoft Visual Studio 8\SmartDevices\SDK\Smartphone2003\Include\
9. Download and install the Ruby 1.8 (or later).
10. Download Sqlite 3 for Ruby 1.8 and put it in your ruby\bin directory. (If you have installed a later version of Ruby you'll have to find another version of the Sqlite 3 dll.)
11. Install Sqlite 3 Ruby Gem by opening a command (cmd) window and entering:
gem install sqlite3-ruby
12. Accept the installation of dependencies. These are the ones you need:
13. Download and install Java SE Development Kit (JDK) 1.6.
14. Make sure the JDK’s \bin directory has been added to Window’s list of path environment variables, otherwise add it.
15. Download and install the latest version of the SonyEricsson SDK for the Java ME Platform.
16. Download and install the ProGuard 3.7 Java obfuscator.
17. Put the file proguard.jar in the \OnDeviceDebug\bin directory of the J2ME SDK.
18. Download and install ActiverPerl 5.8 Community Edition .
19. Download and install S60 3rd Edition SDK for Symbian OS FP1.
20. Download and install the Extensions plug-in for S60 3rd Edition SDK for Symbian OS, for C++, MR.
21. Download and install S60 2nd Edition SDK for Symbian OS FP3. If the installer asks you which network adapter to use, pick any.
22. Download and install S60 5th Edition SDK for Symbian OS. Make sure you install it in the folder
\Symbian\s60v5\, as that is the location that is assumed by our build scripts.
23. Download the Extensions Plug-in for S60 3rd Edition SDK for Symbian OS, for C++, supporting Feature Pack 1, v2.5. Install it in both 3rd and 5th edition SDKs.
24. Download and unzip symbian-94-fixes.zip. Install it over the s60v5 SDK.
25. Download and unzip symbian-81-extras.zip. Install it over the s60v2 SDK, located in the folder:
\Symbian\8.1a\S60_2nd_FP3\
26. For both 3rd and 5th edition SDKs, run CSL Toolchain (GCCE) Install, found on the Start menu, under:
\S60 Developer Tools\* Edition SDK\v1.0\Tools
27. For each Symbian SDK, make sure that the following folder exists:
\Epoc32\Data\z\resource\apps\
Sometimes, this folder is a file, or does not exist at all, and in both cases this would cause the build to fail.
28. For both 3rd and 5th edition SDKs, find line 31 in the file \epoc32\tools\e32env.pm:
die "EPOCROOT environment variable must be capitalised\n" if (!$found);
29. Disable this line by adding a hash sign (#) in front of it.
30. Download and install CoreUtils for Windows.
31. Download and install Grep for Windows.
32. Download and install Sed for Windows.
33. Make sure the \bin directory of GNU binutils has been added to Window’s list of path environment variables, otherwise add it.
34. If required, build the Moblin runtimes on Linux.
35. If required, build the iPhone runtime on Mac OS X.
(You
do not need to build the Windows Mobile, Java ME, Android, and Symbian
runtimes, they are automatically built by the build script).
36. Locate the file run.bat.example in \mb\mosync-trunk\trunk\tools\ReleasePackageBuild, copy it, and name the copy run.bat.
37. Replace the SDK path in run.bat with one appropriate for your system:
start /B /BELOWNORMAL build_package.bat c:\SonyEricsson\JavaME_SDK_CLDC\OnDeviceDebug\ 2>&1 | tee log.txt
38. Start run_commercial_recompiler.bat. It will set up an environment, then call your run.bat (found in the \mb\mosync-trunk\tools\ReleasePackageBuild folder). You can use one of the other run_*.bat files to build the package in different ways.
If all goes well, an installer package should appear in \mb\MoSyncReleasePackage\.
It will be called something like MoSyncSetup_XXX.exe.
39. Done.
If you want to create the Windows Mobile, Java ME, Android, and Symbian runtimes to use with the OS X version of the MoSync SDK (see building the MoSync SDK from source on OS X), here’s how:
1. Follow the instructions above for Getting the MoSync Source Code
and Installing the Dependencies. (You do not need to get Eclipse or build the SDK.)
2. Run the following command from the command line to set the target MoSync Directory:
set MOSYNCDIR=\mb\MoSyncReleasePackage
3. Go to the folder
\mb\mosync-trunk
and run the following command:
ruby workfile.rb base
4. Go to
\mb\mosync-trunk\tools\ConcurrentBuild
and run the following command:
ruby ConcurrentBuild.rb \mb\MoSyncReleasePackage \mb\MoSync-trunk android javame wm s60
The script will build your runtimes and put them in the \profiles folder under \mb\MoSyncReleasePackage
.
5. Copy the runtimes to your mac installation folder and you can start using them on your Mac OS X version.
6. Done.
These instructions describe how to build an OS X installation package for the MoSync SDK. The completed installation package is an .dmg file, just like our featured releases and our nightly builds.
To build a full installation package that includes all the MoSync runtimes, you will need a Windows, a Mac OS X, and a Linux machine. If you want an installation package that just has the iPhone runtime, you can build the whole thing on a single OS X machine.
To be able to follow these instructions you will need to be registered as an Apple Developer. Instructions for building the MoSync SDK for Windows are also available.
To build the MoSync Eclipse IDE, the MoSync libraries, and the MoSync tools, you will need a Mac OS X Snow Leopard (OS X v. 10.6) computer capable of running Xcode.
To build the MoSync runtimes you will need:
If you only want the iPhone runtime, everything can be built on OS X.
1. Download and install Xcode 3.2.5 toolset from the iPhone Dev Center, including the iPhone SDK.
2. Download and install the 32-bit version of Fink for Snow Leopard.
3. Download and install MacPorts.
4. Download and install IceBerg for Mac OS X.
5. From the Terminal, run the following commands:
sudo fink -b install sdl sudo fink -b install sdl-image sudo fink -b install sdl-ttf sudo fink -b install sdl-sound sudo port install freeimage +universal sudo port install ImageMagick +universal sudo port install doxygen
6. Get the MoSync source code from github repository:
git clone https://github.com/MoSync/MoSync.git MoSync
7. Clone the MoSync Eclipse Repository into the same path as MoSync:
git clone https://github.com/MoSync/Eclipse.git Eclipse
8. Download the zip-package here that contains everything needed to build the Eclipse-based IDE and put it in the folder:
/MoSync/tools/ReleasePackageBuild/
9. In your checked out version of the MoSync SDK trunk, go to the folder:
/MoSync/tools/ReleasePackageBuild/
then run:
./build_mac_package.sh
10. If everything goes as it should, the script will build a .dmg installation package in the folder called /results.
11. Install the .dmg installation package on an OS X machine.
12. If required, build the Moblin runtimes on Linux.
13. If required, build the Windows Mobile, Java ME, Android, and Symbian runtimes on Windows (see Building the MoSync SDK on Windows).
14. Add the runtimes to the folder:
/Applications/MoSync/profiles
15. Done.
If you want to create an iPhone runtime to use with the Windows version of the MoSync SDK (see building the MoSync SDK for Windows ), here’s how:
1. Follow the instructions above for Preparing the Mac and Getting the MoSync Source Code. (You do not need to get Eclipse or make the MoSync package.)
2. Give your user the correct permissions to the /MoSync folder by entering the following command at the Terminal (replace user with you actual user name):
sudo chown -R user /Applications/MoSync
3. To build the MoSync base prerequisites, go to your cloned MoSync source directory and run the command:
ruby workfile.rb base
4. Now you are ready to build the iPhone runtime from source. In your checked out version of the MoSync SDK trunk do:
cd runtimes/cpp/platforms/iphone cp Classes/impl/config_platform.h.example Classes/impl/config_platform.h ruby buildLibraries.rb cp -R template $MOSYNCDIR/profiles/runtimes/iphoneos/1/
5. Find the runtime in the folder:
/Applications/MoSync/profiles/runtimes/iphoneos/1/
6. Copy it to your MoSync installation directory on your Windows computer in the folder:
\MoSync\profiles\runtimes\iphoneos\1\
7. Done.
These instructions describe how to build the MoSync runtimes for Moblin. The runtimes can then be included when you build the MoSync SDK for Windows or build the MoSync SDK for OS X.
To build the Moblin runtimes you will need a machine running Ubuntu (9.10).
1. First install the runtime dependencies in the Linux terminal:
sudo apt-get install gcc g++ ruby rake subversion rpm sudo apt-get install libgtk2.0-dev libexpat1-dev sudo apt-get install libbluetooth3-dev libsdl1.2-dev sudo apt-get install libsdl-image1.2-dev libsdl-ttf2.0-dev sudo apt-get install libfreeimage-dev libssl-dev
Important! Do not install libsdl-sound -- Moblin does not support this library.
2. Download the source tarball (.tar.bz2) of our current feature release from our website or from our open-source project repository:
Alternatively, get the source tarball for our latest nightly build from our website:
or through TortoiseGit:
git clone https://github.com/MoSync/MoSync.git MoSync git clone https://github.com/MoSync/Eclipse.git Eclipse
Important! You
must download the same version as you downloaded to build the MoSync
SDK for Windows or OS X. If you do not, when you try to use the SDK you
may get an “IDL Version Mismatch” error.
3. Run the Linux runtime builder script in the MoSync source directory::
/tools/RuntimeBuilder/linux/build-linux-runtime-package.sh
4. You will now have two files in the current directory:
runtime.ubuntu.r*.i386.dbg.tar.gz runtime.ubuntu.r*.i386.rel.tar.gz
Rename them to:
runtime.dbg.tar.gz runtime.rel.tar.gz
5. If you are building the MoSync SDK for Windows, move the files to the following folder on the Windows build machine,
c:\mb\MoSyncReleasePackage\profiles\runtimes\moblin\1\
You are then ready to run the SDK build script.
If you are building the MoSync SDK for OS X, copy the runtimes to the machine on which you have installed the MoSync SDK, in the directory:
/Applications/MoSync/profiles/runtimes/moblin/1/
6. Done.
This guide explains how to build the MoSync SDK from source on Linux. It shows you how to set up your build environment and how to build GCC, Pipe-Tool, and the MoRE Emulator.
Please remember that support for Linux is limited and the build system was made for Windows. At the moment, it is only possible to build the MoRE Emulator on Linux, and to run some example programs in the Emulator. It is not possible to build the entire MoSync package (with its IDE) on Linux.
The distributions that we ourselves run at MoSync AB are Ubuntu 8.10/9.04/9.10 and Xubuntu 9.10. This description may work with those distributions. If you're using any other distribution, you may need to adapt these instructions.
There are a few prerequisites to building the MoSync SDK. In Ubuntu, they can be installed by:
sudo apt-get install gcc g++ bison flex ruby rake subversion rpm libgtk2.0-dev libexpat1-dev sudo apt-get install libbluetooth3-dev libsdl1.2-dev libsdl-image1.2-dev libsdl-ttf2.0-dev sudo apt-get install libfreeimage-dev gperf
Note that, since the MoSync SDK is continuously evolving, there may be additional dependencies.
The first step is to set up a directory where the compiled binaries, libraries and SDK header files will reside. From now on we will refer to this directory as the installation directory. The installation directory, which resides wherever you want, should contain the following directory structure:
/<installation-directory>
/bin
/include
/lib
/libexec/gcc/mapip/3.4.6
The /include and /lib directories will be created automatically during compilation, but the other directories should be created manually because we need to compile GCC before the MoSync SDK can be compiled.
Once you have created the directory structure, the environment variable MOSYNCDIR should point to the installation directory. If you use bash then this is accomplished by adding the following line to your .bashrc:
export MOSYNCDIR=<installation-directory>
or in csh by adding the following line to .cshrc:
setenv MOSYNCDIR <installation-directory>
When the lines have been added to your .bashrc or .cshrc the shell must be restarted, you can accomplish this by closing the terminal window and opening it again.
MoSync uses its own GCC backend that generates source code for the MoSync virtual machine. In order to build the MoSync GCC we start by downloading the source code from Google Code, the source code can be placed wherever you want, in this example we are using a directory called gcc_trunk. To download the code run svn:
git clone git://github.com/MoSync/gcc.git gcc_trunk
Now go into gcc_trunk and build the compiler, the compilation will fail when trying to compile libgcc since we do not use the standard linker. But the compiler will already have been built and will be placed in gcc_trunk/build/gcc/gcc/.
We build the compiler by performing the following steps:
cd gcc_trunk ./configure-linux.sh cd build/gcc make
Remember that the compilation will fail when trying to build libgcc, on my Ubuntu machine the error output begins with:
libgcc2.s: Assembler messages: libgcc2.s:1: Error: unknown pseudo-op: `.model' libgcc2.s:2: Error: unknown pseudo-op: `.code' ...
In order for the build scripts to find MoSync GCC it has to be moved to the installation directory:
cp gcc/xgcc gcc/cpp $MOSYNCDIR/bin cp gcc/cc1 gcc/cc1plus $MOSYNCDIR/libexec/gcc/mapip/3.4.6/
The source code for the MoSync SDK also resides on Google Code and is downloaded by:
git clone git://github.com/MoSync/MoSync.git mosync_trunk
MoSync uses its own build system coined 'work'. The build system consists of a set of Ruby files that compiles the MoSync SDK. In each directory that contains source files there is a file called workfile.rb, which instructs the build system how compile the source files. To build the fundamental tools of the MoSync SDK, move to the root of mosync_trunk and invoke:
./workfile.rb CONFIG="debug"
The above command builds the tools and libraries in debug mode but you should also build everything in release mode:
./workfile.rb CONFIG=""
You will then have to copy the font used in the emulator to the bin directory, stand in the root of mosync_trunk and invoke:
cp tools/ReleasePackageBuild/build_package_tools/mosync_bin/unifont-5.1.20080907.ttf $MOSYNCDIR/bin/
When this script is finished make sure that $MOSYNCDIR/bin contains cc1, cc1plus, xgcc, pipe-tool and moemu. You may then try the MAUIex example by performing:
cd examples/MAUI/MAUIex/ ./workfile.rb CONFIG="" cd build/pipe_release/ $MOSYNCDIR/bin/moemu -program program -resource ../resources
These coding conventions are guidelines for developers creating MoSync code. These conventions are largely inspired by and derived from existing ones in well-known programming environments such as Java and SDL. As such, they shouldn't come across as exotic to any moderately experienced programmer.
All header files should have #define guards to prevent multiple inclusion. The format of the symbol name should be <PROJECT>_<PATH>_<FILE>_H_.
Don't use an #include when a forward declaration would suffice.
Define functions inline only when they are small, say, 10 lines or less.
When defining a function, parameter order is: inputs, then outputs.
Use standard order for readability and to avoid hidden dependencies: C library, C++ library, other libraries' .h, your project's .h.
Prefer nonmember functions within a namespace or static member functions to global functions; use completely global functions rarely.
Place a function's variables in the narrowest scope possible, and initialize variables in the declaration.
Static or global variables of class type are forbidden: they cause hard-to-find bugs due to indeterminate order of construction and destruction.
In general, constructors should merely set member variables to their initial values. Any complex initialization should go in an explicit Init() method.
You must define a default constructor if your class defines member variables and has no other constructors. Otherwise the compiler will do it for you, badly.
Use a struct only for passive objects that carry data; everything else is a class.
Composition is often more appropriate than inheritance. When using inheritance, make it public.
Only very rarely is multiple implementation inheritance actually useful. We allow multiple inheritance only when at most one of the base classes has an implementation; all other base classes must be pure interface classes tagged with the Interface suffix.
Interfaces should be named using an I- prefix. Example: IMySexyInterface
Make data members private, and provide access to them through accessor functions as needed. Typically a variable would be called mFoo and the accessor function getFoo(). You may also want a mutator function setFoo().
Use the specified order of declarations within a class: public: before private:, methods before data members (variables), etc.
Prefer small and focused functions.
All parameters passed by reference must be labeled const.
We strongly recommend that you use const whenever it makes sense to do so.
Code should be 64-bit and 32-bit friendly. Bear in mind problems of printing, comparisons, and structure alignment.
Be very cautious with macros. Prefer inline functions, enums, and const variables to macros.
Function names, variable names, and filenames should be descriptive; eschew abbreviation. Types and variables should be nouns, while functions should be "command" verbs.
Type names start with a capital letter and have a capital letter for each new word, with no underscores: MyExcitingClass, MyExcitingEnum.
They start with a capital letter and have a capital letter for each new word, with no underscores. A m- prefix is used for member variables. A s- prefix is used for static variables. For instance: myExcitingLocalVariable, mMyExcitingMemberVariable, sMyExcitingMemberVariable
Use capitals and underscore as a separator: DAYS_IN_A_WEEK.
Regular functions have mixed case; accessors and mutators match the name of the variable: myExcitingFunction(), myExcitingMethod(), getMyExcitingMemberVariable(), setMyExcitingMemberVariable().
Enumerators should be named either like constants or like macros: ENUM_NAME.
You're not really going to define a macro, are you? If you do, they're like this: MY_MACRO_THAT_SCARES_SMALL_CHILDREN.
Start each file with a copyright notice, followed by a description of the contents of the file.
Every class definition should have an /** accompanying comment */ that describes what it is for and how it should be used.
Every function should have a /** declaration comment */ which describes use of the function, using @param and @return syntax.
In general the actual name of the variable should be descriptive enough to give a good idea of what the variable is used for. In certain cases, more comments are required.
In your implementation you should have comments in tricky, non-obvious, interesting, or important parts of your code.
Pay attention to punctuation, spelling, and grammar; it is easier to read well-written comments than badly written ones.
Each line of text in your code should be at most 80 characters long.
Preprocessor directives should not be indented but should instead start at the beginning of the line.
Sections in public, protected and private order, each indented one space.
Inconsistent
use of indents, tabs and spaces is a problem in much the same way as
inconsistent naming is. Most text editors have the necessary options.
For example, in Visual Studio, go Tools > Options > Text Editor
> C/C++ > Tabs.
The
following should apply to all MoSync code: one level of indention
equals one tab. A tab is defined as the ASCII character \t. The actual
screen size of the indents can thus be set by and for each user with no
ill effects for others.
Syscalls are named using a ma- prefix. Only actual Syscalls and IOCTLs are named this way. Examples:
void maDisposeLayer(Handle layer);
void maSetMap(Handle layer, Handle srcMapResource, int destX, int destY);
Library functions that are directly associated with the manipulation of some complex datatype (such as a struct) should be prefixed with the name of the type followed by an underscore, followed by the function name in camel case. Examples:
MAVec3_normalize(MAVec3* v); MARect_containsPoint(const MAVec3* v, const MAPoint2d* p);
Library functions that are not directly and strongly related to a datatype should be prefixed with an identifying name for the library, which should always contain an initial 'MA'. Examples:
MAMath_solveLinearSystem(); MAInet_sendMail();
Syscalls
and extensions constitute the lowest-level APIs available in MoSync.
They are typically directly mapped to underlying platform features and
are also subject to a number of restrictions:
The number of parameters is limited to four. If more information must be passed, the stack or struct pointers can be used.
Parameters cannot be function pointers. If a notification mechanism is required, one is required to make use of (custom) events.
The
only allowed parameter types are primitive IDL types (see IDL
documentation) and IDL structs that actually are declared in the
relevant IDL file.
The only allowed return types are primitive IDL types.
MoSync memory cannot be allocated within syscalls, other than in the specific case of built-in or custom events.
Allocation, manipulation and deallocation of native objects (resources) is typically implemented by means of handles.
Typically,
there is an maCreateX() function, which takes a placeholder handle to
represent the allocated native object. Subsequent access to this object
is provided through other syscalls that accept handles as their first
parameter.
Finally,
all objects are destroyed using maDestroyObject(). As an example, these
are some functions that create and manipulate images:
void maCreateImageFromData( in Handle placeholder, in Handle data, in int offset, in int size ); void maCreateImageRaw( in Handle placeholder, in MAAddress src, in Extent size, in int alpha ); void maDrawImage( in Handle image, in int left, in int top ); void maDrawImageRegion( in Handle image, in MARect srcRect, in MAPoint2d dstPoint, in int transformMode );
Since MoSync doesn't support user-created threads, it is important to provide asynchronous interfaces to time-consuming native functionality such as network communication. Since syscalls can't accept function pointers, the central MoSync event system is used to provide progress notification. A few built-in event types are provided in the EVENT struct, but there's also a void* provided that can be used for custom events.
We encourage everyone to help us develop MoSync, and writing new extensions for MoSync is probably the most common thing you will want to do. In this topic we introduce you to some important core concepts that you need to understand and lead you step-by-step through creating an API extension.
This topic assumes that you have a good understanding of how to use MoSync, that you understand the build process, and that you can build the MoRE runtime in Visual Studio. It also assumes that you have some basic familiarity with the MoSync code.
In this section we introduce some core concepts that you will need to understand when you write extensions.

User code includes all the code that you write when you create an application with MoSync along with some of the MoSync libraries, such as the MAUI library.
A runtime is the thing that executes the user code on the device. For each platform that MoSync supports, there is a different runtime. Some runtimes are written in C++, others like the J2ME and Android runtimes are written in Java. Each runtime has two parts: one that executes the user code and one that interfaces to it to provide low-level services.
Communication between the user code and a runtime is through syscalls and events. Syscalls are like the traditional calls a user application makes to an OS kernel. Whenever the user code needs to do something it cannot do on its own, such as creating a socket connection, it performs a syscall to the runtime. To create a socket connection, for example, the syscall is maConnect.
A syscall is an actual instruction which the runtime traps during code execution. The instruction only has one argument, and that is the syscall number. A syscall, like any ordinary function call, can return a value. A syscall can do pretty much any thing you'd like it to do, but what it can never do is to block. If the syscall cannot finish immediately, such as when waiting for socket data, it needs to return and have the blocking call run in a thread in the background. Once it has finished, it will return the result through events which the user fetches through yet another syscall called maGetEvent.
The maIOCtl syscall is a special syscall which is meant for extensions which aren't supported or fully supported on all the MoSync runtimes. What this means in practice is that anything that isn't part of the standard API, that is anything that isn't the least common denominator on all platforms, will be implemented through an maIOCtl. Implementing an MaIOCtl is simpler than implementing an entirely new syscall, and is what you will be using to implement your extensions. The only limitation that the maIOCtl syscall has is that it only takes three parameters. But on the bright side, any or all the three can be user defined structures, which means that you can always pass all the parameters you like in a structure.
Any syscall starts its life in a file called maapi.idl. Here all syscalls, events, and event types (among other things) are defined. To minimize the amount of code redundancy, we have created a tool called idl2 which takes the maapi.idl file and generates several important files:
int maFrameBufferGetInfo ( out MAFrameBufferInfo info );#if IX_SOMETHING . . . #end For maIOCtl declarations the block ends up in a separate file with a similar name. It is in this block that you will be writing API extensions. The idl2 tool also produces wrapper code for any extensions that have been written through maIOCtl. This is another one of the advantages of the idl2 tool. It takes care of all the little details and updates every where that needs to be updated. The wrapper code might look something like this (from libs/MAStd/IX_CELLID.h):
static inline int maGetCellInfo ( MACellInfo* pInfo ) { return maIOCtl( 56, (int)pInfo, 0, 0 ); } In this example we will write a simple extension as an maIOCtl, we will pass a structure with 16 chars in it, and will return the same chars through an event.
We need to make four changes in this file:
Edit tools/idl2/extensions.h file and add to it "#define IX_TUTORIAL". This is needed to process anything that is declared between '#if ...' and '#endif' in the maapi.idl file. Here is the start of our example:
#define IX_RESOURCE_TYPES #define IX_GUIDO #define IX_WLAN #define IX_FILE #define IX_RECORD #define IX_CELLID #define IX_CALL #define IX_STREAMING #define IX_CONNSERVER #define IX_OPENGL_ES #define IX_AUDIOBUFFER #define IX_SEGMENTED_DATA #define IX_PIM #define IX_TUTORIAL
The MAEvent structure contains a field called "type", this field is an integer which identifies the event type. So next we need to add a constant which identifies our custom event. At the end of the block called "constset int EVENT_TYPE_" we add our custom event type:
#if IX_TUTORIAL
TUTORIAL = 10001;
#endifNote: To avoid collisions with future extensions from the MoSync team, we suggest that you always choose a large value for the event constant.
In the version of maapi.idl that we are working with, the entire block looks like this:
constset int EVENT_TYPE_ {
/**
* This event is posted when the operating system sends MoSync a command
* to exit. Causes include the OS shutting down and OS-controlled user
* commands.
* \see maGetEvent()
*/
CLOSE = 1;
KEY_PRESSED = 2;
KEY_RELEASED = 3;
/// Connection
CONN = 4;
/// Bluetooth discovery
BT = 5;
#if IX_GUIDO
/// Has MAEvent::key be the identifier for the TTS session, as returned
/// by maStartSpeaking().
TTS = 6;
#endif //IX_GUIDO
#if IX_WLAN
/// Uses MAEvent::state.
WLAN = 7;
#endif //IX_WLAN
POINTER_PRESSED = 8;
POINTER_RELEASED = 9;
POINTER_DRAGGED = 10;
#if IX_CALL
/// Has MAEvent::state be one of the \link CALLSTATE \endlink constants.
CALL = 11;
#endif //IX_CALL
/**
* While MoSync doesn't have focus, no key events will arrive and the
* screen will not be updated. If the keypad is locked, no application
* will have focus.
* \see maLockKeypad
*/
FOCUS_LOST = 13;
FOCUS_GAINED = 14;
#if IX_STREAMING
/**
* Has MAEvent::data point to a MAStreamEventData.
*/
STREAM = 15;
#endif //IX_STREAMING
//#if IX_LOCATION
/// Has MAEvent::data point to an MALocation.
LOCATION = 16;
/// MAEvent::state is one of the \link #MA_LPS_AVAILABLE MA_LPS
/// \endlink constants.
LOCATION_PROVIDER = 17;
//#endif //IX_LOCATION
#if IX_AUDIOBUFFER
/// MAEvent::state is \> 0 when the audio stream is waiting for more data,
/// or \< 0 on error.
AUDIOBUFFER_FILL = 18;
#endif
SCREEN_CHANGED = 21;
#if IX_TUTORIAL
/// Just a simple event type added for the tutorial
TUTORIAL = 10001;
#endif
}Now that we have a new event type, it is time to create a way through which we can return data to the user from an event. This can be accomplished in two ways, one is to allocate dynamic memory in the runtime and let the runtime copy that memory to user memory. The runtime will also update the data pointer in the MAEvent struct. To do this, you have to write a few macros in the right places. The second method is to create a new struct with the data that you need to return to the user and embed this in the MAEvent struct. The second method has the advantage of being a bit simpler, but at the cost of bloating the MAEvent struct. For the sake of simplicity, we will only go through the later method in this document. So let's get started.
First, we define our struct. We can call it MATutorialEvenData, it needs to contain 16 chars. The next step is to embed it in the MAEvent struct, in the revision of the code base that the author is working with, the entire code will look like this.
struct MATutorialEventData {
char m_data[16];
}
struct MAEvent {
/**
* One of the \link #EVENT_TYPE_CLOSE EVENT_TYPE
* \endlink constants.
*/
int type;
union {
struct {
/**
* In KEY events, this will be one of the
* \link #MAK_UNKNOWN MAK \endlink constants.
*/
int key;
/**
* In KEY events, this will be the native keycode.
*/
int nativeKey;
} ked;
/**
* Tutorial structure
*/
MATutorialEvenData tutorial;
/**
* In POINTER events, this will be the location of the pointer.
*/
MAPoint2d point;
/**
* In \link #EVENT_TYPE_BT BT \endlink events, this will be a value \>= 0 or
* one of the \link #CONNERR_GENERIC CONNERR \endlink constants.
*/
int state;
/**
* Valid only in CONN events.
*/
MAConnEventData conn;
/**
* Used by custom events. See invididual event descriptions.
*/
void* data;
}
}
At this point we have all the parts in place to return data through events, now we just need a way of making a call to the runtime. This is where syscalls and maIOCtl comes in. We will define a new IOCtl in the maIOCtl block (after the opening bracket and before the closing bracket). The maIOCtl will look like this:
#if IX_TUTORIAL
int maSyscallTutorial(in MAString data);
#endif //IX_TUTORIALwhere MAString is a defined as 'typedef char* MAString' at the top of the maapi.idl file.
Now that we've made actual changes to the syscall interface, we need to regenerate all the auto generated files that have to do with syscalls. In Visual Studio, build tools/idl2 and run it. Your output should look like this,
If you instead get this:
D:\workspace\repo-new\MoSync2.3\tools\idl2>Debug\idl2.exe Error opening file "opengl_generated.idl" in maapi.idl on line 2383 Exception: Unknown exception
Then you need to build the opengl_generated.idl, run tools\GLWrapperGenerator\build.bat and run the idl2 tool again.
You probably noticed that for most files it generates three different versions of it. For instance, the IX_TUTORIAL extension goes in:
#ifndef IX_TUTORIAL_DEFS_H #define IX_TUTORIAL_DEFS_H /** \brief A hash of the abstract representation of the API described in this file. * Identifiers, declarations and definitions are included in the calculation of the hash, * but documentation is not. */ #define MAIDL_HASH ((int)0xc2fcb710) /// Just a simple event type added for the tutorial #define EVENT_TYPE_TUTORIAL 10001 #define maIOCtl_maSyscallTutorial 247 #endif //IX_TUTORIAL_DEFS_HIn here we have hash (which is discussed in section 4), the event ID, and syscall ID. We will need these to write the code which handles the maIOCtl call in the runtime. The java version contains similar things.
In the next file we have:
#ifndef IX_TUTORIAL_H
#define IX_TUTORIAL_H
#ifdef __cplusplus
extern "C" {
#endif
/// Just a simple event type added for the tutorial
#define EVENT_TYPE_TUTORIAL 10001
static inline int maSyscallTutorial(const char* data) {
return maIOCtl(247, (int)data, 0, 0);
}
#ifdef __cplusplus
}
#endif
#endif //IX_TUTORIAL_H
As you see, this file is a bit different, there is an actual C function in there, this is because we wrote our new syscall/extension in the maIOCtl block. The idl2 tool knows that anything inside that block is not an actual syscall, but goes through the maIOCtl syscall. The first parameter is the maIOCtl ID, and in the previous file you can see that the preproccesor define "maIOCtl_maSyscallTutorial" is set to 247, which is quite practical and the reason that the previously discussed hash is needed to make sure that both the user libraries and the runtime agree on the same syscall interface.
By this point, we have all the parts in place to do the maIOCtl on the user side. Now you need to write the code on the runtime side which actually handles the IOCtl. In this document, the only runtime we will modify is MoRE, but modifying the other runtimes is similar.
In the source directory, there exists a file runtime/cpp/platforms/sdl/SyscallImpl.cpp, this file handles all the syscalls in the SDL runtime (MoRE). In the Visual Studio project you can find it under Platforms/cpp/sdl/SyscallImpl.cpp. Open it, and add the include "#include <helpers/CPP_IX_TUTORIAL.h>", this will include the definitions that have to do with our example.
Next we need to add the actual code for handling the IOCtl. So, scroll down to the part that says:
SYSCALL(int, maIOCtl(int function, int a, int b, int c)) {This is the actual maIOCtl syscall. In it you will find a big switch statement. We need to add our own handler to this switch case. So just before the default case, we add this piece of code:
case maIOCtl_maSyscallTutorial:
{
char * data;
MAEvent myevent;
// Get pointer to memory
data = (char*)SYSCALL_THIS->GetValidatedMemRange( a, 16 );
// Copy to event
myevent.type = EVENT_TYPE_TUTORIAL;
memcpy( myevent.tutorial.m_data, data, 16 );
// Put in event queue
gEventFifo.put( myevent );
// Return success code
return 1;
} Let's go through the parts of this code. Firstly, a pointer to the argument that was passed to the maIOCtl from the user side, is fetched. The method GetValidatedMemRange takes a pointer to the user side memory and the number of bytes that the pointer points to. If the memory is valid, a pointer will be returned. Otherwise a panic will occur. Secondly, the event type is set and the ASCIIZ string passed by the user is copied to the event structure. Thirdly, the event is put in the event queue, from where it can be fetched by the user through the maGetEvent syscall. And lastly, we return from the maIOCtl syscall.
Assuming that you have Visual Studio correctly set up and you can build MoRE, rebuild MoRE. The executable will be copied to your MoSync installation path (MOSYNCDIR/bin).
This step is very important. Any change you make to the IDL file might change the binary interface of syscalls (specfically syscall IDs). Because of this there is a hash in the generated maapi.h file that is verified against the runtime to make sure the user code and the runtime have been built with the same interface. So we need to remove all the old files and rebuild the libs:
If you have gotten everything to work this far, there should be only one last step remaining, and that is to actually test that it works as expected. In the MoSync IDE, create a project and create in it a file called main.c containing the following code:
#include <ma.h>
#include <IX_TUTORIAL.h>
int MAMain ( )
{
while ( 1 )
{
MAEvent e;
while ( maGetEvent( &e ) != 0 )
{
switch ( e.type )
{
case EVENT_TYPE_CLOSE:
return 0;
case EVENT_TYPE_KEY_PRESSED:
case EVENT_TYPE_POINTER_PRESSED:
maSyscallTutorial( "world!" );
break;
case EVENT_TYPE_TUTORIAL:
printf( "Hello %s\n", e.tutorial.m_data );
break;
}
}
}
return 0;
}If you've done everything correctly, this code will compile and run just fine. And in that case, congratulations, you've just written your first MoSync extension!