Saturday, July 2, 2011

Creating and Using C++ shared libraries using g++

It's been an eventful couple of months. I worked my first 90+ hour week, will be moving for a second time, and learned a heck of a lot about C++.
In this post, I will explain in simplified terms, how to create your own C++ shared Library.

It took me a couple hours to figure it out. It's not exactly straightforward, but neither is it overly complex.

I assume that you, the reader, have experience writing C++ classes and headers. 


Step 1: Create your library

Before you go and build a gigantic, powerful library, it is better to create something simple to start, then build upon it. I used a header file in addition to my c++ class file.
I'd recommend writing a simple class with just a constructor, deconstructor, and a method that outputs something like "Hello World" using cout.

Libraries do NOT contain a main() method.

Step 2: Compile your library

The following code will compile your .cpp file as a shared library. Replace the file names and library names with your own.
Be sure to name your library lib[name].so.
It needs the lib prefix and .so suffix. If you have multiple version of your library, the suffix can be .so.1, .so.1.0, .so.1.0.5, etc. as long as one with .so exists.
 g++ -Wall -shared -fPIC -o ~/libs/libmylibrary.so libmylibrary.cpp

The format goes like this: g++ [options] [library placement on filesystem] [file(s) that make up library] 

I also had a ~/libs/ folder created so I could compile and install as user. If you want system-wide access, run the command as root and use "-o /usr/local/lib/libfilename.so".


Step 3: Test your library

Now the fun part:
Create a test file (test.cpp) with just a main() method.

You will have to include the library in the file like so:
#include "libmylibrary.h"

If you are using a namespace in your library, be sure to use it or prefix any methods or constructors with it.

In your main() method, create an instance of the object, call its method(s), and delete it at the end. An example would be so:


ExampleObj * myobj = new ExampleObject();
myobj->printHelloWorld();
delete myobj;

Now the best part: Compiling your program and linking it to your library. Do so with this command:

g++ main.cpp -o ~/bin/libtest -L$HOME/libs -lmylibrary

A couple IMPORTANT things to note here:

  • ~/bin/ is a directory I created. You may have to change location or create the directory yourself
  • The -l command which links the library has omitted the "lib" prefix, so it is mylibrary instead of libmylibrary.
That last point is what really fooled me for a while. 

That's all for c++ libraries. I hope this helps.




Edit



You may have to add the following around the body of your header file.



This goes after the include statements, but before the namespace/class declarations


#ifdef __cplusplus
extern "C"
{
#endif






And after end of namespace/class declarations, but before final #endif tag:


#ifdef __cplusplus
}
#endif




This should fix some c++ specific issues you may encounter.

Saturday, April 30, 2011

Creating a more object-oriented OpenGL Window with Freeglut in C++

As per my previous post where I described how to build an OpenGL window, it was basically a c-to-c++ code transition with explainations of what different methods did.

In this post, I will be posting my code where the window preferences and display information is inside a class and only the main() method is not part of the object.

There are two parts to the following code: the cpp file and the header file. You need them in two separate files and in the same directory for things to compile properly without modifications.

Please feel free to rate and critique the code I post. Also, the method names and filenames are part of a project I'm working on, so feel free to change them. They make sense to me.

Also, I am licensing the following code under the GPL 2. Feel free to distribute and modify the source as you like.

rwindow.cpp

#include <stdlib.h>

#include <stdio.h>

#include <GL/glew.h>

#include <GL/freeglut.h>

#include <GL/gl.h>

#include "rwindow.h"

RWindow::RWindow()

{

str_window_title = "Hello World";

usi_hwindow = 250;

usi_vwindow = 250;

usi_windowx = 100;

usi_windowy = 100;

}

RWindow::RWindow(string newtitle)

{

str_window_title = newtitle;

usi_hwindow = 250;

usi_vwindow = 250;

usi_windowx = 100;

usi_windowy = 100;

}

void RWindow::SetWindowTitle(string newtitle)

{

str_window_title = newtitle;

}

string RWindow::GetWindowTitle() const

{

return str_window_title;

}

void RWindow::SetWindowHorizontal(unsigned short int newsize)

{

usi_hwindow = newsize;

}

unsigned short int RWindow::GetWindowHorizontal() const

