Archive

Archive for the ‘cpp’ Category

MFC and mouse wheel focus

December 14th, 2011 No comments

So i am developing a little MFC application using the VS wizard. It features a main (central) view where i am drawing via GDIPlus. Everything worked quite well, until i tried adding mouse wheel support. Turns out, the control that has focus will get wheel events, and no one else. Since i dont want to click into the window before its usable, i have added this little workaround, should work well for the default MFC applications:

1
2
3
4
5
6
7
8
9
10
11
12
BOOL CMainFrame::PreTranslateMessage( MSG* pMsg )
{
    // big workaround for stupid windows behavior:
    if(pMsg->message == WM_MOUSEWHEEL && GetCapture() == NULL)
    {
        // if the mousewheel was used, send it to the window below the cursor, no matter if it has the focus or not.
        pMsg->hwnd = ::WindowFromPoint(pMsg->pt);
        pMsg->lParam = MAKELPARAM(pMsg->pt.x, pMsg->pt.y);
    }
    // return control to the default handlers
    return CFrameWndEx::PreTranslateMessage(pMsg);
}

It overrides "PreTranslateMessage" and redirects the mouse wheel message to the window below the mouse cursor.

Categories: cpp Tags:

how to format bytes as a human readable string without branching

August 8th, 2011 1 comment

its actually not so complicated:

1
2
3
4
5
6
7
8
9
std::string formatBytes(unsigned long bytes)
{
        char tmp[128] = "";
        const char *si_prefix[] = { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
        const int base = 1024;
    int c = std::min((int)(log((double)bytes)/log((double)base)), (int)sizeof(si_prefix) - 1);
    sprintf(tmp, "%1.2f %s", bytes / pow((double)base, c), si_prefix[c]);
        return std::string(tmp);
}
Categories: coding, cpp Tags:

using c++ templates with function pointers

August 2nd, 2011 No comments

so, i am currently writing an XML parser and one part of the code processes attributes of a XML node:

1
2
3
4
5
6
7
Real radius = 1.0f;
if(n->first_attribute("radius"))
  radius   = StringConverter::parseReal(n->first_attribute("radius")->value());

int segments = 8;
if(n->first_attribute("segments"))
  segments = StringConverter::parseInt(n->first_attribute("segments")->value());

so this is very boring to write and also error-prone. So i came up with this handy template that calls the Setter you define with the correct argument:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// some parsing helpers
void parseArgument(const char *str, int &res) { res =Ogre::StringConverter::parseInt(str); }
void parseArgument(const char *str, unsigned int &res) { res =Ogre::StringConverter::parseInt(str); }
void parseArgument(const char *str, Ogre::Real &res) { res = Ogre::StringConverter::parseReal(str); }
void parseArgument(const char *str, Ogre::Vector3 &res) { res = Ogre::StringConverter::parseVector3(str); }
void parseArgument(const char *str, Ogre::Vector2 &res) { res = Ogre::StringConverter::parseVector2(str); }

template <class TVarType>
TVarType getAttribute(xml_node<> *node, const char *attribute_name, const TVarType defaultValue)
{
    TVarType val = defaultValue;
    xml_attribute<> *atr = node->first_attribute(attribute_name);
    if(atr)
        parseArgument(atr->value(), val);
    return val;
}

// template function that calls a setter with an attribute value
template <class TClass,  class TVarType>
TVarType useAttributeForSetter(xml_node<> *node, const char *attribute_name, const TVarType defaultValue, TClass& (TClass::*setterFunction)(TVarType), TClass &instance, bool setDefault = true)
{
    TVarType val = defaultValue;
    xml_attribute<> *atr = node->first_attribute(attribute_name);
    if(atr)
    {
        parseArgument(atr->value(), val);
        // now try to use the setter
        (instance.*setterFunction)(val);
    } else if(!atr && setDefault)
    {
        (instance.*setterFunction)(val);
    }
    return val;
}

and now it looks much easier:

1
2
3
4
CircleShape cs = CircleShape();
// where the magic happens ;)
useAttributeForSetter<CircleShape, Real>(n, "radius", 1, &CircleShape::setRadius, cs);
useAttributeForSetter<CircleShape, unsigned int>(n, "segments", 8, &CircleShape::setNumSeg, cs);
Categories: cpp Tags:

minimal working Angelscript example

May 13th, 2011 No comments
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <angelscript.h>
#include <scriptbuilder/scriptbuilder.h>

int plus(int a, int b)
{
    return a+b;
}

void testAngelscript()
{
    AngelScript::asIScriptEngine *engine = AngelScript::asCreateScriptEngine(ANGELSCRIPT_VERSION);
    int result = engine->RegisterGlobalFunction("int plus(int, int)", AngelScript::asFUNCTIONPR(plus, (int, int), int), AngelScript::asCALL_CDECL); assert( r >= 0 );
    AngelScript::CScriptBuilder builder;
    result = builder.StartNewModule(engine, "Script"); assert( r >= 0 );
    AngelScript::asIScriptModule *mod = engine->GetModule("Script", AngelScript::asGM_CREATE_IF_NOT_EXISTS);
    result = builder.AddSectionFromMemory("void main() { int a = 1; int b = 2; int c = plus(a, b); }", "main"); assert( r >= 0 );
    result = builder.BuildModule(); assert( r >= 0 );
    int funcId = mod->GetFunctionIdByDecl("void main()");
    AngelScript::asIScriptContext *context = engine->CreateContext();
    result = context->Prepare(funcId); assert( r >= 0 );
    result = context->Execute(); assert( r >= 0 );
    context->Release();
    engine->Release();
}

very compact ;)

