tomassedovic / tcod-rs

Rust bindings for libtcod 1.6.3 (the Doryen library/roguelike toolkit)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Crashes with precompiled libtcod-migw on Windows

tomassedovic opened this issue · comments

This is on a 32bit version of Windows 7 with MinGW and MSYS (dependencies for building libtcod) installed.

When using tcod-rs with the libtcod compiled as part of tcod-sys, none of the examples crash. But when I download the precompiled libtcod-1.5.2-mingw32.tar.gz library from:

http://roguecentral.org/doryen/libtcod/download/

and run e.g. the minimal example, I get a panic unwrapping the Option here:

Key::Special(FromPrimitive::from_u32(tcod_key.vk).unwrap())

The tcod_key.vk values appear to be 256 or greater (hence the failure although this shouldn't ever happen) and when I try to inspect it, I end up with weird crashes (segfaults?) which seem to depend on things such as having a println!(tcod_key.vk) line in there or not.

I'll try to investigate this further but it seems like some sort of memory layout issue or something like that.

My friend @jaywuuu is blocked by this very issue :( is there a workaround? 64-bit? Oh so building tcod-sys manually works.

I'm a bit stumped by this, but I'll try to look into it again in a few days
when I get home.

The only workaround I have right now is to compile libtcod directly. I.e.
run cargo build without using the downloaded library. The build script in
tcod-sys should build libtcod and that didn't crash for me.

See the "building on windows" section in readme.

By the way @jaywuuu, any chance you could give me more details about your
system and output of rustc --version verbose?
On Dec 28, 2014 1:32 AM, "Paul Collier" notifications@github.com wrote:

My friend @jaywuuu https://github.com/jaywuuu is blocked by this very
issue :( is there a workaround? 64-bit?


Reply to this email directly or view it on GitHub
#54 (comment).

Oh sorry, didn't notice you figured out the "build tcod-sys" already.
On Dec 28, 2014 11:54 AM, "Tomáš Šedovič" tomas@sedovic.cz wrote:

I'm a bit stumped by this, but I'll try to look into it again in a few
days when I get home.

The only workaround I have right now is to compile libtcod directly. I.e.
run cargo build without using the downloaded library. The build script in
tcod-sys should build libtcod and that didn't crash for me.

See the "building on windows" section in readme.

By the way @jaywuuu, any chance you could give me more details about your
system and output of rustc --version verbose?
On Dec 28, 2014 1:32 AM, "Paul Collier" notifications@github.com wrote:

My friend @jaywuuu https://github.com/jaywuuu is blocked by this very
issue :( is there a workaround? 64-bit?


Reply to this email directly or view it on GitHub
#54 (comment)
.

I looked into this some more and I can't really figure out what's going on and why.

Here's the smallest repro:

https://gist.github.com/tomassedovic/950eac1ac439d8b37946

If you look at the notes in the Rust example, adding/removing a superfluous println! line changes the code behaviour from broken to working.

I tried to do the same thing with C and poke around the memory (in the same gist). It appears that the memory is a bit jumbled. The first thing that gets filled in the TCOD_key_t struct is not the vk member but rather, the c value. If I look at four bytes before that, vk is there.

I have no idea why would this happen. I tried to play with struct packing, trying different sizes of C's types, but I didn't find anything useful. Plus why should it ever write before the returned value?

I checked libtcod's issues and forum and I didn't find anything useful there either other than a mention that apparently different MinGW versions are incompatible. I can imagine that producing this sort of behaviour, but that's hardly a confirmation.

If there's someone who's willing to pick it up, I'll be super grateful. Other than that, building libtcod / tcod-sys yourself seems to work fine.

I'm running a Win7 Pro 64bit OS. I'm building using win_build's 32-bit tool chain using mingw and msys with 1.5.1 stable build of libtcod. I tried in C too building with 1.5.1 and it worked okay. Let me know if you want to know anything else or specific.

In any case, I'll try building libtcod myself using the nightlies.

My rustc --version verbose:
rustc 0.13.0-nightly (42deaa5e4 2014-12-16 17:51:23 +0000)
binary: rustc
commit-hash: 42deaa5e42c0b8a9e305aa5de5d6953b24b77aca
commit-date: 2014-12-16 17:51:23 +0000
host: i686-pc-windows-gnu
release: 0.13.0-nightly

Thanks for the info, @jaywuuu!

Would you also share the output of gcc --version, please? Mine is gcc <GCC> 4.8.1. If the issue really is that the libtcod libraries were compiled by an incompatible MinGW version, this could shed some light on that.

The other thing is, you said linking the same libtcod library to a C code was fine. Can you paste the C code you tried? And just to make sure: did you check that the keyboard input really work or just check that it didn't crash?

When I tried running C code, it didn't segfault, but it wasn't working properly either -- the values returned by TCOD_console_wait_for_keypress were wrong.

Could you try running this code and pressing the a and Enter keys?

#include "stdio.h"

typedef char bool;

typedef enum {
    TCOD_RENDERER_GLSL,
    TCOD_RENDERER_OPENGL,
    TCOD_RENDERER_SDL,
    TCOD_NB_RENDERERS,
} TCOD_renderer_t;

typedef struct {
    int vk;
    char c;
    bool pressed;
    bool lalt;
    bool lctrl;
    bool ralt;
    bool rctrl;
    bool shift;
} TCOD_key_t;


void TCOD_console_init_root(int w, int h, const char * title, bool fullscreen, TCOD_renderer_t renderer);
bool TCOD_console_is_window_closed();
void TCOD_console_flush();
TCOD_key_t TCOD_console_wait_for_keypress(bool flush);


int main() {
    TCOD_console_init_root(80, 50, "tcod window", 0, 2);
    while (TCOD_console_is_window_closed() == 0) {
        TCOD_console_flush();
        TCOD_key_t key = TCOD_console_wait_for_keypress(1);
        printf("vk: %d, c: %d, pressed: %d, lalt: %d, lctrl: %d, ralt: %d, rctrl: %d, shift: %d\n",
               key.vk, (int)key.c, (int)key.pressed,
               (int)key.lalt, (int)key.lctrl,
               (int)key.ralt, (int)key.rctrl, (int)key.shift);
        char* c = (char*)&key;
        int i;
        printf("TCOD_key_t:\n");
        for(i = 0; i < 12; i++) {
            printf("%d, ", c[i]);
        }
        printf("\n");
        printf("TCOD_key_t - 4 bytes:\n");
        for(i = -4; i < 8; i++) {
            printf("%d, ", c[i]);
        }
        printf("\n---\n");
    }
    return(0);
}

(compiling it with gcc key.c -ltcod -L . -o key_c && key_c should do the trick if you have libtcod.dll and friends in the same directory)

It should output vk: 65, c: 97, pressed: 1, lalt: 0, lctrl: 0, ralt: 0, rctrl: 0, shift: 0 for the a key and vk: 4, c: 13, pressed: 1, lalt: 0, lctrl: 0, ralt: 0, rctrl: 0, shift: 0 for Enter. On my (Win7 32bit + mingw + msys) setup this produces bogus output (something like: vk: 353, c: 0, pressed: 0, lalt: 0, lctrl: 0, ralt: -108, rctrl: -1, shift: 34)

Another interesting tidbit: I've just checked downloaded Brogue (which uses libtcod):

https://sites.google.com/site/broguegame/Brogue-windows-v1.7.4.zip?attredirects=0&d=1

and the dlls provided in that executable work just fine. So that would be another workaround for anyone who doesn't want to compile libtcod themselves. Which makes me lean even more towards the "mingw version incompatibility" issue.

It's most definitely a change in the ABI, see : http://roguecentral.org/doryen/2013/03/the-wonderful-world-of-c/ for more information. (I know it's an old issue, but there's nothing you can do except provide newer pre-compiled binaries or use an older compiler, so I think it's just better to close it and warn the users instead.)

Thanks @L3nn0x. Yeah, I'll close this.