digitalmars.D.learn - How to create a function declaration?
- Marcio Faustino (21/21) Jan 12 2007 Hi everyone,
- Sean Kelly (6/33) Jan 12 2007 Nothing. I think the implementation needs to be in a separate file if
- rochus (2/6) Jan 12 2007 If you meant a "foreward declaration": this is not possible in D.
- Frank Benoit (keinfarbton) (5/13) Jan 12 2007 In the normal case, something like that is not needed.
- Frits van Bommel (16/39) Jan 12 2007 You're writing forward declarations. Seriously, D doesn't need them;
- Marcio Faustino (17/25) Jan 12 2007 So, how can I do something like this:
- Frits van Bommel (6/27) Jan 12 2007 'printf' is problematic because object.d (which is automatically
- Marcio Faustino (6/11) Jan 12 2007 But the problem is that the code *does not* compile with the line that s...
- Frits van Bommel (13/27) Jan 12 2007 The compiler sees two declarations for printf, in different modules. It
- Stewart Gordon (11/23) Jan 12 2007 You've more or less answered your own question: use a fully-qualified
- Marcio Faustino (5/8) Jan 12 2007 That's a nice alternative, but I don't want to use that. Suppose someone...
- Jarrett Billingsley (3/5) Jan 12 2007 It's declared in two places, and so when you call "printf" in test.d, it...
- Frits van Bommel (4/14) Jan 12 2007 If one is writing a kernel, one probably modifies object.d ;).
- Marcio Faustino (5/8) Jan 12 2007 The downside of modifying "object.d" is that you'll end up having a mini...
- Frits van Bommel (13/23) Jan 12 2007 That's what happens with any kernel project in any language higher than
- Sean Kelly (21/27) Jan 12 2007 I think the same conflict can occur in this situation though:
- Tyler Knott (4/12) Jan 12 2007 What's wrong with importing the entire header module? That's what
- Sean Kelly (11/24) Jan 12 2007 In the past, there were some issues with D where importing even empty
- Frits van Bommel (8/43) Jan 12 2007 You cut that quote a bit short. Reread the rest of that paragraph at the...
- Sean Kelly (5/13) Jan 12 2007 Fair enough. I replied mostly because I thought it may be useful to
Hi everyone, How can I create a function declaration only and provide its definition later? For example: /******************************************************************************/ extern (C) int print(char*); extern (C) int print(char* s) { return printf("%s", s); } void main() { print(cast(char*) "test\0"); } /******************************************************************************/ The compiler says: «test.d(9): function test.print called with argument types: (char*) matches both: test.print(char*) and: test.print(char*)» What am I doing wrong? Thanks,
Jan 12 2007
Marcio Faustino wrote:Hi everyone, How can I create a function declaration only and provide its definition later? For example: /******************************************************************************/ extern (C) int print(char*); extern (C) int print(char* s) { return printf("%s", s); } void main() { print(cast(char*) "test\0"); } /******************************************************************************/ The compiler says: «test.d(9): function test.print called with argument types: (char*) matches both: test.print(char*) and: test.print(char*)» What am I doing wrong? Thanks,Nothing. I think the implementation needs to be in a separate file if you want separate compilation like that. Though it would admittedly be nice if the compiler could recognize that there is no actual conflict between a declaration and an implementation of the same function. Sean
Jan 12 2007
Marcio Faustino wrote:Hi everyone, How can I create a function declaration only and provide its definition later? For example:If you meant a "foreward declaration": this is not possible in D.
Jan 12 2007
rochus schrieb:Marcio Faustino wrote:In the normal case, something like that is not needed. For libs, there is the possibilty to generate headers. For dmd use the -H option. The generated .di files will contain all declarations the compiler needs to compile a module.Hi everyone, How can I create a function declaration only and provide its definition later? For example:If you meant a "foreward declaration": this is not possible in D.
Jan 12 2007
Marcio Faustino wrote:How can I create a function declaration only and provide its definition later?You can't. Not in the same file, at least.[1]For example: /******************************************************************************/ extern (C) int print(char*); extern (C) int print(char* s) { return printf("%s", s); } void main() { print(cast(char*) "test\0"); } /******************************************************************************/ The compiler says: «test.d(9): function test.print called with argument types: (char*) matches both: test.print(char*) and: test.print(char*)»What am I doing wrong?You're writing forward declarations. Seriously, D doesn't need them; forward references are allowed ;). A function declaration without definition is for when you put the definition in a different file, not to put it later in the same file. It's mostly useful to link to libraries designed to link to C, though Phobos also uses it in object.d to link to definitions in internal/object.d. It *could* also be useful to link to closed-source D libraries, but I haven't seen any yet... [1]: I just had an evil idea. Turns out it's technically possible. You can declare extern(C) it with a different argument type, then both overloads will have the same name in the executable (no name mangling) and the linker will link them both to the same definition. But I wouldn't use this for anything serious, and I wouldn't have been surprised if it hadn't worked at all due to a symbol conflict or something.
Jan 12 2007
You're writing forward declarations. Seriously, D doesn't need them; forward references are allowed ;). A function declaration without definition is for when you put the definition in a different file, not to put it later in the same file. It's mostly useful to link to libraries designed to link to C, though Phobos also uses it in object.d to link to definitions in internal/object.d. It *could* also be useful to link to closed-source D libraries, but I haven't seen any yet...So, how can I do something like this: /*[ my_printf.d ]**************************************************************/ module my_printf; extern (C) int printf(char* format, ...) { return 0; // Just to test. } /******************************************************************************/ /*[ test.d ]*******************************************************************/ import my_printf; void main() { //printf("test\0"); // Error. my_printf.printf("test\0"); // Ok. } /******************************************************************************/ Because the line with "Error" uncommented, the compiler says: «test.d(5): Error: object.printf at /home/marcio/dmd/src/phobos/object.d(14) conflicts with my_printf.printf at my_printf.d(3)»
Jan 12 2007
Marcio Faustino wrote:So, how can I do something like this: /*[ my_printf.d ]**************************************************************/ module my_printf; extern (C) int printf(char* format, ...) { return 0; // Just to test. } /******************************************************************************/ /*[ test.d ]*******************************************************************/ import my_printf; void main() { //printf("test\0"); // Error. my_printf.printf("test\0"); // Ok. } /******************************************************************************/ Because the line with "Error" uncommented, the compiler says: «test.d(5): Error: object.printf at /home/marcio/dmd/src/phobos/object.d(14) conflicts with my_printf.printf at my_printf.d(3)»'printf' is problematic because object.d (which is automatically imported into every D module) also declares it. That code might otherwise compile, but I'm not sure what would happen at the linking stage; printf is also defined in the C runtime library which is linked to by default. It might just use one of the two, or it might fail.
Jan 12 2007
Frits van Bommel wrote:'printf' is problematic because object.d (which is automatically imported into every D module) also declares it. That code might otherwise compile, but I'm not sure what would happen at the linking stage; printf is also defined in the C runtime library which is linked to by default. It might just use one of the two, or it might fail.But the problem is that the code *does not* compile with the line that says "Error" uncommented. Without getting into linking details, the compiler *should* accept the given definition because "object.d" and "internal/object.d" only contain declarations of the printf function. Am I wrong?
Jan 12 2007
Marcio Faustino wrote:Frits van Bommel wrote:The compiler sees two declarations for printf, in different modules. It sees these as different functions as one is 'object.printf' and the other is 'my_printf.printf'. The easiest ways to solve this ambiguity are (1) rename your printf ;). (2) add 'alias my_printf.printf printf' to your test.d to make it clear which printf you want. (3) change the import line to 'import my_printf : printf' to import only printf from that module and additionally get the effect of (2). I know it seems a bit silly to have to disambiguate between two declarations that will generate the exact same machine code when called (including the called address) but D's name resolution was probably designed with name mangling in mind...'printf' is problematic because object.d (which is automatically imported into every D module) also declares it. That code might otherwise compile, but I'm not sure what would happen at the linking stage; printf is also defined in the C runtime library which is linked to by default. It might just use one of the two, or it might fail.But the problem is that the code *does not* compile with the line that says "Error" uncommented. Without getting into linking details, the compiler *should* accept the given definition because "object.d" and "internal/object.d" only contain declarations of the printf function. Am I wrong?
Jan 12 2007
Marcio Faustino wrote: <snip>/*[ test.d ]*******************************************************************/ import my_printf; void main() { //printf("test\0"); // Error. my_printf.printf("test\0"); // Ok. } /******************************************************************************/ Because the line with "Error" uncommented, the compiler says: «test.d(5): Error: object.printf at /home/marcio/dmd/src/phobos/object.d(14) conflicts with my_printf.printf at my_printf.d(3)»You've more or less answered your own question: use a fully-qualified name. Alternatively, use in test.d alias my_printf.printf printf; However, when doing it on functions with C linkage, you have to be careful. Because they don't have the module name mangled in, you may cause a linker conflict or end up inadvertently calling the C library function with the same name. Indeed, I don't know why this doesn't cause a linker conflict when I try it (under DMD 1.00, Win98SE). Stewart.
Jan 12 2007
Stewart Gordon wrote:You've more or less answered your own question: use a fully-qualified name. Alternatively, use in test.d alias my_printf.printf printf;That's a nice alternative, but I don't want to use that. Suppose someone were writing a kernel, then the compiler should accept the printf definition he gave because he won't link against the C library. Even so, the compiler says that "object.printf" conflicts with "my_printf.printf"... but where??
Jan 12 2007
Marcio Faustino Wrote:Even so, the compiler says that "object.printf" conflicts with "my_printf.printf"... but where??It's declared in two places, and so when you call "printf" in test.d, it finds two printfs. It's a simple matter of symbol lookup -- one name in this case maps to more than one possible function. So the conflict occurs at the call site, which can be fixed by using either an FQN or an alias, as mentioned. If you were linking against some C stdlib that didn't have an implementation of printf, the fix is very simple -- comment out the printf declaration in object.d.
Jan 12 2007
Marcio Faustino wrote:Stewart Gordon wrote:If one is writing a kernel, one probably modifies object.d ;). At least, that's what I did... (Actually, printf was the first thing to get removed :P)You've more or less answered your own question: use a fully-qualified name. Alternatively, use in test.d alias my_printf.printf printf;That's a nice alternative, but I don't want to use that. Suppose someone were writing a kernel, then the compiler should accept the printf definition he gave because he won't link against the C library. Even so, the compiler says that "object.printf" conflicts with "my_printf.printf"... but where??
Jan 12 2007
Thanks for all the replies, I think I understand it now. Frits van Bommel wrote:If one is writing a kernel, one probably modifies object.d ;). At least, that's what I did... (Actually, printf was the first thing to get removed :P)The downside of modifying "object.d" is that you'll end up having a mini-phobos library with only the stuff you need, right? As for your kernel, can I see the source code? :-)
Jan 12 2007
Marcio Faustino wrote:Thanks for all the replies, I think I understand it now. Frits van Bommel wrote:That's what happens with any kernel project in any language higher than C (i.e. any language that needs some form of runtime). Though some C compilers may generate implicit memcpy() calls etc., so I guess that counts...If one is writing a kernel, one probably modifies object.d ;). At least, that's what I did... (Actually, printf was the first thing to get removed :P)The downside of modifying "object.d" is that you'll end up having a mini-phobos library with only the stuff you need, right?As for your kernel, can I see the source code? :-)It doesn't do much of any use currently. It just boots and shows some status messages while initializing the system. Then it just sits there, echoing keyboard input. It doesn't even clean up after itself (no way of freeing allocated memory). I plan on implementing or porting a GC some day, but at the moment it doesn't use enough memory to make it worth freeing. I just think it should be at least marginally functional before I go spreading the source around :).
Jan 12 2007
Frits van Bommel wrote:You're writing forward declarations. Seriously, D doesn't need them; forward references are allowed ;). A function declaration without definition is for when you put the definition in a different file, not to put it later in the same file.I think the same conflict can occur in this situation though: module a; extern (C) void fn(); module b; extern (C) void fn(); module c; import a, b; void main() { fn(); } This one has bitten me a few times where I had declared the prototype for a C library routine to avoid importing the entire header module, and a derived module imported both my module and the C header module. Even worse, the same error will occur if one of the two declarations is private, because of how symbol resolution is handled. This makes the approach outlined above completely intractable, and actually more restrictive than C where multiple prototypes of the same function are allowed. Sean
Jan 12 2007
Sean Kelly wrote:This one has bitten me a few times where I had declared the prototype for a C library routine to avoid importing the entire header module, and a derived module imported both my module and the C header module. Even worse, the same error will occur if one of the two declarations is private, because of how symbol resolution is handled. This makes the approach outlined above completely intractable, and actually more restrictive than C where multiple prototypes of the same function are allowed.What's wrong with importing the entire header module? That's what modules are designed for: avoiding declaring the same function multiple times. They also don't add any code bloat.
Jan 12 2007
Tyler Knott wrote:Sean Kelly wrote:In the past, there were some issues with D where importing even empty modules bloated the executable quite noticeably (I think it was ~500 bytes per empty module). This appeared related to ModuleInfo that was generated apparently regardless of whether it was necessary. I re-tested this recently, however, and was unable to reproduce my old results, so I think this problem has been fixed as a side-effect of other changes. Still, there are some places in my code where I have declarations of C routines rather than imports, as I haven't gone to the trouble of changing them now that this seems to have been resolved. SeanThis one has bitten me a few times where I had declared the prototype for a C library routine to avoid importing the entire header module, and a derived module imported both my module and the C header module. Even worse, the same error will occur if one of the two declarations is private, because of how symbol resolution is handled. This makes the approach outlined above completely intractable, and actually more restrictive than C where multiple prototypes of the same function are allowed.What's wrong with importing the entire header module? That's what modules are designed for: avoiding declaring the same function multiple times. They also don't add any code bloat.
Jan 12 2007
Sean Kelly wrote:Frits van Bommel wrote:You cut that quote a bit short. Reread the rest of that paragraph at the end of your quote. What I was talking about was more in the line of Phobos' object.d & internal/object.d, or a C source file and its D import module. Either way, only one of the files is intended to be imported (but shouldn't get compiled itself). The other file then gets compiled and linked in its place.You're writing forward declarations. Seriously, D doesn't need them; forward references are allowed ;). A function declaration without definition is for when you put the definition in a different file, not to put it later in the same file.I think the same conflict can occur in this situation though: module a; extern (C) void fn(); module b; extern (C) void fn(); module c; import a, b; void main() { fn(); } This one has bitten me a few times where I had declared the prototype for a C library routine to avoid importing the entire header module, and a derived module imported both my module and the C header module. Even worse, the same error will occur if one of the two declarations is private, because of how symbol resolution is handled. This makes the approach outlined above completely intractable, and actually more restrictive than C where multiple prototypes of the same function are allowed.
Jan 12 2007
Frits van Bommel wrote:You cut that quote a bit short. Reread the rest of that paragraph at the end of your quote. What I was talking about was more in the line of Phobos' object.d & internal/object.d, or a C source file and its D import module. Either way, only one of the files is intended to be imported (but shouldn't get compiled itself). The other file then gets compiled and linked in its place.Fair enough. I replied mostly because I thought it may be useful to mention a related issue I'd encountered in the past. My apologies if the implication was otherwise. Sean
Jan 12 2007