May 06, 2011
Testing out a new binding I knocked up for a C library. One of the functions takes a struct by value. It looks somewhat like this:

struct S {}
struct Color
{
    float r,g,b,a;
}

extern C void function(S* s, Color color, int x, int y, in char*) draw_text;

Now, there is another function that adjusts color values when making a color. In C, it is sometimes used like so:

draw_text(s, map_color(255, 0, 0, 0), 0, 0, "Blarg");

When I'm calling draw_text like this on the D side, my text output is corrupt. I keep getting weird things like ^^P^, but in the appropriate color. It's consistent, no matter what string I pass, but is different for each color value. If I call draw_text like this:

auto color = map_color(...);
draw_text(s, color, 0, 0, "Blarg");

It works as expected. Has anyone else seen this, or know of a workaround? I'm going to dig through bugzilla later on and see if it's been reported already, but I'm curious if anyone knows of the cause off hand.

May 06, 2011
On Fri, 06 May 2011 05:56:17 -0400, Mike Parker <aldacron@gmail.com> wrote:

> Testing out a new binding I knocked up for a C library. One of the functions takes a struct by value. It looks somewhat like this:
>
> struct S {}
> struct Color
> {
>      float r,g,b,a;
> }
>
> extern C void function(S* s, Color color, int x, int y, in char*) draw_text;
>
> Now, there is another function that adjusts color values when making a color. In C, it is sometimes used like so:
>
> draw_text(s, map_color(255, 0, 0, 0), 0, 0, "Blarg");
>
> When I'm calling draw_text like this on the D side, my text output is corrupt. I keep getting weird things like ^^P^, but in the appropriate color. It's consistent, no matter what string I pass, but is different for each color value. If I call draw_text like this:
>
> auto color = map_color(...);
> draw_text(s, color, 0, 0, "Blarg");
>
> It works as expected. Has anyone else seen this, or know of a workaround? I'm going to dig through bugzilla later on and see if it's been reported already, but I'm curious if anyone knows of the cause off hand.
>

There are two possible causes I can think of, depending on how draw_text is defined in C.

1. is it truly a function pointer?  That is, does the definition look like void (*draw_text)(S* s, ...), or is it just void draw_text(S* s, ...)?

2. It's possible that the extern C (BTW, I thought it had to be extern(C)?) is only applying to the symbol name draw_text and not the function type.

If you answer no to #1, then your problem is your draw_text definition in D.  It should look like this:

extern(C) void draw_text(S * s, Color color, int x, int y, in char *);

If you answer yes to #1, then to check what type the compiler is giving to draw text, do:

pragma(msg, (typeof(draw_text)).stringof);

This hopefully tells you that it's extern(C), but if not, that is likely the problem.

If that's not it, I have no idea ;)

-Steve
May 06, 2011
On 2011-05-06 11:56, Mike Parker wrote:
> Testing out a new binding I knocked up for a C library. One of the
> functions takes a struct by value. It looks somewhat like this:
>
> struct S {}
> struct Color
> {
> float r,g,b,a;
> }
>
> extern C void function(S* s, Color color, int x, int y, in char*)
> draw_text;
>
> Now, there is another function that adjusts color values when making a
> color. In C, it is sometimes used like so:
>
> draw_text(s, map_color(255, 0, 0, 0), 0, 0, "Blarg");
>
> When I'm calling draw_text like this on the D side, my text output is
> corrupt. I keep getting weird things like ^^P^, but in the appropriate
> color. It's consistent, no matter what string I pass, but is different
> for each color value. If I call draw_text like this:
>
> auto color = map_color(...);
> draw_text(s, color, 0, 0, "Blarg");
>
> It works as expected. Has anyone else seen this, or know of a
> workaround? I'm going to dig through bugzilla later on and see if it's
> been reported already, but I'm curious if anyone knows of the cause off
> hand.

You need to convert the string into a C string;

import std.string;
auto color = map_color(...);
draw_text(s, color, 0, 0, "Blarg".toStringz);

-- 
/Jacob Carlborg
May 06, 2011
On Fri, 06 May 2011 09:16:02 -0400, Jacob Carlborg <doob@me.com> wrote:

