librocket GUI support

Ok, that worked i think, now i dont get could not find rocket error (for example how i get for bullet in next code sample).

But there is other problem, od i need to checkout some other branch (i am using whatever is default)

makepanda/makepanda.py --nothing --use-python --use-gl --use-tinydisplay --installer --threads 4  --use-bullet --use-freetype --use-directcam --use-rocket
Generating library cache...
WARNING: Could not locate thirdparty package bullet, excluding from build
Generating dependencies...
Storing dependency cache.
Elapsed Time: 1 sec
Could not find source file: p3rocket_composite1.cxx
Build terminated.

EDIT1: i am using librocket 1.2.1 source release, could not get latest github master to build

You’re not using the latest CVS version of Panda3D. Update the panda/src/rocket directory.

Just wanted to pop a quick note: I’m still struggling with the segfault; it appears that nothing in init_librocket() in config_rocket.cxx is being called. (Even put a printf as the first line in that; doesn’t ever print.)

Now I’m tracing back through some of the interogate/dtools code… (just don’t have as much time to poke this as I would like). Also, I should note that I don’t have debug symbols built; that’s proving to be annoyingly time consuming.

I’m pretty sure that in ‘built/tmp/libp3rocket_module.cxx’(generated interogate code)

Dtool_PyModuleInitHelper( defs, "libp3rocket");

isn’t getting called. Which puts the segfault in:

LibrayDef   *defs[] = {&libp3rocket_moddef, NULL };

Here’s the full generated file:

#include "dtoolbase.h"
#include "interrogate_request.h"

#undef _POSIX_C_SOURCE
#include "py_panda.h"

extern LibrayDef libp3rocket_moddef ;
#ifdef _WIN32
extern "C" __declspec(dllexport) void initlibp3rocket();
#else
extern "C" void initlibp3rocket();
#endif

void initlibp3rocket() 
{
  LibrayDef   *defs[] = {&libp3rocket_moddef, NULL };
   Dtool_PyModuleInitHelper( defs, "libp3rocket");



}

Any suggestions on where to look next would be appreciated.

Sometimes a segfault will cause printf statements that already happened not to print (because the printf output is still cached and hasn’t yet been written to the output stream), so you have to be careful. You should use fprintf(stderr) instead of printf(), in general, because stderr is flushed automatically, so this problem is less likely with fprintf(stderr). Or, using C++ interfaces, use cerr instead of cout.

But assuming you’re not getting tricked by printf caching, and that init_librocket() really isn’t getting called, that doesn’t necessarily mean that the crash is occurring earlier in init_libp3rocket(). Perhaps the crash is occurring even before that function is getting called (in some static init operation, for instance). This is common when running against a slightly different version than the one that was compiled against, for instance, as structures end up different sizes and memory gets written to incorrectly. To really prove that the crash is occurring in init_libp3rocket(), you need to put an fprintf() in the beginning of that function, and an fprintf() at the end of that function.

David

I was actually using fflush(stdout); after the printfs, to flush the cache, just in case that was happening.

Whitelynx got debug symbols built on his machine, and we’re looking through gdb now. It definitely seems to be segfaulting on

LibrayDef   *defs[] = {&libp3rocket_moddef, NULL };

We’ll post the backtrace shortly.

Here’s the backtrace (bt full) from the segfault on my laptop:
paste.skewedaspect.com/show/88/

And here’s the code I’m using for the test: (probably not the same as what morgul was running, but it demonstrates the same issue)

#!/usr/bin/env python2
from direct.showbase.ShowBase import ShowBase

print "Imported ShowBase."

import rocket

print "Imported rocket."

from panda3d.rocket import RocketRegion, RocketInputHandler

print "Imported panda3d.rocket."


