Hi! I've been helping with some code to interface to a C library,
and I think I've discovered a bit of a hangup in the 64-bit linux
version of DMD.

If a struct is eight bytes or less (the size of two uints), it
can be passed just fine between D and C code, but if it's any
larger than that, the data gets messed up somewhere along the
way. This doesn't happen when the code is compiled in 32-bit mode
(with -m32)

Here's some example code to trigger the bug:

structyc.c:
-----

#include <stdio.h>

struct passingstruct {
        unsigned int a;
        unsigned int b;
        int c;
};

void printatest (struct passingstruct value)
{
        printf ("hello!\n");
        printf ("%u %u %d\n", value.a, value.b, value.c);
}
-----

structyd.d:
------
import std.stdio;

struct passingstruct {
        uint a;
        uint b;
        int c;
        
        void printme () {
                writefln ("%d %d", a, b);
        }
}

int main (char[][] args)
{
        auto thingy = passingstruct( 300, 200, 0);
        writefln ("%u %u %d", test.a, test.b, test.c);
        
        printatest (test);
        return 0;
}

extern (C)
{
        void printatest (passingstruct value);
}
-------

When compiled and linked in 64-bit mode, it produces this output:

300 200 0
hello!
394682976 32695 402542592

However, 32-bit mode produces the expected output:

300 200 0
hello!
300 200 0

Additionally, if the third element (.c) is taken out of the
"testman" struct, or if b and c are made ushort or ubyte, the
program works fine in 64-bit mode. GDC(an admittedly out-of-date
version--ubuntu only packages 4.6.3) also successfully passes the
whole struct in 64bit mode.

Reply via email to