Tuesday, December 28, 2010

Getting Started with Google Test and Google Mock

Writing unit test and mock frameworks in C++ is not an easy task. Fortunately, Google has created wonderful unit test and mock frameworks for us :) In this blog, I'm gonna show how to get started with Google Test and Google Mock frameworks.
1. Download Google Test and Google Mock
2. Extract them and build them by going to the make directory and type 'make'. This will create gtest_main.a and gmock_main.a static libraries.

HelloWorld.h
#ifndef HELLOWORLD_H_
#define HELLOWORLD_H_

#include <string>
#include "Messenger.h"
using namespace std;

class HelloWorld
{
public:
    HelloWorld();
    virtual ~HelloWorld();
    string getMessage(Messenger* messenger) const;
};

#endif /* HELLOWORLD_H_ */

HelloWorld.cpp
#include "HelloWorld.h"
#include "Messenger.h"

HelloWorld::HelloWorld()
{
}

HelloWorld::~HelloWorld()
{
}

string HelloWorld::getMessage(Messenger* messenger) const
{
    return messenger->getMessage();
}

Messenger.h
#ifndef MESSENGER_H_
#define MESSENGER_H_

#include <string>
using namespace std;

class Messenger
{
public:
    virtual ~Messenger() {}
    virtual string getMessage() = 0;
};

#endif /* MESSENGER_H_ */

MockMessenger.h
#ifndef MOCKMESSENGER_H_
#define MOCKMESSENGER_H_

#include "Messenger.h"
#include <string>
#include <gmock/gmock.h>
using namespace std;

class MockMessenger : public Messenger
{
public:
    MOCK_METHOD0(getMessage, string());
};

#endif /* MOCKMESSENGER_H_ */

HelloWorldTest.cpp
#include "HelloWorld.h"
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include "MockMessenger.h"
#include <string>
#include <memory>
using namespace testing;

TEST(HelloWorldTest, getMessage)
{
    MockMessenger messenger;
    std::string msg = "Hello World";
    EXPECT_CALL(messenger, getMessage()).WillRepeatedly(Return(ByRef(msg)));

    HelloWorld helloWorld;
    EXPECT_EQ("Hello World", helloWorld.getMessage(&messenger));
    EXPECT_EQ("Hello World", helloWorld.getMessage(&messenger));
    EXPECT_EQ("Hello World", helloWorld.getMessage(&messenger));
}

With gtest_main.a and gmock_main.a linked, we don't need to manually create the main function.

For more information, go to Google Test and Google Mock.

Escaping HTML String using Python

Sometimes back I wrote a Groovy script for escaping the HTML that can be useful, especially for putting source code into Blogger. Here is the Python version :) I'm seriously in love with Python's "batteries' included" motto.

escapehtml.py
import os, sys, cgi

def escapehtml(path):
    if not os.path.exists(path):
        print "Error:", path, "does not exist"
        sys.exit(1)
    text = open(path).read()
    return cgi.escape(text)

if __name__ == "__main__":
    if not len(sys.argv) == 2:
        print "Error: Invalid argument!"
        sys.exit(1)
    print escapehtml(sys.argv[1])

escapehtml_recurse.py
import os, sys, escapehtml

def escapehtml_recurse(source, destination):
    if not os.path.exists(source):
        print "Error:", path, "does not exist"
        sys.exit(1)
    for root, dirs, files in os.walk(source):
        for f in files:
            filename = os.path.join(root, f)
            content = escapehtml.escapehtml(filename)
            if not os.path.exists(destination):
                os.makedirs(destination)
            newfilename = os.path.join(destination, f + ".txt")
            newpath = open(newfilename, "w")
            print "Creating", newfilename
            newpath.write(content)
            
if __name__ == "__main__":
    if not len(sys.argv) == 3:
        print "Error: Invalid argument!"
        sys.exit(1)
    escapehtml_recurse(sys.argv[1], sys.argv[2])
    print "*** Done ***"

Building Boost with MinGW

In this blog, I'm gonna show you how to build Boost using MinGW. Below are the versions that I use.
- gcc 4.5.0
- boost 1.45.0

All the steps below need to be executed on CMD and not on MSYS.
1. Download Boost
2. Extract it to let's say C:\boost_1_45_0
3. Build bjam tool.
cd C:\boost_1_45_0\tools\build\v2\engine\src
build.bat mingw
bjam will be created in C:\boost_1_45_0\tools\build\v2\engine\src\bin.ntx86
4. Copy the bjam tool to C:\boost_1_45_0
copy bjam.exe C:\boost_1_45_0
5. Build the boost libraries.
cd C:\boost_1_45_0
bjam toolset=gcc
The include header files are located in the C:\boost_1_45_0\boost and the libraries are located in the C:\boost_1_45_0\stage\lib

Enjoy! :)

Thursday, December 23, 2010

Creating Static and Shared Libraries using GCC

There are two types of libraries in C/C++:
1. Static libraries (.a on Linux or .lib on Windows): the library of object code that is linked with becomes part of the application.
2. Shared libraries (.so on Linux or .dll on Windows): the library of object code that is linked with does not become part of the application.

In this blog, I am going to show you how to create static and shared libraries using GCC on Linux. Although the the example shown below uses C++, but the same concept is applicable to C. Simply replace g++ with gcc.

Hello.h
#include <iostream>

class Hello
{
public:
    void sayHello() const;
}; 

Hello.cc
#include "Hello.h"
using namespace std;

void Hello::sayHello() const
{
    cout << "Hello World" << endl;
} 

Main.cc
#include "Hello.h"

int main()
{   
    Hello hello;
    hello.sayHello();

    return 0;
} 

To create a static library, do the following:
1. Compile the library code.
g++ -Wall -c Hello.c
This will produce Hello.o object file.
2. Create a static library.
ar -cvq libhello.a Hello.o
This will produce libhello.a static library.
3. Compile the Main.cc code and link it against the libhello.a static library.
g++ -o Main libhello.a Main.cc
This will produce the Main executable file. When you do ldd, you won't see the dependency to libhello library since it's a static library.
ldd Main
4. Execute the Main program.
./Main

To create a shared library, do the following:
1. Compile the library code.
g++ -Wall -fPIC -c Hello.c
This will produce Hello.o object file. The -fPIC flag is required for creating a shared library. See man g++ or man gcc for more information.
2. Create a shared library.
g++ -shared -o libhello.so Hello.o
This will produce libhello.so shared library.
3. Compile the Main.cc code and link it against the libhello.so shared library.
g++ -o Main libhello.so Main.cc
This will produce the Main executable file. When you do ldd, you will see the dependency to libhello library.
ldd Main
4. Execute the Main program.
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:."
./Main

Saturday, December 4, 2010

Getting Started with JNI

Java Native Interface (JNI) allows Java code to call native applications, e.g. applications written in C or C++. In this example, I will show you how to call C and C++ application from Java using JNI on Linux.

* JNI for C application *

CHelloWorld.java
public class CHelloWorld {
    
    static {
        System.loadLibrary("chello");
    }
    
    private native void print();

    public static void main(String[] args) {
        new CHelloWorld().print();
    }
}
1. Create a header file for CHelloWorld.
javah -jni CHelloWorld

2. Implement CHelloWorld.c
#include <jni.h>
#include <stdio.h>
#include "CHelloWorld.h"

JNIEXPORT void JNICALL
Java_CHelloWorld_print(JNIEnv *env, jobject obj)
{
    printf("Hello World from C\n");
    return;
}

3. Compile the CHelloWorld.c
gcc -Wall -fPIC -c CHelloWorld.c -I$HOME/jdk1.6.0_22/include \
-I$HOME/jdk1.6.0_22/include/linux
This will produce the CHelloWorld.o

4. Create a shared library (.so on Linux or .dll on Windows).
gcc -shared -o libchello.so CHelloWorld.o

5. Execute CHelloWorld in Java.
java -Djava.library.path=. CHelloWorld
The -Djava.library.path is required to tell where to load the library from. Alternatively, LD_LIBRARY_PATH (on Linux) or PATH (on Windows) can also be used.

* JNI for C++ application *
public class CppHelloWorld {

    static {
        System.loadLibrary("cpphello");
    }
    
    private native void print();

    public static void main(String[] args) {
        new CppHelloWorld().print();
    }
}
1. Create a header file for CppHelloWorld
javah -jni CppHelloWorld

2. Implement CppHelloWorld.cpp
#include <jni.h>
#include "CppHelloWorld.h"
#include <iostream>
using namespace std;

JNIEXPORT void JNICALL
Java_CppHelloWorld_print(JNIEnv *env, jobject obj)
{
    cout << "Hello World from C++" << endl;
    return;
}

3. Compile CppHelloWorld
g++ -Wall -fPIC -c CppHelloWorld.cpp -I$HOME/jdk1.6.0_22/include \
-I$HOME/jdk1.6.0_22/include/linux
This will produce the CppHelloWorld.o

4. Create a shared library (.so on Linux or .dll on Windows)
g++ -shared -o libcpphello.so CppHelloWorld.o

5. Execute CppHelloWorld in Java.
java -Djava.library.path=. CppHelloWorld
The -Djava.library.path is required to tell where to load the library from. Alternatively, LD_LIBRARY_PATH (on Linux) or PATH (on Windows) can also be used.

To call native library in Java using similar concept like Python's ctypes or C#'s P/Invoke, JNA is a good alternative.

Wednesday, December 1, 2010

Introduction to Makefile

Following the example from the previous blog on the Introduction to GCC, I am going to show you how to makefile to simplify all those steps.