> On 2011-05-06 11:56, Mike Parker wrote:
>> Testing out a new binding I knocked up for a C library. One of the
>> functions takes a struct by value. It looks somewhat like this:
>>
>> struct S {}
>> struct Color
>> {
>> float r,g,b,a;
>> }
>>
>> extern C void function(S* s, Color color, int x, int y, in char*)
>> draw_text;
>>
>> Now, there is another function that adjusts color values when making a
>> color. In C, it is sometimes used like so:
>>
>> draw_text(s, map_color(255, 0, 0, 0), 0, 0, "Blarg");
>>
>> When I'm calling draw_text like this on the D side, my text output is
>> corrupt. I keep getting weird things like ^^P^, but in the appropriate
>> color. It's consistent, no matter what string I pass, but is different
>> for each color value. If I call draw_text like this:
>>
>> auto color = map_color(...);
>> draw_text(s, color, 0, 0, "Blarg");
>>
>> It works as expected. Has anyone else seen this, or know of a
>> workaround? I'm going to dig through bugzilla later on and see if it's
>> been reported already, but I'm curious if anyone knows of the cause off
>> hand.
>
> You need to convert the string into a C string;
>
> import std.string;
> auto color = map_color(...);
> draw_text(s, color, 0, 0, "Blarg".toStringz);
>

No, D implicitly casts string literals to zero-terminated const(char)*.  That part is fine.

-Steve
May 06, 2011
On 5/6/2011 9:19 PM, Steven Schveighoffer wrote:
> On Fri, 06 May 2011 05:56:17 -0400, Mike Parker <aldacron@gmail.com> wrote:
>
>> Testing out a new binding I knocked up for a C library. One of the
>> functions takes a struct by value. It looks somewhat like this:
>>
>> struct S {}
>> struct Color
>> {
>> float r,g,b,a;
>> }
>>
>> extern C void function(S* s, Color color, int x, int y, in char*)
>> draw_text;
>>
>> Now, there is another function that adjusts color values when making a
>> color. In C, it is sometimes used like so:
>>
>> draw_text(s, map_color(255, 0, 0, 0), 0, 0, "Blarg");
>>
>> When I'm calling draw_text like this on the D side, my text output is
>> corrupt. I keep getting weird things like ^^P^, but in the appropriate
>> color. It's consistent, no matter what string I pass, but is different
>> for each color value. If I call draw_text like this:
>>
>> auto color = map_color(...);
>> draw_text(s, color, 0, 0, "Blarg");
>>
>> It works as expected. Has anyone else seen this, or know of a
>> workaround? I'm going to dig through bugzilla later on and see if it's
>> been reported already, but I'm curious if anyone knows of the cause
>> off hand.
>>
>
> There are two possible causes I can think of, depending on how draw_text
> is defined in C.
>
> 1. is it truly a function pointer? That is, does the definition look
> like void (*draw_text)(S* s, ...), or is it just void draw_text(S* s, ...)?

It's a pointer to a function symbol in a DLL. In Derelict, all functions are pointers on the D side, since the shared libraries are loaded manually. I've bound several C libs in the same way and never encountered this before.

>
> 2. It's possible that the extern C (BTW, I thought it had to be
> extern(C)?) is only applying to the symbol name draw_text and not the
> function type.

Yeah, that's a typo in my post. It's definitely declared as extern(C) in the source. And I checked with the pragma given below to make sure.

>
> If you answer no to #1, then your problem is your draw_text definition
> in D. It should look like this:
>
> extern(C) void draw_text(S * s, Color color, int x, int y, in char *);
>
> If you answer yes to #1, then to check what type the compiler is giving
> to draw text, do:
>
> pragma(msg, (typeof(draw_text)).stringof);
>
> This hopefully tells you that it's extern(C), but if not, that is likely
> the problem.
>
> If that's not it, I have no idea ;)
>

Thanks for the guesses. I don't believe any of the libraries I've bound before now have any functions that take a struct by value. If they have, I haven't had occasion to use them yet. So I wonder if this is an issue with how the compiler handles returning a value struct from a function. Could there be a difference in how it's pushed on to the stack in a D function call versus how it's expected in C? Just grasping.

May 06, 2011
On 5/6/2011 10:23 PM, Steven Schveighoffer wrote:
> On Fri, 06 May 2011 09:16:02 -0400, Jacob Carlborg <doob@me.com> wrote:
>
>> On 2011-05-06 11:56, Mike Parker wrote:
>>> Testing out a new binding I knocked up for a C library. One of the
>>> functions takes a struct by value. It looks somewhat like this:
>>>
>>> struct S {}
>>> struct Color
>>> {
>>> float r,g,b,a;
>>> }
>>>
>>> extern C void function(S* s, Color color, int x, int y, in char*)
>>> draw_text;
>>>
>>> Now, there is another function that adjusts color values when making a
>>> color. In C, it is sometimes used like so:
>>>
>>> draw_text(s, map_color(255, 0, 0, 0), 0, 0, "Blarg");
>>>
>>> When I'm calling draw_text like this on the D side, my text output is
>>> corrupt. I keep getting weird things like ^^P^, but in the appropriate
>>> color. It's consistent, no matter what string I pass, but is different
>>> for each color value. If I call draw_text like this:
>>>
>>> auto color = map_color(...);
>>> draw_text(s, color, 0, 0, "Blarg");
>>>
>>> It works as expected. Has anyone else seen this, or know of a
>>> workaround? I'm going to dig through bugzilla later on and see if it's
>>> been reported already, but I'm curious if anyone knows of the cause off
>>> hand.
>>
>> You need to convert the string into a C string;
>>
>> import std.string;
>> auto color = map_color(...);
>> draw_text(s, color, 0, 0, "Blarg".toStringz);
>>
>
> No, D implicitly casts string literals to zero-terminated const(char)*.
> That part is fine.
>

