Get ACTIVE-IST Open Source Tools at SourceForge.net. Fast, secure and Free Open Source software downloads

CxUtils

Cross-Platform Utilties Library

Introduction

CxUtils is a multi-platform C++ library containing many useful functions and classes for rapid development of applications released under the BSD License. It contains tools for threads, network communication, joysticks, RS-232/serial communication, shared/mapped memory interfaces (e.g. message box, message server/client), timers, keyboard and mouse capture/emulation, and basic math operations (matrices, quaternions, coordinate transformations). Using this library it should be a simple task to create a C++ application that can easily be ported between Windows, Linux, and other platforms. The following sections describe some of the available interfaces included with CxUtils. The full documentation can be found here. Example programs and additional documentation for developers is available with the library.

Examples

The following are descriptions and code examples for just a few of the common interfaces included with CxUtils. Included with the CxUtils release are more comprehensive example programs that are fully documented making CxUtils easy to learn.

Mutex

The Mutex class is just that, a simple way to create a mutex. This implementation allows creation of a standard mutex, or Named Mutexes, which will work across processes (similar to semaphore). By providing a unique name to your Mutex, you can synchronize data between multiple threads and processes.

Mutex globalMutex;

// Create a named mutex which will 
// work across processes.  If you don't
// care about inter-process synchronization you
// don't event need to call this method.

globalMutex.Create("GlobalName");

// Enter the critical
// section of memory (block
// other threads/processes).
globalMutex.Lock();

// Do some stuff

// When done, leave 
// critical section in memory
// (allow access to other threads
//  and processes)
globalMutex.Unlock();

Thread

The Thread class is used to create additional threads within a process. Threads can be started using a function pointer, or you can inherit from the Thread class and overload a virtual function.

Packet

The Packet class is a utility class for serialization of data. It makes it easy to write different data types into a buffer, and read them back out again. Byte order conversions, memory allocation and deletion are handled automatically. Packet is used by other interfaces within CxUtils such as UDPServer, UDPClient, TCPServer, TCPClient, and Serial.

Packet packet;    
int b, c;
double d;
unsigned char a;

/*  Test encoding and decoding
    that automatically keeps track
    of encode and decode positions in
    the packet. */
a = 3;
b = 100;
c = -33;
d = 3.145;

cout << "Data being written.\n";
cout << "\t" << (int)a << endl;
cout << "\t" << b << endl;
cout << "\t" << c << endl;
cout << "\t" << d << endl << endl;
//  Write data into packet.
packet.Write(a);
packet.Write(b);
packet.Write(c);
packet.Write(d);

//  Clear values.
a = 0;
b = c = 0;
d = 0;

//  Start reading from beginning of packet.
packet.SetReadPos(0);
packet.Read(a);
packet.Read(b);
packet.Read(c);
packet.Read(d);

// Values should match originals.
cout << "Data read.\n";
cout << "\t" << (int)a << endl;
cout << "\t" << b << endl;
cout << "\t" << c << endl;
cout << "\t" << d << endl << endl;

UDPServer

UDPServer is used to receive UDP messages being sent out by a UDPClient. UDPServer can receive unicast, broadcast, and multicast data.

UdpServer server;
Packet data;
IP4Address source;
data.SetByteOrder(CX_PACKET_BIG_ENDIAN);
if(!server.InitializeMulticastSocket(20000, "224.1.0.1")) 
{
    cout << "Unable to initialize on port " << PORT << endl;
    return;
}

char key = 0;
// Loop until <escape key> is pressed.
while(key != 27) 
{
    //  Receive up to 500 bytes and
    //  store the result in the Packet data, 
    //  the timeout value is 0, so this is a
    //  blocking receive.  A pointer to a string
    //  will provide the IP address of the
    //  sender of the data.
    if(server.Recv(data, 500, 0, &source) > 0) 
    { 
        char val;
        while(data.Read(val))
            cout << val;
			
        cout << endl;
    }

    key = GetChar();     //  Get key.

}

UDPClient

The UDPClient interface is used to transmit UDP messages over an active network connection. It can send to unicast, multicast or broadcast destinations. The following example sends data to the UDPServer example show previously.

