Wednesday, 25 May 2011

BMTC & Android

Recently, I noticed interactive display panels on BMTC - Vayu Vajra (BIA) Volvo bus, while commuting to office (Hebbal to Marathhalli). I’m really excited to say that these are powered by Google’s Android Operating System.

1

Good part is, it includes a "Webkit" browser for free internet browsing while you travel. What else you want when you are stuck in traffic? :)

I could confirm that its using Android OS and Webkit browser by examining the UserAgent:

Mozilla/5.0(Linux; U; Android 2.1-update1; en-us; Generic Build/ECLAIR) AppleWebkit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17

See below snapshot.

2

Along with the in-built browser, it also lists few useful apps - Youtube, facebook, Sudoku, Weather, Stocks, News etc.

For me, these apps looks to be web-apps which are non-native and not even Java based.

Advertising is another interesting aspect.
The lower part of the display has local retailer advertisements. BMTC may be earning a good revenue out of it. :)

Overall experience of using internet on BMTC Vayu Vajra was awesome! I'm really amazed by abilities of Android as a platform. Its not just phone anymore.

You may not be surprised to see these devices one day in your car. :)
I'll wait for that day!

Sunday, 31 October 2010

The Age of ‘WebApps’

Looks like there is a big paradigm shift from ‘native’ apps to so-called ‘WebApps’ nowadays!

Listing the WebApps which I personally use in daily life and like the most.

Do you come across any? Let me know!

dropbox_logo_home Store, Sync, Share files online.
password_manager_clipperz_logo Password Manager.
rtm_logo2 To-Do list manager.
evernote_logo Remember everything on any device.
meebo-logo Instant messaging program which supports multiple IM services.
tunewiki Creates social media players for cellphones and handheld devices with huge library of lyrics.
ril Save Pages to Read Later. Offline reading!
youtube Web videos!
google_reader Great feeds reader from Google.
twitter-logo(1) Twitter!
wikipedia Wiki.
floor_planner Bookmark manager.
foursquare_logo Geo-tagging.
floor_planner

Create floor plans, house plans and home plans ‘online’.

facebook facebook!

Sunday, 24 October 2010

no service found for - "com.nokia.qt.mediaplayer"

Of late, I was trying to build QtMobility on Ubuntu, specifically experimenting with QtMultimedia feature set.

In the process, I stumbled on this (not so) strange issue which frustrated me for a log time. I was using Qt4.7 + QtMobility v1.1.0 Beta.

Building QtMobility was not an issue. However, when I tried to play a multimedia content in demo/player app , it just couldn't play it complaining :