{

return usi_hwindow;

}

void RWindow::SetWindowVertical(unsigned short int newsize)

{

usi_vwindow = newsize;

}

unsigned short int RWindow::GetWindowVertical() const

{

return usi_vwindow;

}

unsigned short int RWindow::GetWindowX() const

{

return usi_windowx;

}

void RWindow::SetWindowX(unsigned short int newsize)

{

usi_windowx = newsize;

}

unsigned short int RWindow::GetWindowY() const

{

return usi_windowy;

}

void RWindow::SetWindowY(unsigned short int newsize)

{

usi_windowy = newsize;

}

RWindow::~RWindow()

{

// remove new variables if any

// remove self

delete this; // Make sure pointer is null

}

void RWindow::display_contents()

{

/* clear all pixels */

glClear (GL_COLOR_BUFFER_BIT);

/* draw white polygon (rectangle) with corners at

* (0.25, 0.25, 0.0) and (0.75, 0.75, 0.0)

*/

glColor3f (1.0, 1.0, 1.0);

glBegin(GL_POLYGON);

glVertex3f (0.25, 0.25, 0.0);

glVertex3f (0.75, 0.25, 0.0);

glVertex3f (0.75, 0.75, 0.0);

glVertex3f (0.45, 0.45, 0.0);

glEnd();

/* don't wait!

* start processing buffered OpenGL routines

*/

glFlush ();

};

void RWindow::init ()

{

/* select clearing (background) color */

glClearColor (0.0, 0.0, 0.0, 0.0);

/* initialize viewing values */

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

glOrtho(0.0, 1.0, 0.0, 1.0, 1.0, -1.0);

};

/*

* Declare initial window size, position, and display mode

* (single buffer and RGBA). Open window with "hello"

* in its title bar. Call initialization routines.

* Register callback function to display graphics.

* Enter main loop and process events.

*/

int main(int argc, char** argv)

{

// Code to initialize window. Normally this would be in another class

RWindow *testWindow = new RWindow();

glutInit(&argc, argv);

glutInitDisplayMode (GLUT_SINGLE | GLUT_RGBA);

glutInitWindowSize (testWindow->GetWindowHorizontal(), testWindow->GetWindowVertical());

glutInitWindowPosition (testWindow->GetWindowX(), testWindow->GetWindowY());

// .c_str() converts string to constant char*, which this function needs

glutCreateWindow (testWindow->GetWindowTitle().c_str());

testWindow->init ();

glutDisplayFunc(RWindow::display_contents);

glutMainLoop();

delete testWindow;

return 0; /* ISO C requires main to return int. */

};

rwindow.h

#ifndef R_WINDOW

#define R_WINDOW

#include <string>

using namespace std;

class RWindow

{

public:

RWindow();

RWindow(string);

virtual ~RWindow();

void SetWindowTitle(string);

string GetWindowTitle() const;

void SetWindowHorizontal(unsigned short int);

unsigned short int GetWindowHorizontal() const;

void SetWindowVertical(unsigned short int);

unsigned short int GetWindowVertical() const;

void SetWindowX(unsigned short int);

unsigned short int GetWindowX() const;

void SetWindowY(unsigned short int);

unsigned short int GetWindowY() const;

static void init();

static void display_contents();

private:

string str_window_title;

unsigned short int usi_hwindow;

unsigned short int usi_vwindow;

unsigned short int usi_windowx;

unsigned short int usi_windowy;

};

#endif

In order to compile type this:

g++ -Os rwindow.cpp -lGL -lglut -lX11 -lXext -o ~/example-window

Things you can expand on: adding shape-building methods and including them in display_contents(), random polygon generation, etc. etc.

More to come.

=-=-=-=-=
Powered by Blogilo

Thursday, April 28, 2011

Creating an OpenGL Window with Freeglut in C++

It seems everybody exudes the virtues of OpenGL's 3D capabilities. That's all fine and good, but what about 2D?

While searching for information on creating my own 2D hardware-accelerated platform, I came across this excellent website.

http://nehe.gamedev.net/

- See the opengl tutorials on the left-hand side.

And as always, the official OpenGL website is a great resource.

http://www.opengl.org/resources/libraries/

