Jump to page: 1 2
Thread overview
Qs about structs and their references WRT C functions and variables
Jan 31, 2007
Rick Mann
Jan 31, 2007
Rick Mann
Jan 31, 2007
Frits van Bommel
Jan 31, 2007
Rick Mann
Jan 31, 2007
Mike Parker
Jan 31, 2007
Hasan Aljudy
Jan 31, 2007
Rick Mann
Jan 31, 2007
torhu
Jan 31, 2007
Rick Mann
Jan 31, 2007
torhu
January 31, 2007
I'm working on some C bindings, and I need to know a few things that aren't clear from the spec.

a) If a C function takes a pointer to a struct so that it can fill that struct (return it), I've found I can write the parameter as "out MyStruct outS", and things work as expected (I don't take the address of the parameter I pass).

If a function simply takes a struct as input, and therefore I leave off any qualifier in the D parameter declaration (i.e., "MyStruct inS"), is the struct still passed by reference? I assume so, but want to be sure.

b) Some of the API's in C pass the entire struct (I question the wisdom of this). How do I link to these?

c) I need to declare a couple of extern structs. Can I just slap an "extern (C)" on these and all will be well? The spec seems to indicate that this is so, and it may be fine; I'm just looking for verification. e.g.:

struct
ControlID
{
	uint		signature;
	int		id;
};
typedef ControlID                       HIViewID;
extern (C)
const HIViewID kHIViewWindowContentID;

TIA,
Rick


January 31, 2007
"Rick Mann" <rmann-d-lang@latencyzero.com> wrote in message news:epoqju$26f0$1@digitaldaemon.com...
> I'm working on some C bindings, and I need to know a few things that aren't clear from the spec.
>
> a) If a C function takes a pointer to a struct so that it can fill that struct (return it), I've found I can write the parameter as "out MyStruct outS", and things work as expected (I don't take the address of the parameter I pass).

Right.  'out' implicitly passes the struct by reference, so if the struct parameter is a return value, then 'out' is the right way to go.  That it works with C libraries is something that I didn't know, and something very cool..

> If a function simply takes a struct as input, and therefore I leave off any qualifier in the D parameter declaration (i.e., "MyStruct inS"), is the struct still passed by reference? I assume so, but want to be sure.

No.  It's passed by value, just like if you were to write

void func(struct SomeStruct s);

in C.

> b) Some of the API's in C pass the entire struct (I question the wisdom of this). How do I link to these?

If the struct is fairly small, passing the struct by value probably isn't that much of a performance loss (and might even be a gain, if it accesses the structs members often inside the function).  But if it were declared as

void func(struct SomeStruct s);

in C, then you declare it as

extern(C) void func(SomeStruct s);

in D.

> c) I need to declare a couple of extern structs. Can I just slap an "extern (C)" on these and all will be well? The spec seems to indicate that this is so, and it may be fine; I'm just looking for verification. e.g.:
>
> struct
> ControlID
> {
> uint signature;
> int id;
> };
> typedef ControlID                       HIViewID;
> extern (C)
> const HIViewID kHIViewWindowContentID;
>
> TIA,
> Rick

Hmm.. if I remember correctly, those extern struct declarations have to be in a .d file which is _imported_ but never _compiled_.  So you'd have something like

importedstructs.d

struct ControlID
{
    uint signature;
    int id;
}

typedef ControlID HIViewID;
extern(C) const HIViewID kHIViewWindowContentID;

And then the rest of your program would have:

import importedstructs;

But you wouldn't put importedstructs.d on the command line when you compile your program.


January 31, 2007
Jarrett Billingsley Wrote:

> Right.  'out' implicitly passes the struct by reference, so if the struct parameter is a return value, then 'out' is the right way to go.  That it works with C libraries is something that I didn't know, and something very cool..

It makes for tidy calls where the parameter is used for output. However, I can't seem to do the same for an input parameter. I'd like to do the equivalent of the following C code:

void func(const SomeStruct& inS);

This is identical to

void func(const SomeStruct* inS);

but allows me to call it without adding the & in front of the parameter. It's a bit inconsistent that I can do this with an "out" parameter, but not an "in" parameter.