just use as an example, you would need to add much more error checking...

Categories: cpp Tags:

using libcurl to download files

July 25th, 2010 No comments

this example shows how to use curl for downloading a file in c++ with a class and a progress callback.

this is pseudocode, means you need some header for this to work, etc :)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#define CURL_STATICLIB
#include <stdio.h>
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>
#include <string>

class MyClass;

typedef struct job_info_t {
 int jobID;
 MyClass *parent;
} struct job_info_t;

int progress_callback(void *data, double download_total_size, double download_total_size_done, double ultotal, double uldone)
{
    job_info_t *jinfo = (job_info_t *)data;
    if(!jinfo) return 1;
   
    jinfo->parent->reportProgress(jinfo->jobID, download_total_size, download_total_size_done);
    return 0;
}

void MyClass::reportProgress(int jobID, double download_total_size, double download_total_size_done)
{
    printf("DLFile-%04d|progress: %0.3f\n", jobID, download_total_size_done / download_total_size);
}

int MyClass::downloadFile(int jobID, std::string localFile, string url)
{
    job_info jinfo;
    jinfo.parent = this;
    jinfo.jobID = jobID;
   
    CURL *curl = curl_easy_init();
    if(!curl)
    {
        printf("DLFile-%04d|error creating curl: %s\n", jobID, localFile.string().c_str());
        printf("DLFile-%04d|download URL: %s\n", jobID, url.c_str());
        return 1;
    }
    FILE *outFile = fopen(localFile.string().c_str(), "wb");
    if(!outFile)
    {
        perror("error opening file");
        printf("DLFile-%04d|error opening local file: %s.\n", jobID, localFile.string().c_str());
        printf("DLFile-%04d|download URL: %s\n", jobID, url.c_str());
        return 2;
    }

    char *curl_err_str[CURL_ERROR_SIZE];
    memset(curl_err_str, 0, CURL_ERROR_SIZE);

    CURLcode res;
    curl_easy_setopt(curl, CURLOPT_URL,              url.c_str());
   
    // logging stuff
//  curl_easy_setopt(curl, CURLOPT_STDERR,           InstallerLog::getSingleton()->getLogFilePtr());
    curl_easy_setopt(curl, CURLOPT_ERRORBUFFER,      curl_err_str[0]);

    // progess stuff
    curl_easy_setopt(curl, CURLOPT_NOPROGRESS,       0);
    curl_easy_setopt(curl, CURLOPT_PROGRESSDATA,     &jinfo);
    curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, &progress_callback);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA,        outFile);

    // http related settings
    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION,   1); // follow redirects
    curl_easy_setopt(curl, CURLOPT_AUTOREFERER,      1); // set the Referer: field in requests where it follows a Location: redirect.
    curl_easy_setopt(curl, CURLOPT_MAXREDIRS,        20);
    curl_easy_setopt(curl, CURLOPT_USERAGENT,        "YourUserAgent");
    curl_easy_setopt(curl, CURLOPT_FILETIME,         1);
   
   
    res = curl_easy_perform(curl);
    curl_easy_cleanup(curl);
    fclose(outFile);

    // print curl error if existing
    if(res != CURLE_OK)
    {
        printf("DLFile-%04d| CURL returned: %d\n", jobID, res);
        printf("DLFile-%04d| CURL error: %s\n", jobID, curl_err_str);
        return 3;
    }
    return 0;
}
Categories: coding, cpp Tags:

embedding Ogre 1.7 into wxWidgets 2.9 cross platform

May 17th, 2010 3 comments

well, its harder than you might think, but i finally found this to be working quite well:

wxutils.h:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*
 * File:   wxutils.h
 * Author: thomas
 *
 * Created on May 12, 2010, 9:23 AM
 */


#ifndef _WXUTILS_H
#define _WXUTILS_H

#include <wx/wx.h>
#include <string.h>

std::string getWindowHandle(wxWindow *window);

#endif  /* _WXUTILS_H */

wxutils.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include "wxutils.h"

#include <iostream>
#include <sstream>

// this is in a separate file to reduce the clutter in the global namespace and their conflicts

#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX
# ifdef __WXGTK__
#include <gdk/gdk.h>
#include <gtk/gtk.h> // just this should suffice as it should include gdk.h itself
/* Seems to be needed under Linux */
//#include <wx/gtk/win_gtk.h>
#include "wx/gtk/private/win_gtk.h"
#include <gdk/gdkx.h>
#include <GL/glx.h>

#if  wxCHECK_VERSION(2, 9, 0)
#define piz(wxwin) WX_PIZZA((wxwin)->m_wxwindow)
#define GetXWindow(wxwin) (wxwin)->m_wxwindow ? \
        GDK_WINDOW_XWINDOW(((GtkWidget*)piz(wxwin))->window) : \
        GDK_WINDOW_XWINDOW((wxwin)->m_widget->window)

#else
#define GetXWindow(wxwin) (wxwin)->m_wxwindow ? \
        GDK_WINDOW_XWINDOW(GTK_PIZZA((wxwin)->m_wxwindow)->bin_window) : \
        GDK_WINDOW_XWINDOW((wxwin)->m_widget->window)

#endif

#ifdef __WXX11__
#include "wx/x11/privx.h"
#define GetXWindow(wxwin)   ((Window)(wxwin)->GetHandle())
#endif

# endif //__WXGTK__
#endif //OGRE_PLATFORM_LINUX

std::string getWindowHandle(wxWindow *window)
{
#if WIN32
    std::stringstream sstr;
    size_t hWnd = (size_t)window->GetHandle();
    sstr << hWnd;
    std::string result = sstr.str();
    return result;
#else

    // TODO: Someone test this. you might to use "parentWindowHandle" if this
    // does not work.  Ogre 1.2 + Linux + GLX platform wants a string of the
    // format display:screen:window, which has variable types ulong:uint:ulong.
    GtkWidget* widget = window->GetHandle();
    //gtk_widget_set_double_buffered (widget, FALSE);
    gtk_widget_realize( widget );   // Mandatory. Otherwise, a segfault happens.
    //XSync(GDK_WINDOW_XDISPLAY(widget->window), False);
   
    Display* display = GDK_WINDOW_XDISPLAY( widget->window );

   
    //Window wid = GetXWindow(window);
    Window wid = GDK_WINDOW_XWINDOW( widget->window );

    std::stringstream sstr;
    /* Get the right display (DisplayString() returns ":display.screen") */
    std::string displayStr = DisplayString( display );
    displayStr = displayStr.substr( 1, ( displayStr.find( ".", 0 ) - 1 ) );

    int screenNum = DefaultScreen( display );

    /* Put all together */
    printf("using display: %s\n", displayStr.c_str());
    printf("using screen: %d\n", screenNum);
    printf("using window: 0x%x\n", wid);

    // old format:
    sstr << displayStr << ':' << screenNum << ':' << wid;
    std::string result = sstr.str();

    printf("getWindowHandle() = %s\n", result.c_str());
    return result;
#endif
}