Making a window using Freeglut to accelerate it through OpenGL isn't too difficult.

I can't remember where I found the code I am using as an example, but the gist of it can be found here:

http://www.codeproject.com/KB/openGL/OpenGLWindowWithGLUT.aspx?display=Mobile

(Credit goes to whomever wrote it)

Differences include:

  • This probably won't run on a Windows box
  • We have to compile it manually (see below)

Alright. Onto the code.

First we have the headers. They are C headers, but Freeglut is a C++ friendly library so there shouldn't be any problems.

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include <GL/glew.h>

#include <GL/freeglut.h>

#include <GL/gl.h>

We are importing two main categories of libraries: standard C libraries that handle input/output, library functions and strings as well as the OpenGL libraries.

using namespace std;

Use the standard namespace so you don't have to write out the path of the library functions. It makes reading the code a lot easier.

Now to include a method that will display a static something in the window when we get to that point.

The reason we are writing this function right after the include and namespace statements is because both C and C++ (to name two of many programming languages) cannot call a method that it does not know about at compile time. If this function was at the bottom of our file and we called it at the top, it wouldn't know that function existed yet so it would fail.

void display(void)

{

/* clear all pixels */

glClear (GL_COLOR_BUFFER_BIT);

/* draw white polygon (rectangle) with corners at

* (0.25, 0.25, 0.0) and (0.75, 0.75, 0.0)

*/

glColor3f (1.0, 1.0, 1.0);

glBegin(GL_POLYGON);

glVertex3f (0.25, 0.25, 0.0);

glVertex3f (0.75, 0.25, 0.0);

glVertex3f (0.75, 0.75, 0.0);

glVertex3f (0.25, 0.75, 0.0);

glEnd();

/* don't wait!

* start processing buffered OpenGL routines

*/

glFlush ();

}

The statements are fairly self-explainatory here. glClear clears the window of previous drawings, sets a colour (white), creates a polygon (in this case, a square/rectangle), sets the points and then completes the shape, It then calls the glFlush so that all images that have been declared (have a Begin/End) get displayed.

The reason for having a flush statement is because a) it is faster to store a bunch of shapes in memory and display them after a period of time (aka a flush of the video buffer) than it is to display each and every object right after it gets created, plus b) it makes predicting and controlling frame rates a LOT easier. There are lots of reasons I'm probably not getting to, but it is important.

You could put the flush statement in the main loop after the display() method, but that would be if you want animations or are doing game design, and I recommend keeping the main loop as clean as possible. Plus it would make conditions a lot easier to write. Sometimes the flush() method is skipped because the hardware cannot keep up with the window which causes the dropping of frames to keep framerate acceptible. It will cause 'lag', but won't slow the entire program down to a crawl.

Another point to note: the glVertex3f function. Perhaps you are thinking it should be 'glVertex3d' because we are dealing with 3d graphics libraries here. This is not the case. The '3f' part of the function stands for '3 float parameter' (3f) function. As you can see, the method as 3 values that are floats and must stay as floats. (A float is a number with decimal places, smaller than a double value) If there is no number/letter suffix to the method, it probably has just one type of input parameter.

There could be a glVertex3d method, which would take doubles. Or a glVertex3i, which takes 3 integers. As you can see, the number/letter notation is a great way to know how the method gets used. Of course, you need to know the different C types as a pre-requesite to make good use of this.

void init (void)

{

/* select clearing (background) color */

glClearColor (0.0, 0.0, 0.0, 0.0);

/* initialize viewing values */

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);

}

The init method is next. It takes no parameters itself, like the display method above. All this does is set a few values for the window we'll be creating. The window we'll be drawing will need a background colour (otherwise the background of your computer will be seen through it) and some values set.

I'm not an expert in OpenGL by any means, so when I describe the glMatrixMode() method, I could be off.

There are a few different modes that OpenGL can operate in. GL_PROJECTION mode which I'm guessing is a more 2D-oriented mode, GL_MODELVIEW which does 3D, GL_TEXTURE which applies images and other texturey things to a surface (2D or 3D) therefore requires efficient I/O operations, and GL_COLOR which works on colour algorithms such as blending, transparencies and effects than actual objects.