> Hmm.. if I remember correctly, those extern struct declarations have to be in a .d file which is _imported_ but never _compiled_.  So you'd have something like
> 
> importedstructs.d
> 
> struct ControlID
> {
>     uint signature;
>     int id;
> }
> 
> typedef ControlID HIViewID;
> extern(C) const HIViewID kHIViewWindowContentID;
> 
> And then the rest of your program would have:
> 
> import importedstructs;
> 
> But you wouldn't put importedstructs.d on the command line when you compile your program.

I finally got to try that code. Seems to work, even with compiling the class in which it's declared.

Thanks!
January 31, 2007
Rick Mann wrote:
> Jarrett Billingsley Wrote:
> 
>> Right.  'out' implicitly passes the struct by reference, so if the struct parameter is a return value, then 'out' is the right way to go.  That it works with C libraries is something that I didn't know, and something very cool..
> 
> It makes for tidy calls where the parameter is used for output. However, I can't seem to do the same for an input parameter. I'd like to do the equivalent of the following C code:
> 
> void func(const SomeStruct& inS);
> 
> This is identical to
> 
> void func(const SomeStruct* inS);
> 
> but allows me to call it without adding the & in front of the parameter. It's a bit inconsistent that I can do this with an "out" parameter, but not an "in" parameter.

You could use inout. It's basically a C++ non-const reference.
January 31, 2007
Frits van Bommel Wrote:

> You could use inout. It's basically a C++ non-const reference.

Yeah, but it kind of breaks the implied semantics...in this case, the parameter is used as input, and not modified, so the value of the supplied parameter is unaffected by the call.
January 31, 2007
Rick Mann wrote:
> Frits van Bommel Wrote:
> 
>> You could use inout. It's basically a C++ non-const reference.
> 
> Yeah, but it kind of breaks the implied semantics...in this case, the parameter is used as input, and not modified, so the value of the supplied parameter is unaffected by the call.

For now, it's the only option we have. You can read 'inout' as 'byref'.
January 31, 2007

Rick Mann wrote:
> Frits van Bommel Wrote:
> 
>> You could use inout. It's basically a C++ non-const reference.
> 
> Yeah, but it kind of breaks the implied semantics...in this case, the parameter is used as input, and not modified, so the value of the supplied parameter is unaffected by the call.

Why? It *is* modified when you modify it inside the function ..

If my information is correct, the difference between out and inout is:
- "inout" just passes the struct by reference.
- "out" clears the struct before passing it by reference.
January 31, 2007
Hasan Aljudy Wrote:

> 
> Why? It *is* modified when you modify it inside the function ..

Well, I mean in the case where you do NOT modify it in the function, and you want to communicate(and even enforce) that contract. Allowing const on parameters would allow the compiler to generate errors in the function.
January 31, 2007
Rick Mann wrote:
> c) I need to declare a couple of extern structs. Can I just slap an "extern (C)" on these and all will be well? The spec seems to indicate that this is so, and it may be fine; I'm just looking for verification. e.g.:
> 
> struct
> ControlID
> {
> 	uint		signature;
> 	int		id;
> };
> typedef ControlID                       HIViewID;
> extern (C)
> const HIViewID kHIViewWindowContentID;

Try this:

extern extern (C) const HIViewID kHIViewWindowContentID;

http://www.digitalmars.com/d/declaration.html#extern

You need to add 'extern', just like in C headers.  Then kHIViewWindowContentID will be a pure declaration, and the linker will look elsewhere for a definition.  'extern (C)' by itself only causes the compiler to output the symbol with C instead of D name mangling.

If you link dynamically with the C lib, you are supposed to to add 'export' too, even if it works without that in some cases.
January 31, 2007
torhu Wrote:

> Try this:
> 
> extern extern (C) const HIViewID kHIViewWindowContentID;
> 
> http://www.digitalmars.com/d/declaration.html#extern
> 
> You need to add 'extern', just like in C headers.  Then kHIViewWindowContentID will be a pure declaration, and the linker will look elsewhere for a definition.  'extern (C)' by itself only causes the compiler to output the symbol with C instead of D name mangling.

Thank you! That worked very well. I did not interpret that section to mean I needed to add a second "extern" keyword.

> If you link dynamically with the C lib, you are supposed to to add 'export' too, even if it works without that in some cases.

"export" just before the rest of it, I suppose?

Can you tell me how "export" changes things? It's working right now without it, and I don't see where it is in the spec...

« First   ‹ Prev
1 2