how to use (panel_viewport is the widget that should show the 3d content):

1
2
3
4
5
6
...
mWindow = mRoot->initialise(false);
Ogre::NameValuePairList params;
params["externalWindowHandle"] = getWindowHandle(panel_viewport);
mWindow = Ogre::Root::getSingleton().createRenderWindow("OgreRenderWindow", 640, 480, false, &params);
...

works great so far under windows 7 and ubuntu 9.10 with Ogre 1.7 and wxWidgets 2.9

Categories: coding, cpp Tags:

wxWidgets logging quickstart

May 2nd, 2010 No comments

so, its really easy if you know how ;)

This example inits a file log and logs to std::cout by default.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void MyApp::initLogging()
{
    // log everything
    wxLog::SetLogLevel(wxLOG_Max);
    wxLog::SetVerbose();

    // use stdout always
    wxLog *logger_cout = new wxLogStream(&std::cout);
    wxLog::SetActiveTarget(logger_cout);

    FILE *f = fopen("mylog.txt", "w");
    if(f)
    {
        // and a file log
        wxLog *logger_file = new wxLogStderr(f);
        wxLogChain *logChain = new wxLogChain(logger_file);
    }
    wxLogStatus(wxT("log started"));
}

in your application you can then use

1
wxLog{Status,Verbose,Info,Message,Warning,Error,FatalError}(...)
Categories: cpp Tags:

benchmarking std::vector

January 12th, 2010 No comments

so i always wondered whats the fastest way is to iterate over a vector. So with this little snippet you can find out for yourself:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
// some simple std::vector benchmark tool
// Jan 2010, thomas{AT}thomasfischer{DOT}biz
// also see http://stackoverflow.com/questions/776624/whats-faster-iterating-an-stl-vector-with-vectoriterator-or-with-at
#include <stdio.h>
#include <vector>
#include "Timer.h"

#define VECSIZE 500000


typedef struct foo_t {
    char tmp[2];
} foo_t;

int main(int argc, char **argv)
{
    int amount = VECSIZE;
    int tests = 10;
    printf("testing with %d elements a %d bytes (%0.2f MB) and %d runs per test\n", amount, sizeof(foo_t), (amount*sizeof(foo_t))/1024.0f/1024.0f, tests);
   
    double time = 0.0f;
    for(int i=0;i<tests;i++)
    {
        std::vector<foo_t> vec;
        vec.reserve(amount);
        foo_t f; // with random data in it
        Timer *t = new Timer();
        for(int i=0;i<amount;i++)
            vec.push_back(f);
        time += t->elapsed();
    }
    printf("add time (resized before): %f\n", time/tests);


    time=0;
    for(int i=0;i<tests;i++)
    {
        std::vector<foo_t> vec;
        foo_t f; // with random data in it
        Timer *t = new Timer();
        for(int i=0;i<amount;i++)
            vec.push_back(f);
        time += t->elapsed();
    }
    printf("add time (dynamic resize): %f\n", time/tests);


    time=0;
    for(int i=0;i<tests;i++)
    {
        std::vector<foo_t> vec;
        foo_t f; // with random data in it
        for(int i=0;i<amount;i++)
            vec.push_back(f);

        Timer *t = new Timer();
        for(std::vector<foo_t>::iterator it=vec.begin(); it!=vec.end(); it++)
        {
            // some example usage
            it->tmp[1] = 0;
        }
        time += t->elapsed();
    }
    printf("iterate time (version #1): %f\n", time/tests);


    time=0;
    for(int i=0;i<tests;i++)
    {
        std::vector<foo_t> vec;
        foo_t f; // with random data in it
        for(int i=0;i<amount;i++)
            vec.push_back(f);

        Timer *t = new Timer();
        std::vector<foo_t>::iterator vecEnd = vec.end();
        for(std::vector<foo_t>::iterator it=vec.begin(); it!=vecEnd; ++it)
        {
            // some example usage
            it->tmp[1] = 0;
        }
        time += t->elapsed();
    }
    printf("iterate time (version #2): %f\n", time/tests);


    time=0;
    for(int i=0;i<tests;i++)
    {
        std::vector<foo_t> vec;
        foo_t f; // with random data in it
        for(int i=0;i<amount;i++)
            vec.push_back(f);

        Timer *t = new Timer();
        for(int i=0; i<amount; i++)
        {
            // some example usage
            vec[i].tmp[1] = 0;
        }
        time += t->elapsed();
    }
    printf("iterate time (version #3): %f\n", time/tests);


    time=0;
    for(int i=0;i<tests;i++)
    {
        std::vector<foo_t> vec;
        foo_t f; // with random data in it
        for(int i=0;i<amount;i++)
            vec.push_back(f);

        Timer *t = new Timer();
        for(unsigned int i=0; i<vec.size(); ++i)
        {
            // some example usage
            vec.at(i).tmp[1] = 0;
        }
        time += t->elapsed();
    }
    printf("iterate time (version #4): %f\n", time/tests);


    time=0;
    for(int i=0;i<tests;i++)
    {
        foo_t vec[VECSIZE];
       
        Timer *t = new Timer();
        for(int i=0; i<amount; ++i)
        {
            // some example usage
            vec[i].tmp[1] = 0;
        }
        time += t->elapsed();
    }
    printf("iterate over array (version #1): %f\n", time/tests);

    time=0;
    for(int i=0;i<tests;i++)
    {
        foo_t *vec = (foo_t *)malloc(sizeof(foo_t) * amount);
       
        Timer *t = new Timer();
        for(int i=0; i<amount; ++i)
        {
            // some example usage
            vec[i].tmp[1] = 0;
        }
        time += t->elapsed();
        free(vec);
    }
    printf("iterate over array (version #2): %f\n", time/tests);

    return 0;
}

