Thread overview
extremely subtle D --> C linking bug ... (dmd .139 linux)
Nov 15, 2005
clayasaurus
Nov 15, 2005
clayasaurus
Nov 15, 2005
Regan Heath
Nov 15, 2005
clayasaurus
Nov 16, 2005
Mike Parker
Nov 18, 2005
Thomas Kuehne
November 15, 2005
This bug was /almost/ a show stopper for me, just because it took so long to find it.

I attached two files, bug.d, and c_func.cpp.

Compile with..

g++ -c c_func.cpp
dmd bug.d c_func.o -L-lstdc++

The D version links to this function through

extern(C)
{
    void c_func(ushort a, ulong b, int c, ushort d);
}

and the actual function itself is

extern "C" {

    void c_func(unsigned short a, unsigned long b, int c, unsigned short d)
    {
       printf("%d %d %d %d\n", a, b, c, d);
    }

}

I call the function with the following arguments...

c_func(60000, 0, 0, 60000);

And it prints the following...

60000 0 0 0

It can be 'fixed' when you make all the arguments in the function the same type. I really have no clue why this is happening though.









November 15, 2005
clayasaurus wrote:
> This bug was /almost/ a show stopper for me, just because it took so long to find it.
> 
> I attached two files, bug.d, and c_func.cpp.
> 
> Compile with..
> 
> g++ -c c_func.cpp
> dmd bug.d c_func.o -L-lstdc++
> 
> The D version links to this function through
> 
> extern(C)
> {
>    void c_func(ushort a, ulong b, int c, ushort d);
> }
> 
> and the actual function itself is
> 
> extern "C" {
> 
>    void c_func(unsigned short a, unsigned long b, int c, unsigned short d)
>    {
>       printf("%d %d %d %d\n", a, b, c, d);
>    }
> 
> }
> 
> I call the function with the following arguments...
> 
> c_func(60000, 0, 0, 60000);
> 
> And it prints the following...
> 
> 60000 0 0 0
> 
> It can be 'fixed' when you make all the arguments in the function the same type. I really have no clue why this is happening though.
> 
> 
> 
> 
> 
> 
> 
> 
> ------------------------------------------------------------------------
> 
> 
> extern(C)
> {
>    void c_func(ushort a, ulong b, int c, ushort d);
> }
> 
> int main()
> {
>    c_func(60000, 0, 0, 60000); 
> 
>    return 0;
> }
> 
> 
> ------------------------------------------------------------------------
> 
> 
> #include <stdio.h> 
> 
> extern "C" {
> 
>    void c_func(unsigned short a, unsigned long b, int c, unsigned short d)
>    {
>       printf("%d %d %d %d\n", a, b, c, d);
>    }
> 
> }

Just found out it doesn't work if they are all ulong, but it does it they are all uint.
November 15, 2005
On Tue, 15 Nov 2005 11:04:18 -0500, clayasaurus <clayasaurus@gmail.com> wrote:
> clayasaurus wrote:
>> This bug was /almost/ a show stopper for me, just because it took so long to find it.
>>  I attached two files, bug.d, and c_func.cpp.
>>  Compile with..
>>  g++ -c c_func.cpp
>> dmd bug.d c_func.o -L-lstdc++
>>  The D version links to this function through
>>  extern(C)
>> {
>>    void c_func(ushort a, ulong b, int c, ushort d);
>> }
>>  and the actual function itself is
>>  extern "C" {
>>     void c_func(unsigned short a, unsigned long b, int c, unsigned short d)
>>    {
>>       printf("%d %d %d %d\n", a, b, c, d);
>>    }
>>  }
>>  I call the function with the following arguments...
>>  c_func(60000, 0, 0, 60000);
>>  And it prints the following...
>>  60000 0 0 0
>>  It can be 'fixed' when you make all the arguments in the function the same type. I really have no clue why this is happening though.
>>         ------------------------------------------------------------------------
>>   extern(C)
>> {
>>    void c_func(ushort a, ulong b, int c, ushort d);
>> }
>>  int main()
>> {
>>    c_func(60000, 0, 0, 60000);     return 0;
>> }
>>   ------------------------------------------------------------------------
>>   #include <stdio.h>  extern "C" {
>>     void c_func(unsigned short a, unsigned long b, int c, unsigned short d)
>>    {
>>       printf("%d %d %d %d\n", a, b, c, d);
>>    }
>>  }
>
> Just found out it doesn't work if they are all ulong, but it does it they are all uint.

A ulong in D is twice as long as an unsigned long in C (generally).

For help converting C to D, see:
  http://www.digitalmars.com/d/type.html
  http://www.digitalmars.com/d/ctod.html#types

In other words, if C says "unsigned long" in D you use "uint". eg.

[original.c]
void c_func(unsigned short a, unsigned long b, int c, unsigned short d) {}

[your.d]
extern(C)
{
  void c_func(ushort a, uint b, int c, ushort d);
}

If however C used "long long" then you'd use D's "long" type.

Regan

November 15, 2005
Regan Heath wrote:
> On Tue, 15 Nov 2005 11:04:18 -0500, clayasaurus <clayasaurus@gmail.com>  wrote:
> 
>> clayasaurus wrote:
>>
>>> This bug was /almost/ a show stopper for me, just because it took so  long to find it.
>>>  I attached two files, bug.d, and c_func.cpp.
>>>  Compile with..
>>>  g++ -c c_func.cpp
>>> dmd bug.d c_func.o -L-lstdc++
>>>  The D version links to this function through
>>>  extern(C)
>>> {
>>>    void c_func(ushort a, ulong b, int c, ushort d);
>>> }
>>>  and the actual function itself is
>>>  extern "C" {
>>>     void c_func(unsigned short a, unsigned long b, int c, unsigned  short d)
>>>    {
>>>       printf("%d %d %d %d\n", a, b, c, d);
>>>    }
>>>  }
>>>  I call the function with the following arguments...
>>>  c_func(60000, 0, 0, 60000);
>>>  And it prints the following...
>>>  60000 0 0 0
>>>  It can be 'fixed' when you make all the arguments in the function the  same type. I really have no clue why this is happening though.
>>>          ------------------------------------------------------------------------
>>>   extern(C)
>>> {
>>>    void c_func(ushort a, ulong b, int c, ushort d);
>>> }
>>>  int main()
>>> {
>>>    c_func(60000, 0, 0, 60000);     return 0;
>>> }
>>>    ------------------------------------------------------------------------
>>>   #include <stdio.h>  extern "C" {
>>>     void c_func(unsigned short a, unsigned long b, int c, unsigned  short d)
>>>    {
>>>       printf("%d %d %d %d\n", a, b, c, d);
>>>    }
>>>  }
>>
>>
>> Just found out it doesn't work if they are all ulong, but it does it  they are all uint.
> 
> 
> A ulong in D is twice as long as an unsigned long in C (generally).
> 
> For help converting C to D, see:
>   http://www.digitalmars.com/d/type.html
>   http://www.digitalmars.com/d/ctod.html#types

Thanks, I didn't realize that a unsigned long in C is the same as a uint in D.

> 
> In other words, if C says "unsigned long" in D you use "uint". eg.
> 
> [original.c]
> void c_func(unsigned short a, unsigned long b, int c, unsigned short d) {}
> 
> [your.d]
> extern(C)
> {
>   void c_func(ushort a, uint b, int c, ushort d);
> }
> 
> If however C used "long long" then you'd use D's "long" type.
> 
> Regan
> 
November 16, 2005
clayasaurus wrote:
 >
> Thanks, I didn't realize that a unsigned long in C is the same as a uint in D.
> 
>

Be careful with this, though. That's on 32-bit systems, where ints and longs are almost always the same size from compiler to compiler. On 64-bit systems, I have heard that some compilers treat longs as 64-bit and some do not. The C (and/or C++) spec does not specify anything other than 'a long is at least as big as an int'. When interfacing with C code, always be aware of the properties of the compiler you are using and the platform you are using it on.
November 18, 2005
Mike Parker schrieb am 2005-11-16:
> clayasaurus wrote:
>  >
>> Thanks, I didn't realize that a unsigned long in C is the same as a uint in D.
>> 
>>
>
> Be careful with this, though. That's on 32-bit systems, where ints and longs are almost always the same size from compiler to compiler. On 64-bit systems, I have heard that some compilers treat longs as 64-bit and some do not. The C (and/or C++) spec does not specify anything other than 'a long is at least as big as an int'. When interfacing with C code, always be aware of the properties of the compiler you are using and the platform you are using it on.

for 64-bit systems:

Microsoft - sizeof(int) == sizeof(long)

most Posix systems - sizeof(int) * 2 == sizeof(long)

And then there are options like GCC's -mlong32 and -mlong64

Thomas