no service found for - "com.nokia.qt.mediaplayer"
It was clearly a mistake of mine not having a look at the 'configure' warning messages :
Reading /home/pranaray/qt-mobility-opensource-src-1.1.0-beta2/plugins/multimedia/multimedia.pro
Project MESSAGE: QtMultiMedia checking for gstreamer...
Package gstreamer-0.10 was not found in the pkg-config search path.
Perhaps you should add the directory containing `gstreamer-0.10.pc' to the PKG_CONFIG_PATH environment variable
No package 'gstreamer-0.10' found
Package gstreamer-base-0.10 was not found in the pkg-config search path.
Perhaps you should add the directory containing `gstreamer-base-0.10.pc' to the PKG_CONFIG_PATH environment variable
No package 'gstreamer-base-0.10' found
Package gstreamer-interfaces-0.10 was not found in the pkg-config search path.
Perhaps you should add the directory containing `gstreamer-interfaces-0.10.pc' to the PKG_CONFIG_PATH environment variable
No package 'gstreamer-interfaces-0.10' found
Package gstreamer-audio-0.10 was not found in the pkg-config search path.
Perhaps you should add the directory containing `gstreamer-audio-0.10.pc' to the PKG_CONFIG_PATH environment variable
No package 'gstreamer-audio-0.10' found
Package gstreamer-video-0.10 was not found in the pkg-config search path.
Perhaps you should add the directory containing `gstreamer-video-0.10.pc' to the PKG_CONFIG_PATH environment variable
No package 'gstreamer-video-0.10' found
The message was clearly warning about the missing gstreamer library packages.
I had to install libgstreamer0.10-dev & libgstreamer-plugins-base0.10-dev packages to resolve the issue.
sudo apt-get install libgstreamer0.10-dev libgstreamer-plugins-base0.10-dev
I also installed few additional gstreamer plugins along with the above said packages to be able to play mp3 and other media content formats.

Tuesday, 24 August 2010

Bypassing Same-Origin policy on Firefox.

Same-origin policy is an essential feature implemented in most of the modern browsers to shield against malicious scripts execution. It simply blocks javascripts belong to domains other than the one which is currently being executed.

However, for development and testing of mash-ups, web apps or widgets, its sometimes required to disable this, so that a local javascript of my widget could reach Twitter or Foursquare webserver to pull the data via AJAX.

Firefox as a leader desktop browser simply block such attempts denying the cross origin AJAX requests.

Fortunately, Firefox’s settings are configurable and it allows us to disable such restrictions so that it can bypass the Same-origin policy.

Here is a brief summary of what I discovered for achieving this. Special thanks to Raghava for helping me out to reach to it.

Step-1

  • Launch Firefox browser, navigate to "about:config".
  • Set the property "security.fileuri.strict_origin_policy" to “false

Step-2

  • Update the javascript by add this line before creating any XHR request:

netscape.security.PrivilegeManager.enablePrivilege(”UniversalBrowserRead”);

Example :

// Enable Universal Browser Read
try{

netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");

}
catch(e){

alert(e);

}

// create XmlHttpRequest Object
var xmlhttp = new XMLHttpRequest();

That's it! You are now all set to access any cross origin resource from a local web app running on Firefox.

Please remember to revert this setting back so that your web is back to safe mode :)

Sunday, 11 July 2010

Building QtWebKit on Windows – Few common issues

In continuation to my last blog entry, here I’m trying to capture few common problems that I encountered along with possible solutions for them, in the process of building QtWebKit for windows.

Listing out issues and followed by possible solution for them:

1. ERROR: qmake missing but required to build WebKit.

Make sure QTDIR env variable is set and PATH variable includes path to Qt bin folder.

set QTDIR=C:\Qt\4.6.3

set PATH=%PATH%;%QTDIR%\bin;

2. ERROR: flex, bison, gperf missing but required to build WebKit.

Have you installed GNUWin32 tools? Also, include GNUWin32 bin path under PATH env variable.

set PATH=%PATH%;C:\GnuWin32\bin;

3. 'nmake' is not recognized as an internal or external command

Make sure you have installed MS Visual Studio. Also try running the webkit build script from within Visual Studio 2008 Command Prompt.

4. Failed to generate WebCore's derived sources!Can't locate Switch.pm in @INC

Is Active Perl installed? Active Perl v5.10 or higher is required. Update PATH env variable with perl bin folder paths.

set PATH=C:\Perl\site\bin;C:\Perl\bin;%PATH%

5. Cannot open include file: 'windows.h': No such file or directory

Microsoft Platform SDK need to be installed. INCLUDE and LIB env variables need to be updated.

set INCLUDE=%INCLUDE%;C:\Program Files\Microsoft SDKs\Windows\v6.0\Include

set LIB=%LIB%;C:\Program Files\Microsoft SDKs\Windows\v6.0\Lib

6. JavaScriptCore\DerivedSources\chartables.c (13) : error C2466: cannot allocate an array of constant size 0

This issue arises because of usage of wrong version of perl to generate derived sources.

To solve this issue, we need to install Active Perl v5.10 and regenerate derived sources. For regenerating the derived sources, delete the ‘WebKitBuild’ folder and restart the build by launching the ‘build-webkit’ script again.

7. LINK : fatal error LNK1210: exceeded internal ILK size limit; link with /INCREMENTAL:NO

Not sure why visual studio crib with such a linker error. As a quick solution, we need to disable incremental linking.

Update webkit.pri by adding linker flag to disable incremental linking:

QMAKE_LFLAGS += /INCREMENTAL:NO

Restart the build by launching the ‘build-webkit’ script again.

Building QtWebKit on Windows

Intention of this and the following blog entries is to record my experiences while building QtWebKit on Windows with MS Visual Studio 2008. I’ve tried to gather few common issues and solutions for them which I came across in the process of compilation.

Which compiler?

I opted for Microsoft Visual Studio 2008 as I had it already installed on my laptop.

However, QtWebKit building instructions indicate that we can use either MSVS or MinGW.

Note that, rest of this article only talks about using MS Visual Studio (nmake) as the compiler. If you are willing to choose MinGW, please follow instructions here.

Windows Platform SDK

Download and install Windows Platform SDK. Make sure INCLUDE env variable has the SDK include path:

ex : C:\Program Files\Microsoft SDKs\Windows\v6.0\Include

and LIB env variable includes SDK lib path.

ex : C:\Program Files\Microsoft SDKs\Windows\v6.0\Lib

Active Perl v5.10

Install Active Perl later than v5.10 from here. Ensure PATH variable includes:

C:\Perl\bin;C:\Perl\site\bin

Qt for Windows SDK

Download and install latest available Qt for windows from http://qt.nokia.com/downloads. Qt can either be downloaded as an SDK or as precompiled binary set.

When I downloaded SDK, I noticed that the SDK binaries were compiled with MinGW. This means, its incompatible with my MSVC compiler. So, I had to rebuild Qt source from scratch after installing Qt SDK.

As an alternative to this approach, we can download and install Qt binaries which are precompiled with MSVC.

Luckily Qt provides prebuilt binaries compiled with both MinGW and MSVC-2008. You can choose either of that, based on the compiler you are using.

Ensure QTDIR env variable is created and pointing to Qt install folder.

ex : QTDIR=C:\Qt\4.6.3

Also, PATH variable need to include the Qt binary path:

C:\Qt\4.6.3\bin

GNUWin32 tools

Download and install following GNUWin32 tools :

Include install path under PATH env variable (ex: C:\GnuWin32\bin)

Checking out WebKit source

Check out source from WebKit SVN trunk http://svn.webkit.org/repository/webkit/trunk

I experienced a glitch while checking out webkit repository. Have a look at my previous blog entry for more info on that.

Building QtWebkit

Now, we are ready with all the pre-requisites. To build QtWebKit, we need to run build-webkit script passing –-qt and -–debug or --release parameters.

Following script execution builds the release version of QtWebKit binaries:

perl WebKitTools\Scripts\build-webkit --qt --release

for debug version of binaries :

perl WebKitTools\Scripts\build-webkit --qt --debug

References

http://trac.webkit.org/wiki/BuildingOnWindows
http://trac.webkit.org/wiki/BuildingQtOnWindows
http://webkit.sed.hu/blog/20091027/building-qtwebkit-windows
http://webkit.org/building/build.html
http://webkit.org/building/tools.html

Sunday, 4 July 2010

Excluding folders while checking out an SVN repository

Blogging this entry out of frustration of not finding an easier way to exclude selected folders while ‘svn checkout’ing a huge svn repository.

I had to checkout all folders from webkit trunk repository except this folder – LayoutTests, which was not really necessary for my work. I was not interested in downloading it, as it was really huge and could consume lots of time and bandwidth in downloading it.

Unfortunately ‘svn:ignore’ couldn’t helped me in achieving this as I was thinking earlier :(. ‘svn:ignore’ is meant only for ignoring files/folders while committing/adding them to repository, but not for checking out or updating a repository.

After googling for a while came to know that only way of achieving this is to use Sparse Checkouts feature which was introduced since SVN v1.5.

However, solution is not straight forward. we have to checkout with an option of --depth=immediates which would checkout all files and folders (excluding everything from sub-folders). Then ‘svn up’ individual folder which we are interested in.

I was really not satisfied by this solution. This doesn’t help much in addressing the problem if we do have large number of folders and are in different levels in folder hierarchy.

Can this be a new feature for svn toolset? or do any one have a better approach for this problem? Let me know.

Sunday, 17 January 2010

Swap space on Ubuntu

Had to compile Qt on Ubuntu virtual machine running on Win XP. Compilation used to fail repeatedly for QtGui component with the following error:

collect2: ld terminated with signal 9 [Killed]

With not much error information, I was clueless on what was going wrong!

Google’ing this error resulted me to learn that swap space reserved was too less (or not at all reserved?) which was required for Qt compilation.

Then tried using the swapon utility command to check how much swap space is already reserved:

sudo swapon –s

Found that nothing was listed at all!

Executed the following commands to create a swap space of 512MB.

sudo dd if=/dev/zero of=/mnt/512Mb.swap bs=1M count=512
sudo mkswap /mnt/512Mb.swap
sudo swapon /mnt/512Mb.swap

This reserved 512MB of swap space, which solved my Qt compilation issues.

reference : https://help.ubuntu.com/community/SwapFaq

Saturday, 17 October 2009

Developing Applications with Nokia WRT - VTU EduSat ppt

Check out this SlideShare Presentation on Developing Applications with Nokia Web Runtime.
This was broadcasted live to all VTU colleges in Karnataka on 14th Sept 2009 as part of VTU's EDUSAT programme.

My self and Raghava had an opportunity to represent Nokia's Web Runtime.
We tried to present the latest developments in Nokia's WebRuntime.


Sunday, 6 September 2009

Dependency Walker for Windows binaries

I find Dependency Walker a very useful utility. This helps us to scan any of windows binaries (exe, dll ...).

It can dissect almost any type of windows binary file, to show up all possible details hidden within.

Listing few of the details this utility can provide,

  • Basic binary properties Ex: physical path, version info, etc.
  • Exported functions with their signatures and ordinal numbers.
  • Recursive list of dependent libraries and their details.

It didn’t took much time for me to discover the power of this tiny tool which is distributed as apart of MS Visual Studio Tools. This can also be downloaded for free at http://www.dependencywalker.com/.

Below is one of such situation, where this tool helped me to rapidly identify and debug the problem.

I was building Qt for Win with ‘-openssl-linked’ option and this required me to download the openSSL libraries separately. I had downloaded and copied ‘libeay32.dll’ under Qt’s bin folder.

Even though Qt compiled without any problems, I had issues with launching few of the processes which had dependency over libeay32.dll. For some reasons, loader started complaining about missing ordinal in libeay32.dll.

Dependency walker came into rescue. I simply loaded the failing process into DependencyWalker and it listed all dependent DLLs with respective details. I could just walk to the libeay32.dll and examine its version.

There you go! It was loading an older version of DLL which had been installed as part of Wireless monitor app. Since PATH variable had the wireless app’s path occurring before Qt’s bin path, it was always picking the older DLL from wrong location which caused the issue.

It hardly took me few minutes to identify and fix the issue.

Hope this is useful :)

Thursday, 13 August 2009

HTML5 video

Just wanted to embed a video using HTML5 video feature.  The source looks very simple!

<video controls="controls" src="http://tinyvid.tv/file/3ifyc1xrvwkjr.ogg" tabindex="0">
   <p>
   Sorry, your browser doesn't support the <video> element. You'll need a browser that can playback Ogg media using HTML5 video and audio tags.
   </p>
</video>

This tries to embed one of my favorite music video – In the Shadows by The Rasmus :)

Please use the latest versions of Chrome or Firefox to experience the embedded video. The latest versions of Chrome and Firefox are already supporting the HTML5 video and audio features.

Have fun!

Reference : HTML5 spec

Wednesday, 22 July 2009

Resolving the exported symbols from a Symbian DLL

Symbian OS optimizes DLL program code to save ROM and RAM space, by offering only "lookup by ordinal" and not "lookup by name".

Symbian OS does not offer “lookup by name” because this adds an overhead to the size of the DLL (storing the names of all the functions exported from the library is wasteful of space). Instead, Symbian OS only uses link by ordinal, which has significant implications for binary compatibility.

If we are loading a DLL dynamically and need to resolve a exported function address, we need to use the following RLibrary API, which takes an integer parameter representing the ordinal number of the exported function.

TLibraryFunction RLibrary::Lookup(TInt anOrdinal)

Luckily, as part of POSIX for Symbian (P.I.P.S), widely known as Open-C library, we can achieve “lookup by name” with a Symbian DLL.

This is possible only if the library is built as STDDLL.

This allows us to have the POSIX like behavior for resolving the exported DLL symbols even on Symbian. Following POSIX like APIs can be used on Symbian provided the DLL is built as STDDLL.

void *dlopen(const char *filename, int flag);
void *dlsym(void *handle, const char *symbol);
void dlclose(void *handle);

An example with source using the PIPS libraries is here.

Sunday, 31 May 2009

Digest authentication with Apache

This article is in continuation with previous and talks about setting up digest authentication with Apache.

There are few changes compared to the steps for Basic authentication.

1. Generating the password file for digest auth.

htdigest -c digest.txt secret prash

digest.txt is the password file, secret - the realm and prash is the username.

2. Create htaccess.acl under c:\wamp\www\digest-auth\ with following data

AuthUserFile C:\wamp\bin\apache\Apache2.2.11\bin\digest.txt
AuthName "Protected by Digest auth"
AuthType Digest
AuthDigestProvider file

<Limit GET POST>
require valid-user
</Limit>

‘AuthDigestProvider file’ is an additional property that needs to be mentioned for proper working of digest authentication.

3. And, last but not the least. Enable auth_digest_module by un-commenting the following line if its already commented in httpd.conf.

LoadModule auth_digest_module modules/mod_auth_digest.so

Reference : http://httpd.apache.org/docs/2.2/mod/mod_auth_digest.html

Setting up HTTP Basic authentication with Apache

Last week, I had a chance to setup our test Apache server for Basic and Digest authentication. The setup was required to verify few of the HTTP authentication related test cases.

I’m blogging it here so that I’ll not forget, if I need it again :)

I had WAMP Server v2.0  which included Apache v2.2.11 web server.

Setting up Basic authentication was straight forward.

1. Update http.conf by adding :

AccessFileName htaccess.acl .htaccess

An htaccess file can be used to modify the Apache configuration on a per-directory basis.

On some operating systems ‘htaccess.acl’ is not required. Ex, on Linux, you can just mention it as .htaccess. This is because, on Linux you can create a file with name .htaccess.

2. Add “Directory” tag into http.conf as shown below :

<Directory "c:/wamp/www/basic-auth/">
    Options None
    AllowOverride all
    Order Deny,Allow
</Directory>

c:/wamp/www/basic-auth/ is the folder which needs to be secured by the authentication scheme which we are trying to impose.

3. Next step is to create password file.

cd C:\wamp\bin\apache\Apache2.2.11\bin
htpasswd -c pwd.txt prash

This prompts for the password for the username – ‘prash’. After supplying the password we will be ready with the password file – ‘pwd.txt’ under ‘C:\wamp\bin\apache\Apache2.2.11\bin’.

4. Create the htaccess file - ‘htaccess.acl’ file with the following data.

AuthUserFile C:\wamp\bin\apache\Apache2.2.11\bin\pwd.txt
AuthName "Protected"
AuthType Basic

<Limit GET POST>
require valid-user
</Limit>

This specifies which password file need to be considered for the authentication – ‘C:/wamp/bin/apache/Apache2.2.11/bin/pwd.txt’ also the type of authentication scheme – Basic.

Place this file under the folder ‘c:/wamp/www/basic-auth/’ along with other live data and restart the server.

Now, try accessing the folder http://localhost/basic-auth. This should prompt for username and password.

Reference : http://httpd.apache.org/docs/2.2/mod/mod_auth_basic.html

Saturday, 2 May 2009

Making my blog 'Mobile Friendly'

Being part of mobile software industry and that too working for S60 Browser research team, I desperately wanted to make my blog mobile friendly.


Unfortunately Blogger, where this blog is hosted lacks this service. This would be a very nice and really useful feature.
Wordpress seems to offer this already - http://wordpressmobile.mobi/.

After I did some googling I came across MoFuse. Mofuse provides feeds based solution to convert your blogs to mobile readable version.

Setting up a mobilized version with MoFuse was pretty straight forward, I just registered for a new mobilized blog URL - http://prashtech.mofuse.mobi which internally points to my blogs' RSS feeds.

That's it. If any of you visiting my blog from your mobile, try the mobilized version of my Blog!


Sunday, 11 January 2009

Backward Compatibility with DLLs – Part 2 (Private Implementation)

A very Happy New Year to all of the readers!

This article is in continuation with the previous one, about preserving DLL exported APIs’ backward compatibility.

The last article described a technique of achieving this by privatizing the API’s constructor. This has many disadvantages of its own, as the c’tor is private, ex: Object can not be instantiated on stack.

An alternative technique is to have a “Private Implementation”.

If you have a class, which you intend to export, separate out all the internal implementation including the data members and the functions which you think can be hidden. The exported class will only have the functions exported along with a private member pointer to the new internal class.

As an example, consider the following class,

#define DLL_EXPORT __declspec(dllexport)
class DLL_EXPORT ExampleExport
{
public: // c'tors and d'tors
    ExampleExport();
    ~ExampleExport();

public: // functions
    void function1();
    int function2();

private: // private data members
    int m_member1;
    int m_member2;
};

We have 2 integer member variables. Adding or removing the member variables later, will always cause a binary compatibility break as described in the previous article.

Let’s try to separate out the internal implementation. We will move all the private data members to a different class – ExampleExportPrivate.

class ExampleExportPrivate
{
public: // c'tors and d'tors
    ExampleExportPrivate();
    ~ExampleExportPrivate();

public: // data members
    int m_member1;
    int m_member2;
};

We will redefine ExampleExport to use ExampleExportPrivate.

#define DLL_EXPORT __declspec(dllexport)

class ExampleExportPrivate; // <<-- forward declaration of the private implementation which is defined in cpp file


class DLL_EXPORT ExampleExport
{
public: // c'tors and d'tors
    ExampleExport();
    ~ExampleExport();

public: // functions
    void function1();
    int function2();

private:
    ExampleExportPrivate *m_private; // <—Pointer to private implementation. };

As a first step, forward declare the private implementation class – ExampleExportPrivate. The actual definition of this private implementation class can be placed as part of the cpp file. So, we are not exposing this class outside, even in the header files exported. Next step is to have a private pointer member variable which points to ExampleExportPrivate. Any references to the data will be redirected to the internal private implementation.

This technique will help us to not change the size of the exported class. If we need to add or delete a new member variable, ExampleExportPrivate will be the class which will have those changes, but not ExampleExport.

This technique is usually called as “PImpl” (Private Implementation). Here is an interesting article http://www.gotw.ca/publications/mill04.htm

Monday, 1 December 2008

Backward Compatibility with DLLs

This and the following articles, I personally feel very interesting.

It’s related to the “backward compatibility” of the DLLs.

If you are distributing your DLLs to people or 3rd party, whom you expect to use them, you should be very careful about the interface you expose out of the DLLs.

Consider you are distributing a DLL, which has an exported class of some size and few public functions. If you update the same DLL in future and redistribute it, you cannot always expect the users to re-link their application with your new DLL. In such cases, users of the DLL expect the same interface what you had provided in the earlier release. If by any way there is a change in the interface, it results in failure of backward compatibility.

Let’s take an example to explain this situation. The following is a class which you are exporting as part of your DLL,

#define DLL_EXPORT __declspec(dllexport)

class DLL_EXPORT ExampleExport
{
    public:
        ExampleExport();
        ~ExampleExport();

        void function1();
        int function2();

    private:

        int m_member1;
        int m_member2;
};

In a future release you updated this class to have an additional member variable,

class DLL_EXPORT ExampleExport
{
    public:
        ExampleExport();
        ~ExampleExport();

        void function1();
        int function2();

    private:

        int m_member1;
        int m_member2;
        int m_member3; // <<---- a new member variable added
};

You can observer that the class size has been changed. Earlier it was 8 bytes (assuming int as 4 bytes) and it’s changed to 12 by adding an additional integer member variable.

Consequence: For an end user application, which is not re-linked with the updated DLL, the size of the class is still 8 bytes. Since the application was compiled and linked with the first version of DLL, the size is still the same even after they started using the new DLL. The application may have unpredicted behavior.

Resolution: This problem needs to be addressed before we release the first version of the DLL. Of course we cannot restrict the size of the class to not to change in future. We may need to update it by adding or removing new member variables. One solution is to force the end user application to not to construct the object by itself.

  • Make constructor private.
  • Export a new static member function which creates an object by calling private constructor

class DLL_EXPORT ExampleExport
{
public:
    ~ExampleExport();

public:
    static ExampleExport* Instance();

public:
    void function1();
    int function2();

private:
    ExampleExport(); // <<---- private constructor

private:
    int m_member1;
    int m_member2;
    int m_member3; // <<---- a new member variable added
};

This forces the client application to use ExampleExport::Instance() function always to construct an object and since the definition of Instance() is part of the DLL, 12 bytes will be allocated with the new DLL.

Let’s have a look at another solution for the same problem, in the next article.

Sunday, 1 June 2008

Forward Declarations

We can use forward declaration to speedup the compilation and to reduce the interdependencies between different modules.

Consider following CServer and CClient classes, declared in Server.h and Client.h header files respectively.

Server.h

#include "Client.h"

class CServer
{
public:
CServer();
virtual ~CServer();

void SendMsg(CClient &clnt);

private:
CClient *m_ptrClient;
};

In this case it will always be more efficient to omit the inclusion of the header file Client.h, instead we can use forward declaration as shown below,

class CClient;

class CServer
{
public:
CServer();
virtual ~CServer();

void SendMsg(CClient &clnt);

private:
CClient *m_ptrClient;
};

This is sufficient in this case because of the reason that C++ compiler is optimized enough and it doesn't need to know about the size and interfaces of the class CClient within the declaration of the CServer class.

However we have to include the Client.h header in Server.cpp where the actual definition of the member functions exist.

Below are some use cases which indicates the usage of forward declarations,

class CClient;

class CServer
{
public:
CServer();
virtual ~CServer();

void SendMsg(CClient clnt); // non-ref/pointer parameter

private:
CClient *m_ptrClient;
};

Usage of forward declaration is valid even though we have non-reference or non-pointer parameter in the member function.

Below is a case where we cannot use forward declaration,

class CClient;

class CServer
{
public:
CServer();
virtual ~CServer();

void SendMsg(CClient clnt) { clnt.updateMsg(); } // inline definition

private:
CClient *m_ptrClient;
};

Cannot use forward declaration here because SendMsg has it's inline definition which is actually using CClient::updateMsg(). In this case we need to include the header Client.h within Server.h

One more case where we can not use forward declaration,

class CClient;

class CServer
{
public:
CServer();
virtual ~CServer();

void SendMsg(CClient clnt);

private:
CClient m_client;
};

Since the member variable m_client within CServer is of type CClient, compiler need to know about the CClient. We cannot use the forward declaration here.

The cause of compilation speed increase

The increase in speed by forward declaration is due to the fact that header files can be included multiple times, whereas implementation files (CPP) are not. Therefore, keep the heaer files as simple as possible.

Rule of Thumb : "If the compiler doesn't need it, you won't have to do it." C++ is well optimized.


Wednesday, 9 January 2008

dynamic_casting with pointers and references

First of all a very warm happy new year to all the readers. Its been a while since the last post.

Today I intend to write about dynamic_cast again. There's already an article about dynamic_cast. The reason why I'm writing about this is to show with some samples how we can use dynamic cast with pointers and also with references.

Yes, RTTI can be implemented both with pointers and references.

Below sample shows how to use dynamic_cast with pointers. I have considered the same example classes which were there in the dynamic_cast article .

void ProcessButtonEvent(CControlIface *pControl)
{
    // Here we need make sure safe down-cast happens
    CButtonControl *pButton = dynamic_cast <CButtonControl *> (pControl);

    // casting works fine here since we had passed pControl1

    if(pButton != NULL)
    {
        pButton->OnClick();
        // We can now safely call OnClick() of CButtonControl
    }
    else
    {
        cout << "dynamic_cast failed. pControl is not pointing to instance of CButtonControl"<<endl;
    }
}

We need to note here that whenever dynamic cast fails with pointers it returns NULL. This is the reason why we are checking for

pButton!=NULL


Lets try dynamic casting with references,

void ProcessButtonEvent(CControlIface &Control)
{
    // Here we need make sure safe down-cast happens
    try{
    CButtonControl &Button = dynamic_cast <CButtonControl &> (Control);
    Button.OnClick();
    }
    catch(bad_cast)
    {
        cout << "Caught: bad_cast exception. This control is not a button"<<endl;
        return;
    }
}

In case of references if dynamic_cast fails, it throws bad_cast exception. This is the reason why we are catching the exception in the above code sample.

Please note that some old compilers may not support dynamic_cast. In that case its high time for you to upgrade your C++ compiler!

Tuesday, 4 September 2007

Global vs Member overloaded operator new

In an earlier post we saw how to overload operator new, which will allow us to have customized memory allocation for an object on heap.

Its possible to place this overloaded operator new function either globally or as member function within a class.

 

// Global overloaded operator new
void *operator new(size_t size)
{
    return malloc(size);
}

 

// Class CTest
class CTest
{
public:

    // Member overloaded operator new
    void *operator new(size_t size)
    {
        return malloc(size);
    }

};

 

Is there any behavioral difference between these two versions of operator new?

Yes, there is.

If we have overloaded new as a member function within a class, it will always have high precedence over the globally defined version.

If we have a globally defined operator new function, the same will be used for all classes which doesn't have overloaded operator new defined within.

If both exist, the member version will be preferred over the global version.

Is there any advantage of this feature?

Yes.

Global version of overloaded operator new will be very much useful when we need to have a common strategy for memory allocation for all the classes in the module.

If we are in a situation where we need to have a specific way for allocation for a particular class which is different from others then we can overload operator new for the class with desired allocation method. A good example would be to allocate and initialize the allocated memory with zeros.