toStringz was actually the first thing I went for when I got the corrupted output, thinking that maybe literals were no longer null terminated.

I can't for the life of me figure out what's different about passing a local struct variable and one that's returned by value from a function call. The only thing I can think of is that the temp returned from the function is somehow corrupting the stack when it's pushed for the function call. But why? I'm hoping someone can shed some light on that aspect.
May 06, 2011
Mike Parker:

> Testing out a new binding I knocked up for a C library. One of the functions takes a struct by value. It looks somewhat like this:
> 
> struct S {}
> struct Color
> {
>      float r,g,b,a;
> }
> 
> extern C void function(S* s, Color color, int x, int y, in char*) draw_text;

My suggestion is:
1) create a test case that shows your program with minimal D code and minimal C code.
2) Create the binary
3) Disassembly it, take a look at the ASM and find the relevant parts, or show them here...

Bye,
bearophile
May 06, 2011
On 2011-05-06 15:23, Steven Schveighoffer wrote:
> On Fri, 06 May 2011 09:16:02 -0400, Jacob Carlborg <doob@me.com> wrote:
>
>> On 2011-05-06 11:56, Mike Parker wrote:
>>> Testing out a new binding I knocked up for a C library. One of the
>>> functions takes a struct by value. It looks somewhat like this:
>>>
>>> struct S {}
>>> struct Color
>>> {
>>> float r,g,b,a;
>>> }
>>>
>>> extern C void function(S* s, Color color, int x, int y, in char*)
>>> draw_text;
>>>
>>> Now, there is another function that adjusts color values when making a
>>> color. In C, it is sometimes used like so:
>>>
>>> draw_text(s, map_color(255, 0, 0, 0), 0, 0, "Blarg");
>>>
>>> When I'm calling draw_text like this on the D side, my text output is
>>> corrupt. I keep getting weird things like ^^P^, but in the appropriate
>>> color. It's consistent, no matter what string I pass, but is different
>>> for each color value. If I call draw_text like this:
>>>
>>> auto color = map_color(...);
>>> draw_text(s, color, 0, 0, "Blarg");
>>>
>>> It works as expected. Has anyone else seen this, or know of a
>>> workaround? I'm going to dig through bugzilla later on and see if it's
>>> been reported already, but I'm curious if anyone knows of the cause off
>>> hand.
>>
>> You need to convert the string into a C string;
>>
>> import std.string;
>> auto color = map_color(...);
>> draw_text(s, color, 0, 0, "Blarg".toStringz);
>>
>
> No, D implicitly casts string literals to zero-terminated const(char)*.
> That part is fine.
>
> -Steve

Since when?

-- 
/Jacob Carlborg
May 06, 2011
On 2011-05-06 11:56, Mike Parker wrote:
> Testing out a new binding I knocked up for a C library. One of the
> functions takes a struct by value. It looks somewhat like this:
>
> struct S {}
> struct Color
> {
> float r,g,b,a;
> }
>
> extern C void function(S* s, Color color, int x, int y, in char*)
> draw_text;
>
> Now, there is another function that adjusts color values when making a
> color. In C, it is sometimes used like so:
>
> draw_text(s, map_color(255, 0, 0, 0), 0, 0, "Blarg");
>
> When I'm calling draw_text like this on the D side, my text output is
> corrupt. I keep getting weird things like ^^P^, but in the appropriate
> color. It's consistent, no matter what string I pass, but is different
> for each color value. If I call draw_text like this:
>
> auto color = map_color(...);
> draw_text(s, color, 0, 0, "Blarg");
>
> It works as expected. Has anyone else seen this, or know of a
> workaround? I'm going to dig through bugzilla later on and see if it's
> been reported already, but I'm curious if anyone knows of the cause off
> hand.
>

Don't know if it has anything to do with the problem but you have to watch out with the floats, they are initialized to NaN.

-- 
/Jacob Carlborg
May 06, 2011
On 06/05/2011 19:40, Jacob Carlborg wrote:
>> No, D implicitly casts string literals to zero-terminated const(char)*.
>> That part is fine.
>>
>> -Steve
>
> Since when?

Since const was introduced, before then they implicitly casted to char* instead. And that has been the case since early D1.

-- 
Robert
http://octarineparrot.com/
« First   ‹ Prev
1 2
Top | Discussion index | About this forum | D home