class MyApp(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        print "ShowBase init finished."

        r = RocketRegion.make('pandaRocket', self.win)
        r.setActive(1)

        print "RocketRegion created."

        ih = RocketInputHandler()
        self.mouseWatcher.attachNewNode(ih)
        r.setInputHandler(ih)

        print "RocketInputHandler created."

        context = r.getContext()

        print "Got rocket context."


app = MyApp()
app.run()

[i]EDIT: New backtrace after recompiling Panda: paste.skewedaspect.com/show/89/

As far as I’m aware no actual code was changed here, so I’m not sure why it’s segfaulting in a different spot than before.[/i]

Hmm, I’m still baffled. What happens if you do this (on Linux only):

import libp3rocket
print "imported libp3rocket"
import rocket
print "imported rocket"
from panda3d.rocket import *

At which line does it fail?

Well, this is interesting:

[morgul] ~ > python
Python 2.7.2+ (default, Oct  4 2011, 20:06:09) 
[GCC 4.6.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import libp3rocket 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: /usr/lib64/panda3d/libp3rocket.so: undefined symbol: _ZN5boost6python23throw_error_already_setEv

So, import libp3rocket fails, with an error about a missing symbol… Any ideas?

Oh, I suppose that is to be expected if your librocket is compiled as a static library instead of a shared one. Bah, this is a mess.

Well, still no success. I’ve decided to stop banging my head against this wall. However, I’ve instead pulled the RocketInputHandler out of the current repo, and have been having some success in integrating it in my standalone solution (pyrokit, mentioned above).

In doing so, I’ve found some bugs in RocketInputHandler. I’ll list them, and then provide a patch.

  • libRocket’s mouse buttons are 0 based, not 1 based.
  • _keys was not being cleared properly. (copy/paste error. _mouse_buttons was being cleared instead.)
  • function keys were not being passed through.
  • modifiers should also send key up/down events.
  • libRocket accepts/expects key up/down events for 0-9 and a-z, in addition to the text input. (Not required, but allows for listening for keypress events)

Here is the patch:

Index: panda/src/rocket/rocketInputHandler.cxx
===================================================================
RCS file: /cvsroot/panda3d/panda/src/rocket/rocketInputHandler.cxx,v
retrieving revision 1.1
diff -u -r1.1 rocketInputHandler.cxx
--- panda/src/rocket/rocketInputHandler.cxx     7 Jan 2012 19:02:41 -0000       1.1
+++ panda/src/rocket/rocketInputHandler.cxx     20 Jan 2012 03:53:40 -0000
@@ -176,6 +176,83 @@
           _keys[KI_INSERT] = down;
         } else if (be._button == KeyboardButton::del()) {
           _keys[KI_DELETE] = down;
+        } else if (be._button == KeyboardButton::caps_lock()) {
+          _keys[KI_CAPITAL] = down;
+        } else if (be._button == KeyboardButton::f1()) {
+          _keys[KI_F1] = down;
+        } else if (be._button == KeyboardButton::f10()) {
+          _keys[KI_F10] = down;
+        } else if (be._button == KeyboardButton::f11()) {
+          _keys[KI_F11] = down;
+        } else if (be._button == KeyboardButton::f12()) {
+          _keys[KI_F12] = down;
+        } else if (be._button == KeyboardButton::f13()) {
+          _keys[KI_F13] = down;
+        } else if (be._button == KeyboardButton::f14()) {
+          _keys[KI_F14] = down;
+        } else if (be._button == KeyboardButton::f15()) {
+          _keys[KI_F15] = down;
+        } else if (be._button == KeyboardButton::f16()) {
+          _keys[KI_F16] = down;
+        } else if (be._button == KeyboardButton::f2()) {
+          _keys[KI_F2] = down;
+        } else if (be._button == KeyboardButton::f3()) {
+          _keys[KI_F3] = down;
+        } else if (be._button == KeyboardButton::f4()) {
+          _keys[KI_F4] = down;
+        } else if (be._button == KeyboardButton::f5()) {
+          _keys[KI_F5] = down;
+        } else if (be._button == KeyboardButton::f6()) {
+          _keys[KI_F6] = down;
+        } else if (be._button == KeyboardButton::f7()) {
+          _keys[KI_F7] = down;
+        } else if (be._button == KeyboardButton::f8()) {
+          _keys[KI_F8] = down;
+        } else if (be._button == KeyboardButton::f9()) {
+          _keys[KI_F9] = down;
+        } else if (be._button == KeyboardButton::help()) {
+          _keys[KI_HELP] = down;
+        } else if (be._button == KeyboardButton::lalt()) {
+          _keys[KI_LMENU] = down;
+        } else if (be._button == KeyboardButton::lcontrol()) {
+          _keys[KI_LCONTROL] = down;
+        } else if (be._button == KeyboardButton::lshift()) {
+          _keys[KI_LSHIFT] = down;
+        } else if (be._button == KeyboardButton::meta()) {
+          // Not sure which of these is correct...
+          //_keys[KI_LWIN] = down;
+          _keys[KI_LMETA] = down;
+        } else if (be._button == KeyboardButton::num_lock()) {
+          _keys[KI_NUMLOCK] = down;
+        } else if (be._button == KeyboardButton::page_down()) {
+          _keys[KI_NEXT] = down;
+        } else if (be._button == KeyboardButton::page_up()) {
+          _keys[KI_PRIOR] = down;
+        } else if (be._button == KeyboardButton::pause()) {
+          _keys[KI_PAUSE] = down;
+        } else if (be._button == KeyboardButton::print_screen()) {
+          _keys[KI_SNAPSHOT] = down;
+        } else if (be._button == KeyboardButton::ralt()) {
+          _keys[KI_RMENU] = down;
+        } else if (be._button == KeyboardButton::rcontrol()) {
+          _keys[KI_RCONTROL] = down;
+        } else if (be._button == KeyboardButton::rshift()) {
+          _keys[KI_RSHIFT] = down;
+        } else if (be._button == KeyboardButton::scroll_lock()) {
+          _keys[KI_SCROLL] = down;
+        /* What is shift_lock? It's not caps_lock apparently...
+        } else if (be._button == KeyboardButton::shift_lock()) {
+          _keys[KI_SHIFT_LOCK] = down;
+        */
+        } else {
+          // libRocket accepts/expects keypress events
+                 // as well as text input
+          char asciiChar = be._button.get_ascii_equivalent();
+          if ('0' <= asciiChar && asciiChar <= '9') {
+            _keys[asciiChar - '0' + KI_0] = down;
+          } else if ('a' <= asciiChar && asciiChar <= 'z') {
+            _keys[asciiChar - 'a' + KI_A] = down;
+          }
         }
       }
     }