UdpClient client;
IP4Address::List hosts;
client.GetHostAddresses(hosts);
cout << "IP Address for Host Machine\n";
for(int i = 0; i < (int)hosts.size(); i++ ) 
{
    cout << hosts[i].mString << endl;
}

Packet data;
data.SetByteOrder(CX_PACKET_BIG_ENDIAN);

if(!client.InitializeSocket("192.168.1.2", 20000)) 
{
    return;
}

cout << "Initialized UDP Client Socket on port " << 20000<< endl;

char key = 0;
while(key != 27) 
{
    if((key = GetChar()) > 0) 
    {
        data.Write(key);   
        cout << key;
        client.Send(data);  //  Send data (could send character array also if desired
	data.Clear();       //  Clear packet and encode data.
        /*  Alternative way to send:
        client.Send(&key, 1);    //  Send buffer/array.
        */
    }
}

MappedMemory

The MappedMemory class can be used to create a memory mapped file, or open a view to an existing memory mapped file. In addition to opening a view shared memory, it also creates a Named Mutex for synchronization between processes. Methods for read and writing data to/from memory exist, making it easy to share formatted streams.

// Process 1 (Server)

MappedMemory mappedMem;

// Create mapped/shared memory called "MySharedMemory", and
// make it 200 bytes in size.
mappedMem.CreateMappedMemory("MySharedMemory", 200);

// Lock the shared memory so that we avoid read/write
// errors from other processes/threads using this
// mapped/shared memory also.
mappedMem.Lock();

// Set the write position in shared memory.
mappedMem->SetWritePos(0);
// Now write some numbers.  The write position will advance 
// automatically based on the size of the data written.
for(unsigned char i = 0; i < 200; i++)
{
    mappedMem->Write(i);
}
// When done, release the mutex lock.
mappedMem.Unlock();

// If done with shared memory, close it.  However,
// if no other process is attached to your shared memory
// location, it will be deleted. (Always deleted when the
// last attached process disconnects).
mappedMem.CloseMappedMemory();
// Process 2 (Client)

MappedMemory mappedMem;

// Open mapped/shared memory called "MySharedMemory".
if(mappedMem.OpenMappedMemory("MySharedMemory"))
{
    // Lock the shared memory so that we avoid read/write
    // errors from other processes/threads using this
    // mapped/shared memory also.
    mappedMem.Lock();

    // Set the read position in shared memory.
    mappedMem->SetReadPos(0);
    // Now read out the numbers.
    for(unsigned int i = 0; i < mappedMem.Length(); i++)
    {
        // The read position will advance automatically 
        // based on the size of the data read.
        unsigned char var;
        mappedMem->Read(var);
    }
    // When done, release the mutex lock.
    mappedMem.Unlock();

    // If done with shared memory, close it.  
    // However, if no other process is 
    // attached to your shared memory
    // location, it will be deleted. 
    // (Always deleted when the
    // last attached process disconnects).
    mappedMem.CloseMappedMemory();
}

Matrix

The Matrix class is one of the many math utility classes available with CxUtils. It supports multiplication, addition, subtraction, division and has methods for the inverse, determinent, etc.

Matrix mat1, mat2, mat3, mat4;

mat1.Create(3, 5);
mat2.Create(5, 3);

mat3.Create(4, 4);
mat4.Create(4, 4);

for(unsigned int i = 0; i < mat2.Rows(); i++)
    for(unsigned int j = 0; j < mat2.Cols(); j++)
        mat2[i][j] = (i + j);

for(unsigned int i = 0; i < mat1.Rows(); i++)
    for(unsigned int j = 0; j < mat1.Cols(); j++)
        mat1(i, j) = (i + j);

mat3[0][0] = 3; mat3[0][1] = 2; mat3[0][2] = 0; mat3[0][3] = 1;
mat3[1][0] = 4; mat3[1][1] = 0; mat3[1][2] = 1; mat3[1][3] = 2;
mat3[2][0] = 3; mat3[2][1] = 0; mat3[2][2] = 2; mat3[2][3] = 1;
mat3[3][0] = 9; mat3[3][1] = 2; mat3[3][2] = 3; mat3[3][3] = 1;

mat1.Print();
mat2.Print();
mat3.Print();

cout << "M1 * M2 = \n";
mat1 *= mat2;
mat1.Print();