If for example, we have a directory structure like this.
/home/cpp/HelloWorld.cpp
         /HelloWorld.hpp
         /Main.cpp

* Makefile *
CC=g++
CFLAGS=-Wall
OBJ=Main.o HelloWorld.o

Main: $(OBJ)

clean:
    rm -rf Main *.o

1. To build
make
2. To clean
make clean
Here we use Makefile's implicit rules by only specifying the CC and CFLAGS implicit variables. For more information, see this link.

If now, we have a directory structure like this.
/home/cpp/lib/libhello.a
         /include/HelloWorld.hpp
         /Main.cpp
* Makefile *
CC=g++
INCLUDEDIR=include
LIBDIR=lib/libhello.a
CFLAGS=-Wall -I$(INCLUDEDIR)
OBJ=Main.o
DEPS=$(INCLUDEDIR)/HelloWorld.hpp

Main: $(OBJ)
    $(CC) -o Main $(OBJ) $(LIBDIR) $(CFLAGS) 

%.o: %.cpp $(DEPS)
    $(CC) -c -o $@ $< $(CFLAGS)

clean:
    rm -rf Main *.o
For more information about the automatic variables, such as $@, $<, see this link.

Introduction to GCC

In this blog, I am going show you the basic stuff on how to compile, link, and create an executable of a C++ application using GCC. Although the example here uses C++, it should also be applicable to C by changing the compiler to use gcc instead of g++.

HelloWorld.hpp
#include <iostream>
using namespace std;

class HelloWorld
{
public:
    void sayHello() const;    
};

HelloWorld.cpp
#include "HelloWorld.hpp"

void HelloWorld::sayHello() const 
{
    cout << "Hello World" << endl;
}

Main.cpp
#include "HelloWorld.hpp"

int main()
{
    HelloWorld helloWorld;
    helloWorld.sayHello();        

    return 0;
}

If for example, we have a directory structure is as below.
/home/cpp/HelloWorld.cpp
         /HelloWorld.hpp
         /Main.cpp

In order to create a Main executable, we need to perform the following steps.
1. Compile the HelloWorld.cpp
g++ -Wall -c HelloWorld.cpp
-Wall option is used to display all the warnings. This will produce HelloWorld.o object file.
2. Compile the Main.cpp
g++ -Wall -c Main.cpp
This will produce Main.o object file.
3. Link the two object files (HelloWorld.o and Main.o) to create an executable (Main).
g++ -Wall -o Main Main.o HelloWorld.o
This will produce Main executable file.
4. Execute the Main file.
./Main

If we change the directory structure as below.
/home/cpp/HelloWorld.cpp
         /include/HelloWorld.hpp
         /Main.cpp
We will need to perform the following steps.
1. Compile the HelloWorld.cpp
g++ -Wall -c -Iinclude HelloWorld.cpp
The -Iinclude is used here to tell the that header files are located in the ./include directory since HelloWorld.cpp requires HelloWorld.hpp (see the source file of HelloWorld.cpp). This step will produce HelloWorld.o object file.
2. Compile the Main.cpp
g++ -Wall -c -Iinclude Main.cpp
The -Iinclude is used here to tell that the header files are located in the ./include directory since Main.cpp requires HelloWorld.hpp (see the source file of Main.cpp). This step will produce Main.o object file.
3. Link the two object files (HelloWorld.o and Main.o) to create an executable (Main).
g++ -Wall -o Main Main.o HelloWorld.o
This will produce Main executable file.
4. Execute the Main file.
./Main

To make things more complicated, let's change the directory structure as below.
/home/cpp/lib/HelloWorld.cpp
         /include/HelloWorld.hpp
         /Main.cpp
Before that, let's create a static library (libhello.a) in the lib directory.
1. Compile HelloWorld.cpp
cd lib
g++ -Wall -c HelloWorld.cpp -I../include
2. Create a static library (libhello.a).
ar -crv libhello.a HelloWorld.o
3. To view the content of the static library.
ar -t libhello.a

Now we the directory structure should look like this.
/home/cpp/lib/libhello.a
         /include/HelloWorld.hpp
         /Main.cpp

1. Compile Main.cpp
g++ -Wall -c Main.cpp -Iinclude 
This step will produce Main.o object file.
2. Link the library to create a Main executable file.
g++ -Wall -o Main Main.o lib/libhello.a -Iinclude
Alternatively, this statement can also be used.
g++ -Wall -o Main Main.o -Llib -lhello -Iinclude
Here, we don't tell where the libhello.a location explicitly. Instead, we tell where the library directory is by specifying the -Llib. This means that the library directory is located in the ./lib. The -l will strip the word lib. Thus, if we have libraries like below:
libhello.a ---> this will become -lhello
libabc.a ---> this will become -labc
libxyz.a ---> this will become -lxyz

3. Execute the Main file.
./Main