digitalmars.D.learn - Qs about structs and their references WRT C functions and variables
- Rick Mann (16/16) Jan 30 2007 I'm working on some C bindings, and I need to know a few things that are...
- Jarrett Billingsley (31/57) Jan 30 2007 Right. 'out' implicitly passes the struct by reference, so if the struc...
- Rick Mann (8/33) Jan 30 2007 It makes for tidy calls where the parameter is used for output. However,...
- Frits van Bommel (2/18) Jan 30 2007 You could use inout. It's basically a C++ non-const reference.
- Rick Mann (2/3) Jan 30 2007 Yeah, but it kind of breaks the implied semantics...in this case, the pa...
- Mike Parker (2/7) Jan 30 2007 For now, it's the only option we have. You can read 'inout' as 'byref'.
- Hasan Aljudy (5/10) Jan 30 2007 Why? It *is* modified when you modify it inside the function ..
- Rick Mann (2/4) Jan 31 2007 Well, I mean in the case where you do NOT modify it in the function, and...
- torhu (10/21) Jan 31 2007 Try this:
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
Jan 30 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, RickHmm.. 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.
Jan 30 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!
Jan 30 2007
Rick Mann wrote:Jarrett Billingsley Wrote:You could use inout. It's basically a C++ non-const reference.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.
Jan 30 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.
Jan 30 2007
Rick Mann wrote:Frits van Bommel Wrote:For now, it's the only option we have. You can read 'inout' as 'byref'.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.
Jan 30 2007
Rick Mann wrote:Frits van Bommel Wrote: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.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.
Jan 30 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.
Jan 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.
Jan 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...
Jan 31 2007
Rick Mann wrote:torhu Wrote:export is mentioned on these pages, the first two being most relevant to what you're doing: http://www.digitalmars.com/d/attribute.html http://www.digitalmars.com/d/htomodule.html http://www.digitalmars.com/d/dll.html http://www.digitalmars.com/d/windows.html I don't know much more than what's on those pages. But like I said, some variables seem to link correctly without 'export'. Which ones might depend on the compiler or linker you're using. Using 'export' means that you can't link statically to the C lib and expect things to work. Not sure what to do about that, I just use search and replace to remove export.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...
Jan 31 2007