glOrtho is part of the GL_PROJECTION Matrix Mode. It may be 2D only. The first 4 double values determine the four points of the buffer we display. Left, Right, Bottom, Top. The next two values are near and far values, glOrtho seems to deal with inversion and clipping. The OpenGL article seems to depict that it is a matrix transformation that replaces the current matrix (or what has been written to the video buffer).

Anyway, enough math for now. It may be better to experiment with changing values than to explain it with words.

The main() method, not to be mistaken for the main loop I mentioned earlier, sets up the window.

/*

* Declare initial window size, position, and display mode

* (single buffer and RGBA). Open window with "hello"

* in its title bar. Call initialization routines.

* Register callback function to display graphics.

* Enter main loop and process events.

*/

int main(int argc, char** argv)

{

glutInit(&argc, argv);

glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);

glutInitWindowSize (250, 250);

glutInitWindowPosition (100, 100);

glutCreateWindow ("hello");

init ();

glutDisplayFunc(display);

glutMainLoop();

return 0; /* ISO C requires main to return int. */

}

The header with the 'int argc, char** argv' is a C and C++ thing for command line parameters. It could probably be void, but would leave the program with little to no options if it wanted it to run a certain way.

Here's where we use glut commands. Init glut using the method parameters GLUT_SINGLE and GLUT_RGB. These are parameters: GLUT_SINGLE should set up a single buffer for the window while GLUT_RGB allows Red/Green/Blue colour values in it. GLUT_RGBA is also a possible option and I assume includes alpha transparency too.

glutWindowSize and glutWindowPosition are self explainatory. glutCreateWindow sets the window title bar text. Size and Position on your desktop. init() sets up the internals to freeglut while glutDisplayFunc() specifies the name of the method to call for displaying things using GL syntax. glutMainLoop() is that main loop I mentioned earlier and should loop through, refreshing the display so when you move the window, it doesn't get corrupted. (Don't quote me on that though).

Return statement exists as an ISO standard. Even if the program never gets to the return statement, it's required.

So that's a window example in freeglut, opengl, and c++. Copy all the code segments into a text file, save as "filename".cpp. (change filename to something else if you wish, change it in your compile statement too though.)

To compile it, you must first have installed the freeglut libraries and opengl libraries AND have a compatible video card.

But that's not all, you must also specify the libraries in the compile statment so it will include them.

g++ -Os filename.cpp -lGL -lglut -lX11 -lXext -o ~/filename

First off, "-Os" is an optimization flag. Good options are -O1, -O2, and -Os. -Os optimizes the program for small size. Can be omitted.

