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.

Reply via email to