@@ -204,9 +281,9 @@
     ButtonActivityMap::const_iterator it;
     for (it = _mouse_buttons.begin(); it != _mouse_buttons.end(); ++it) {
       if (it->second) {
-        context->ProcessMouseButtonDown(it->first, _modifiers);
+        context->ProcessMouseButtonDown(it->first - 1, _modifiers);
       } else {
-        context->ProcessMouseButtonUp(it->first, _modifiers);
+        context->ProcessMouseButtonUp(it->first - 1, _modifiers);
       }
     }
     _mouse_buttons.clear();
@@ -226,7 +303,7 @@
         context->ProcessKeyUp((KeyIdentifier) it->first, _modifiers);
       }
     }
-    _mouse_buttons.clear();
+    _keys.clear();
   }
 
   if (_text_input.size() > 0) {

I tried to match the code styling as much as I could, and I’ve verified this code works in pyrokit; can’t test it in panda. Let me know if there’s anything you need clarification on.

Working with Morgul I’ve tried this on my computer (Ubuntu 11.10) and got a good bit farther, but ran into another indecipherable error.

Note: Morgul’s patch above has been accepted and merged with the libRocket tree on GitHub.

I found that I can reproduce the segfault issue by calling:

from panda3d.rocket import *

but if I use:

from panda3d import rocket

this succeeds without incident.

Where I run into trouble is trying to make any calls to rocket. This results in an Undefined Symbol error.

Here’s my current test app:

from direct.showbase.ShowBase import ShowBase
from panda3d import rocket


class MyApp(ShowBase):

    def __init__(self):
        ShowBase.__init__(self)
        r = rocket.RocketRegion.make('pandaRocket', self.win)
        r.setActive(1)

        ih = rocket.RocketInputHandler()
        self.mouseWatcher.attachNewNode(ih)
        r.setInputHandler(ih) 

        context = r.getContext()
app = MyApp() 
app.run() 

And he’s the error I receive:

Known pipe types:
  glxGraphicsPipe
(all display modules loaded.)
:audio(error):   load_dso(libp3openal_audio.so) failed, will use NullAudioManager
:audio(error):     No error.
Traceback (most recent call last):
  File "test.py", line 16, in <module>
    app = MyApp() 
  File "test.py", line 8, in __init__
    r = rocket.RocketRegion.make('pandaRocket', base.win) 
  File "/usr/share/panda3d/panda3d.py", line 202, in __getattr__
    mod = self.__manager__.libimport(lib)
  File "/usr/share/panda3d/panda3d.py", line 107, in libimport
    return __import__(name)
ImportError: /usr/lib64/panda3d/libp3rocket.so: undefined symbol: _ZN5boost6python23throw_error_already_setEv

So, I am able to actually import libRocket and attempt to use it, but then that attempt immediately fails. Suggestions, anyone? Thanks in advance.

@morgul: thanks for the patch, I’ll review and check it in shortly.
I don’t understand why you’re mapping lalt and ralt to LMENU and RMENU. The menu key is different from the alt key, isn’t it?
libRocket handles modifier keys using a separate bitmask, I think these extra definitions are for specialised keyboards.

@Burstaholic: Interesting that the other import method (which uses lazy loading) does work. Maybe it has something to do with ShowBase being initialised before the library is actually being loaded, the first time you create a RocketRegion?

As for the error, sorry, that’s my fault. I forgot to add boost_python to the libraries to link to in makepanda.

What do you mean with “GitHub”? I wasn’t aware that there was any git repository for my libRocket implementation?

Oh, and welcome to the forums! :slight_smile:

Rocket actually seems a bit dumb about, well, everything. (I don’t mean dumb as in ‘this is stupid’, rather, dumb as in ‘simple’.) From what I can tell, the only way to, say, pop a menu when the user pressed the windows key, is to also send the keydown for the windows key. Once I realized that, I decided to be as all-inclusive as I could. Why you’d want to trigger logic on the ALT keypress, I don’t know, but I figured, why not allow it?

As for R/LALT => R/LMENU… some of the define names are weird in Rocket. I don’t have the code infront of me, atm, but I remember trying to puzzle out what alt was, and thinking that since ‘Application key’ was apparently different from ‘menu’, R/LMENU must be ALT. I could be dead wrong, but it made sense at the time.

On the subject of input, I’ve got another patch for you, which I’ll be sending as soon as I get in to work. This one fixes issues with text input (The current implementation sends characters for delete and backspace, which royally mess up text input in forms), and adds auto-repeat support for some keys. (Panda’s smart about when it sends text, so letters/numbers auto-repeat. Delete/Backspace/Left/Right/Up/Down currently don’t, since librocket leaves auto-repeat up to the user.)

And as for Burst’s mention of GitHub, I’m pretty sure he got confused; I had a patch fixing librocket’s python bindings (the ones in git have been broken since october, it looks like), and that got accepted while he and I were working on things together. I think he thought my patch to input was the patch to rocket, not to panda.

Yup, got my patches confused. Carry on citizen, nothing to see here :stuck_out_tongue:

EDIT: Just realized this includes my previous patch; sorry about that. Apply this one instead of the previous one.

Here’s the new patch:

Index: panda/src/rocket/rocketInputHandler.cxx
===================================================================
RCS file: /cvsroot/panda3d/panda/src/rocket/rocketInputHandler.cxx,v
retrieving revision 1.1
diff -u -r1.1 rocketInputHandler.cxx
--- panda/src/rocket/rocketInputHandler.cxx     7 Jan 2012 19:02:41 -0000       1.1
+++ panda/src/rocket/rocketInputHandler.cxx     25 Jan 2012 16:51:25 -0000
@@ -111,6 +111,20 @@
         break;
 
       case ButtonEvent::T_repeat:
+               // TODO: More may need to be added later.
+        if (be._button == KeyboardButton::backspace()) {
+          _repeated_keys[KI_BACK] = true;
+        } else if (be._button == KeyboardButton::del()) {
+          _repeated_keys[KI_DELETE] = true;
+        } else if (be._button == KeyboardButton::left()) {
+          _repeated_keys[KI_LEFT] = true;
+        } else if (be._button == KeyboardButton::up()) {
+          _repeated_keys[KI_UP] = true;
+        } else if (be._button == KeyboardButton::right()) {
+          _repeated_keys[KI_RIGHT] = true;
+        } else if (be._button == KeyboardButton::down()) {
+          _repeated_keys[KI_DOWN] = true;
+        } // end if
         break;
 
       case ButtonEvent::T_up:
@@ -126,7 +140,10 @@
         break;
 
       case ButtonEvent::T_keystroke:
-        _text_input.push_back(be._keycode);
+        // Ignore control characters; otherwise, they actually get added to strings in the UI.
+        if (be._keycode > 0x1F and (be._keycode < 0x7F or be._keycode > 0x9F)){
+          _text_input.push_back(be._keycode);
+        }
         break;
 
       case ButtonEvent::T_resume_down:
@@ -176,6 +193,83 @@
           _keys[KI_INSERT] = down;
         } else if (be._button == KeyboardButton::del()) {
           _keys[KI_DELETE] = down;
+        } else if (be._button == KeyboardButton::caps_lock()) {
+          _keys[KI_CAPITAL] = down;
+        } else if (be._button == KeyboardButton::f1()) {
+          _keys[KI_F1] = down;
+        } else if (be._button == KeyboardButton::f10()) {
+          _keys[KI_F10] = down;
+        } else if (be._button == KeyboardButton::f11()) {
+          _keys[KI_F11] = down;
+        } else if (be._button == KeyboardButton::f12()) {
+          _keys[KI_F12] = down;
+        } else if (be._button == KeyboardButton::f13()) {
+          _keys[KI_F13] = down;
+        } else if (be._button == KeyboardButton::f14()) {
+          _keys[KI_F14] = down;
+        } else if (be._button == KeyboardButton::f15()) {
+          _keys[KI_F15] = down;
+        } else if (be._button == KeyboardButton::f16()) {
+          _keys[KI_F16] = down;
+        } else if (be._button == KeyboardButton::f2()) {
+          _keys[KI_F2] = down;
+        } else if (be._button == KeyboardButton::f3()) {
+          _keys[KI_F3] = down;
+        } else if (be._button == KeyboardButton::f4()) {
+          _keys[KI_F4] = down;
+        } else if (be._button == KeyboardButton::f5()) {
+          _keys[KI_F5] = down;
+        } else if (be._button == KeyboardButton::f6()) {
+          _keys[KI_F6] = down;
+        } else if (be._button == KeyboardButton::f7()) {
+          _keys[KI_F7] = down;
+        } else if (be._button == KeyboardButton::f8()) {
+          _keys[KI_F8] = down;
+        } else if (be._button == KeyboardButton::f9()) {
+          _keys[KI_F9] = down;
+        } else if (be._button == KeyboardButton::help()) {
+          _keys[KI_HELP] = down;
+        } else if (be._button == KeyboardButton::lalt()) {
+          _keys[KI_LMENU] = down;
+        } else if (be._button == KeyboardButton::lcontrol()) {
+          _keys[KI_LCONTROL] = down;
+        } else if (be._button == KeyboardButton::lshift()) {
+          _keys[KI_LSHIFT] = down;
+        } else if (be._button == KeyboardButton::meta()) {
+          // Not sure which of these is correct...
+          //_keys[KI_LWIN] = down;
+          _keys[KI_LMETA] = down;
+        } else if (be._button == KeyboardButton::num_lock()) {
+          _keys[KI_NUMLOCK] = down;
+        } else if (be._button == KeyboardButton::page_down()) {
+          _keys[KI_NEXT] = down;
+        } else if (be._button == KeyboardButton::page_up()) {
+          _keys[KI_PRIOR] = down;
+        } else if (be._button == KeyboardButton::pause()) {
+          _keys[KI_PAUSE] = down;
+        } else if (be._button == KeyboardButton::print_screen()) {
+          _keys[KI_SNAPSHOT] = down;
+        } else if (be._button == KeyboardButton::ralt()) {
+          _keys[KI_RMENU] = down;
+        } else if (be._button == KeyboardButton::rcontrol()) {
+          _keys[KI_RCONTROL] = down;
+        } else if (be._button == KeyboardButton::rshift()) {
+          _keys[KI_RSHIFT] = down;
+        } else if (be._button == KeyboardButton::scroll_lock()) {
+          _keys[KI_SCROLL] = down;
+        /* What is shift_lock? It's not caps_lock apparently...
+        } else if (be._button == KeyboardButton::shift_lock()) {
+          _keys[KI_SHIFT_LOCK] = down;
+        */
+        } else {
+          // libRocket accepts/expects keypress events
+                 // as well as text input
+          char asciiChar = be._button.get_ascii_equivalent();
+          if ('0' <= asciiChar && asciiChar <= '9') {
+            _keys[asciiChar - '0' + KI_0] = down;
+          } else if ('a' <= asciiChar && asciiChar <= 'z') {
+            _keys[asciiChar - 'a' + KI_A] = down;
+          }
         }
       }
     }
