Function prototype + definition in the same file

Manu turkeyman at gmail.com
Tue Sep 25 04:53:17 PDT 2012


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... :)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20120925/52378b96/attachment.html>


More information about the Digitalmars-d mailing list