-lGL and -lglut are required, the -l means include library and we are including glut and opengl. (it's not -lfreeglut because freeglut is meant as a replacement for glut, an abandonded library, so requires the same import name.)

You can omit the -lX11 and -lXext, at least, it works on my machine. It still works when I include them, so maybe it's just if you write in C.

Lastly, -o means output and the next parameter is where to put it and what the program is called using a path. ~ means home directory for Unix or GNU/Linux users.

I'm fairly new to OpenGL windows, but I hope this helps other new users to start up their development-fu for hardware accelerated applications.

If learning this low-level stuff isn't for you, check out QT and KDE application libraries. They have this stuff built in already.

Thanks for stopping by and look forward to more.

=-=-=-=-=
Powered by Blogilo

Saturday, April 23, 2011

Installing Adobe Flash "Square" on a 64-bit Linux Distribution, Firefox 4

In the past month I set myself up a beautiful pure 64-bit Gentoo system on my Thinkpad X61. It's not completely ready yet, as I have yet to compile my custom kernel that should allow the wacom screen to be recognized.

Installing 64-bit Flash "Square" should be the exact same procedure on any major GNU/Linux distribution, so there shouldn't be any specific instructions. Also, this instruction set ignores the "proper" distro way of doing things.

Ubuntu has an install-flashplayer deb that does things for the user. Which is preferrable, as the way I am about to describe does not provide automatic updates. And before we continue, I should stress that Flash Square is a PREVIEW and flash is inherantly insecure due to it being a proprietary offering and ubiquitous on the web.

This method installs flash in "userspace", or in a way that does not require admin privileges. This method reduces the consequences if your computer is comprimised through flash by not being able to touch your system.

1. Download Flash Player "Square" from Adobe's web site: http://labs.adobe.com/downloads/flashplayer10_square.html

Check under the heading "64-bit Release Flash Player Downloads" and choose what should be the last option: plugin for 64-bit linux

(I shake my head at Adobe. Flash doesn't run in the kernel; they should change it to "linux-based OS" or the proper "GNU/Linux" label)

2. Extract the .tar.gz download. This can be done via command line by typing "tar -xvf [file]".

3. Make sure that the plugins folder exists. It didn't by default for my system. "mkdir -p ~/.mozilla/plugins/"

My first attempt at this failed because I created the plugins directory in .mozilla/firefox/.

4. Copy the libflashplayer.so file to the user's plugin folder. This command should work: "cp libflashplayer* ~/.mozilla/plugins/"

If you get any errors in the previous commands, you are probably in the wrong directory when typing them, you are typing the double-quotes (don't), or you aren't in the shell/command line. As well, this is for Firefox 4. Theoretically it should work for previous versions of Firefox, but I'm a little lazy to make sure.

And if you haven't checked out Mozilla's newest browser version, you really should. Startup times alone are much improved. Having a default page already cached helps, but the option to load your previously viewed tabs on last exit is convenient.

I have been doing some introductory coding in OpenGL, Freeglut and C++/QT lately. I hope to come out with some tutorials for those as well in the near future.

=-=-=-=-=
Powered by Blogilo

Friday, February 11, 2011

Gentoo Users, QT pt 2

QT 4.6 is officially out for Gentoo's portage. It needs to be unmasked, mind you. But I've now installed it and it looks damned great.

I reinstalled Gentoo over the past week, upgrading to an ext4 filesystem along with all my applications. There is a noticable speed difference with the filesystem upgrade alone, but 4.6 also is improved.

The K3B issue I was having in the last post was solved. Until it gets a newer QT port, I probably won't install it. Plus I installed Gentoo without HAL support, so I may not even be able to use my cd/dvdrom until later. I previously mentioned the drive was having issues. At some point, it got fixed, probably through an update.

While doing this re-install, I had some trouble with my Radeon X1400 mobility card.

I couldn't use desktop effects as they were full of artifacts and my screen was off-kilter. Long story short, I installed xorg-server as opposed to xorg-x11. This installs more of xorg (fonts, etc.) that not everybody needs. I also modified my custom kernel to use pci video card support as a module, which was probably the culprit. After using this new kernel and enabling desktop effects, things run faster than they did previously on my old install.

All in all, quite impressive and great job to KDE and Gentoo teams.

On a slightly related note, it's quite upsetting to see Microsoft executives infiltrate Nokia, bring down their stock, add their retarded phone OS to the mix (which barely anybody wants), possibly comprimising QT and its development (which is probably what they want anyhow) and looking the fool.

The sooner M$ is buried under their incompetance, the better. It's a shame that they act the bully because they cannot compete in the marketplace.

They already drain resources from samsung and lg off their android phones under false pretences of patent infringement.

Quite foolish, and most disappointing, coming from an IT giant. Then again, Canada's ISP giants are also looking like the retards they are. Usage based billing my ass.

They shant get away with it.

=-=-=-=-=
Powered by Blogilo

Thursday, January 20, 2011

Gentoo Users, QT

I was recently updating my gentoo system when I came across a puzzling issue. I was getting updates for QT 4.6.x as well as 4.7.x and there were conflicts all over the place. At least 12 were listed when attempting to emerge world.

I removed all QT 4.7.x packages rather foolishly to see if the conflicts would clear up, which they didn't. After looking closely at some of the packages, it seems that K3b was bringing in all these older qt updates. I removed it from my system, but the problem still persisted. That's why I'm writing this down. I had to explicitly mask the package in order for the problem to go away.

(as root)

echo "app-cdr/k3b" >> /etc/portage/package.mask

My laptop's already not allowing me to use my cdrom very well, perhaps it's dying. I can't burn or play dvd's on it. Keeps giving me HAL errors, regardless of whether it's running. Other burners don't see the drive either.

Anyway, I'll be heading up for the Global Game Jam soon. Cheers, y'all.