to compile, add the Timer.h from my previous post :)

which results in the following output on my windows machine (/Oi /O2)

testing with 500000 elements a 2 bytes (0.95 MB) and 10 runs per test
add time (resized before):       0.005281
add time (dynamic resize):       0.007693
iterate time (version #1):       0.004180
iterate time (version #2):       0.004107
iterate time (version #3):       0.000903
iterate time (version #4):       0.004891
iterate over array (version #1): 0.000277
iterate over array (version #2): 0.000773

what are your results?

Categories: coding, cpp, funstuff Tags:

cross platform timer class

January 12th, 2010 No comments

So, as it seems there is no usable class in boost which can measure time down to milliseconds, so i rolled my own. (in fact i was a bit shocked that the timer class that ships with Boost only measures used CPU time) I tested it under linux and windows, and its working well:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// simple Timer class, Jan 2010, thomas{AT}thomasfischer{DOT}biz
// tested under windows and linux
// license: do whatever you want to do with it ;)
#ifndef TIMER_H__
#define TIMER_H__

// boost timer is awful, measures cpu time on linux only...
// thus we have to hack together some cross platform timer :(

#ifndef WIN32
#include <sys/time.h>
#else
#include <windows.h>
#endif

class Timer
{
protected:
#ifdef WIN32
    LARGE_INTEGER start;
#else
    struct timeval start;
#endif

public:
    Timer()
    {
        restart();
    }

    double elapsed()
    {
#ifdef WIN32
        LARGE_INTEGER tick, ticksPerSecond;
        QueryPerformanceFrequency(&ticksPerSecond);
        QueryPerformanceCounter(&tick);
        return ((double)tick.QuadPart - (double)start.QuadPart) / (double)ticksPerSecond.QuadPart;
#else
        struct timeval now;
        gettimeofday(&now, NULL);
        return (now.tv_sec - start.tv_sec) + (now.tv_usec - start.tv_usec)/1000000.0;
#endif
    }

    void restart()
    {
#ifdef WIN32
        QueryPerformanceCounter(&start);       
#else
        gettimeofday(&start, NULL);
#endif
    }
};

#endif //TIMER_H__

how you use it:

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#include "Timer.h"

int main(int argc, char **argv)
{
    Timer *t = new Timer();
    Sleep(1000);
    printf("time gone: %f\n", t->elapsed());
    return 0;
}

which results in my windows machine into this output:

time gone: 0.999699
Categories: coding, cpp, tutorials Tags: