Function prototype + definition in the same file

deadalnix deadalnix at gmail.com
Tue Sep 25 10:49:33 PDT 2012


Le 25/09/2012 13:53, Manu a écrit :
> So I have this recurring pattern, it's really starting to annoy me.
> It stems from the fact that a function prototype and the definition can
> not appear in the same file in D (as it can in C/C++)
> Eg,
>
> void func(int x); // <-- declaration of function, informs type and
> associated names, args, ...
>
> //later
> void func(int x) // <-- may be generated with magic (and may use the
> prototype declaration for type information as declared by the prototype
> above)
> {
>    ... do stuff
> }
>
> I really need this. Why is it illegal? Is there chance of having this
> supported? What are the problems?
>
> My problem is essentially to do with supporting both static or dynamic
> linkage optionally, but it also shows up in situations where I want to
> perform comprehensive magic code generation, but want clear-readable
> user declarations.
> The simplest case:
>    I have an extern that I may want to statically or dynamically link.
>      In the case of static linkage, one just produces a prototype, and
> it links, no problem.
>      In the case of dynamic linkage, one must produce a stub for the
> function, a function pointer to call through, and perhaps some code to
> hook-up the function pointer at init.
>
> I have a fairly comprehensive binding solution which automates the work
> in the case of dynamic linkage, but the problem is the way the user
> defines the functions that exist in the D code.
> I'd like it if the users would just write the prototypes, they'd be
> easily readable, simple to create by cutting and pasting straight from C
> code. And when statically linking, it would just work, the module
> hook-up mixin does nothing in this configuration.
> In the case of dynamic linkage, a single hook-up mixin in the file
> somewhere could scan the module for these prototypes and generate the
> stubs, function pointers, and the boot-up code that would connect them
> (while validating their signatures against the extern import table, etc).
>
> This approach isn't supported though. What I do instead:
>
> mixin( ImportFunction!( "functionName", int function( int arg1, float
> arg2, ref in SomeStruct arg3 ), "pure nothrow" ) );
> mixin( ImportFunction!( "functionName2", int function() ) );
> mixin( ImportFunction!( "functionName3", int function( int x, int y ),
> "nothrow" ) );
> etc etc
>
> These templates produce, from the information provided, either a
> prototype for static linkage, or the { stub, func pointer,
> initialisation info } for dynamic linkage.
>
> I really don't like doing it this way for a number of reasons:
>    *** This results in hundreds of mixins, which quickly lead to
> intolerable compile times (to the point where D is losing it's appeal as
> a viable choice for our needs). If done my preferred way, I could do the
> magic with a single mixin at the bottom of the file.
>    * It's barely readable.
>    * Much more annoying to write and maintain when the counterpart API
> changes, and is more error-prone.
>    * IDE features don't work properly; syntax highlighting, hover info,
> go-to-definition, etc.
>
> I also have numerous more advanced cases of the same problem, and
> becomes even more unsightly when used in structs to emulate dynamic
> linkage to static methods of C++ classes.
>
> The solution is seemingly trivial; allow function prototypes and
> definitions to exist in the same file, like in C/C++.
>
>
> Go on, tear me apart... :)

This is code duplication and is generally considered as a bad practice. 
I'm not convinced that the language should be modified to allow 
something that is known as bad practice.

What you need here is a more robust di generator IMO.


More information about the Digitalmars-d mailing list