double d;
mat3.GetDeterminant(d);
cout << "Det of M3 = " << d << "\n";

mat4[0][0] = 1; mat4[0][1] = 0; mat4[0][2] = 0; mat4[0][3] = 0;
mat4[1][0] = 0; mat4[1][1] = 1; mat4[1][2] = 0; mat4[1][3] = 0;
mat4[2][0] = 0; mat4[2][1] = 0; mat4[2][2] = 1; mat4[2][3] = 0;
mat4[3][0] = 0; mat4[3][1] = 0; mat4[3][2] = 0; mat4[3][3] = 1;

Matrix imat3;

Matrix::GaussJordan(mat3, mat4, imat3);

cout << "Matrix A:\n";
mat3.Print();
cout << "Inverse of Matrix A:\n";

imat3.Print();
cout << "A*A^-1\n";       
(mat3*imat3).Print();

cout << "Checking inverse\n";
Matrix iden = mat3.Inverse()*mat3;

iden.Print();

Coordinate Conversion Routines

The CxUtils library has several classes for representing different types of coordinate systems such as World Geodetic System (WGS), Universal Transmercator Coordinates (UTM), and Geo-Centric Coordinates (GCC). The following example demonstrates how to convert position and orientation values between the different representations.

Wgs wgs;    //  World geodetic coordinates (lat, long, elevation).
Gcc gcc;    //  GeoCentric Coordinates ( X, Y, Z).

Point3D xyz, hpr; //  HLA/DIS orientation ( psi, theta, phi), and heading, pitch, roll.

//  Set the starting location in the world using
//  a latitude and longitue.  The object at the location
//  is at a heading of 135, pitch of 20 degrees, and roll of 30 degrees.
wgs.mLatitude = -34.9;
wgs.mLongitude = 138.5;
wgs.mElevation = 10000;
//  Heading, Pitch, Roll
hpr( CX_DEG2RAD(135), CX_DEG2RAD(20), CX_DEG2RAD(30) );

//  Display initial values to screen.
cout << "World Geodetic Position (WGS): Latitude: " 
     << wgs.mLatitude << ", Longitude: " 
     << wgs.mLongitude << ", Elevation: " 
     << wgs.mElevation << endl;
cout << "HPR orientation values:\n";
cout << "Degrees: X: " << CX_RAD2DEG(hpr.mX) << ", Y: " << CX_RAD2DEG(hpr.mY) << ", Z: "
     << CX_RAD2DEG(hpr.mZ) << endl;
cout << "Radians: X: " << hpr.mX << ", Y: " << hpr.mY << ", Z: "
     << hpr.mZ << endl;

//  Convert from [WGS, HPR] to the HLA/DIS coordinates [GCC, XYZ].
WgsHprToGccXyz( wgs, hpr, gcc, xyz);
cout << "World GeoCentric Position (GCC): X: " 
     << gcc.mX << ", Y: " 
     << gcc.mY << ", Z: " 
     << gcc.mZ << endl;
cout << "DIS orientation values:\n";
cout << "Degrees: X: " << CX_RAD2DEG(xyz.mX) << ", Y: " << CX_RAD2DEG(xyz.mY) << ", Z: "
     << CX_RAD2DEG(xyz.mZ) << endl;
cout << "Radians: X: " << xyz.mX << ", Y: " << xyz.mY << ", Z: "
     << xyz.mZ << endl;

//  Convert back to [WGS, HPR] from HLA/DIS coordinates [GCC, XYZ].
GccXyzToWgsHpr( gcc, xyz, wgs, hpr );
cout << "World Geodetic Position (WGS): Latitude: " 
     << wgs.mLatitude << ", Longitude: " 
     << wgs.mLongitude << ", Elevation: " 
     << wgs.mElevation << endl;
cout << "HPR orientation values:\n";
cout << "Degrees: X: " << CX_RAD2DEG(hpr.mX) << ", Y: " << CX_RAD2DEG(hpr.mY) << ", Z: "
     << CX_RAD2DEG(hpr.mZ) << endl;
cout << "Radians: X: " << hpr.mX << ", Y: " << hpr.mY << ", Z: "
     << hpr.mZ << endl;

// How to convert from WGS to UTM Coordinates
Utm utm;

utm << wgs;
wgs2 << utm;