@@ -204,9 +298,9 @@
     ButtonActivityMap::const_iterator it;
     for (it = _mouse_buttons.begin(); it != _mouse_buttons.end(); ++it) {
       if (it->second) {
-        context->ProcessMouseButtonDown(it->first, _modifiers);
+        context->ProcessMouseButtonDown(it->first - 1, _modifiers);
       } else {
-        context->ProcessMouseButtonUp(it->first, _modifiers);
+        context->ProcessMouseButtonUp(it->first - 1, _modifiers);
       }
     }
     _mouse_buttons.clear();
@@ -226,7 +320,17 @@
         context->ProcessKeyUp((KeyIdentifier) it->first, _modifiers);
       }
     }
-    _mouse_buttons.clear();
+    _keys.clear();
+  }
+
+  if (_repeated_keys.size() > 0) {
+    ButtonActivityMap::const_iterator it;
+
+  for (it = _repeated_keys.begin(); it != _repeated_keys.end(); ++it) {
+    context->ProcessKeyUp((KeyIdentifier) it->first, _modifiers);
+    context->ProcessKeyDown((KeyIdentifier) it->first, _modifiers);
+  }
+    _repeated_keys.clear();
   }
 
   if (_text_input.size() > 0) {
Index: panda/src/rocket/rocketInputHandler.h
===================================================================
RCS file: /cvsroot/panda3d/panda/src/rocket/rocketInputHandler.h,v
retrieving revision 1.1
diff -u -r1.1 rocketInputHandler.h
--- panda/src/rocket/rocketInputHandler.h       7 Jan 2012 19:02:41 -0000       1.1
+++ panda/src/rocket/rocketInputHandler.h       25 Jan 2012 16:51:25 -0000
@@ -57,6 +57,7 @@
   typedef pmap<int, bool> ButtonActivityMap;
   ButtonActivityMap _mouse_buttons;
   ButtonActivityMap _keys;
+  ButtonActivityMap _repeated_keys;
   pvector<short> _text_input;
 
 public:

(Is there a better way to submit patches? I suspect this won’t be the last one I submit…)

Edit: Backtrace - pastebin.com/HdNtrwDr
Full Backtrace: pastebin.com/xDLR8nwB

Latest debug output from libRocket:

Starting program: /usr/bin/python test.py
[Thread debugging using libthread_db enabled]
Known pipe types:
  glxGraphicsPipe
(all display modules loaded.)
:audio(error):   load_dso(libp3openal_audio.so) failed, will use NullAudioManager
:audio(error):     No error.
rocket 0x2682828

Program received signal SIGSEGV, Segmentation fault.
0x00007fffea02ef27 in Rocket::Core::Context::GetElementAtPoint(Rocket::Core::Vector2<float> const&, Rocket::Core::Element const*, Rocket::Core::Element*) ()
   from /usr/local/lib/libRocketCore.so.1

OK, I just made a big commit. Burstaholic’s crash should be fixed now, it was happening because his Python context object was getting destroyed before his C++ context was, and because it used a borrowed reference, this led to the C++ context being destroyed prematurely.

I’ve included morgul’s changes (thanks!), I’ve adapted them a little bit because I switched to using a lookup table for key translations, for better performance.

Everything seems to be working in the Invaders sample for me, except that I’m still working on a font issue:
rdb.name/librocket_font_problem.png

Ah, never mind, I’ve got fonts working now:

Looks good! (I haven’t had a chance to try it, I will later tonight.)

Out of curiosity, rdb, did you have to do anything special to get librocket building on OSX? I’m running Lion on one of my machines, and the python bindings won’t compile. (Searching around, it looks like it’s a problem with boost python, and include order, but I haven’t had much time to mess with that.)

I had no issues on Snow Leopard. Tomorrow I’ll make sure the OSX buildbot contains libRocket support.

Make sure that you compile it for i386 arch with Python 2.5 if you use the default SDK.