www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Using templates to declare function prototypes

reply Heinz <malagana15 yahoo.com> writes:
Hello D community!!!

I'm porting the NVIDIA CUDA headers to D. The CUDA platform runs on multiple
OS, so functions prototypes (in the D way) are declared as "extern(Windows)
..." for MS Windows and "extern(C) ..." for other OS'es.

The thing is that there's no "alias extern(X) myextern;" in D to be used like
this:

version(Windows)
    alias extern(Windows) myextern;
else
    alias extern(C) myextern;

...
myextern void cudaFunct1();
myextern uint cudaFunct2(byte*);

...The C way to accomplish this is:

#ifdef _WIN32
#define CUDAAPI __stdcall
#else
#define CUDAAPI
#endif
...
CUresult CUDAAPI cuInit(unsigned int Flags);

It is a bit redundant and dirty to declare all the functions twice. So i made
a template to declare functions prototypes with the corresponding naming
convention, here's what i got:

template CUDAAPI(R, P ...)
{
	version(Windows)
		alias extern(Windows) R function(P) CUDAAPI;
	else
		alias extern(C) R function(P) CUDAAPI;
}
...
CUDAAPI!(CUresult, uint) cuInit;

This code actually compiles since its syntax is correct but when linking i
relize that the linker is still looking for the "extern(D)" symbol and by any
means, no matter where i place the extern(X), the compiler is generating the D
mangled symbol (_D5cudad4cuda6cuInitPWkZE5cudad4cuda8CUresult, at least the
template is inserted in the context).
I've tried with DMD 1.030 and the latest 1.069, both with the same result.

I also did a mixin flavored template that also compiles but is even worse
because the linker is still stuck with a templated/D mangled symbol, take a
look:

template CUDAAPI(string N, R, P ...)
{
	version(Windows)
		mixin("extern(Windows) R " ~ N ~ "(P);");
}
...
mixin CUDAAPI!("cuInit", CUresult, uint);

The generated symbol for this code is:
__D5cudad4cuda55__T7CUDAAPIVG6aa6_6375496e6974TE5cud
ad4cuda8CUresultTkZ6cuInitWkZE5cudad4cuda8CUresult 4. As you can see, the
symbol is still recognized as a template so i discard this code.

I found templates to be a very interesting case of study, templates give
languages the fun or the exciting part of programming by presenting challenges
in code complexity but still i can not get some parts of my code to work.

Any aproach or ideas on how to accomplish this template or multi extern
declaration?

Thank you so much for reading.
Jul 30 2011
parent reply "Daniel Murphy" <yebblies nospamgmail.com> writes:
Use extern(System)?

"Heinz" <malagana15 yahoo.com> wrote in message 
news:j12hkk$2mcd$1 digitalmars.com...
 Hello D community!!!

 I'm porting the NVIDIA CUDA headers to D. The CUDA platform runs on 
 multiple
 OS, so functions prototypes (in the D way) are declared as 
 "extern(Windows)
 ..." for MS Windows and "extern(C) ..." for other OS'es.

 The thing is that there's no "alias extern(X) myextern;" in D to be used 
 like
 this:

 version(Windows)
    alias extern(Windows) myextern;
 else
    alias extern(C) myextern;

 ...
 myextern void cudaFunct1();
 myextern uint cudaFunct2(byte*);

 ...The C way to accomplish this is:

 #ifdef _WIN32
 #define CUDAAPI __stdcall
 #else
 #define CUDAAPI
 #endif
 ...
 CUresult CUDAAPI cuInit(unsigned int Flags);

 It is a bit redundant and dirty to declare all the functions twice. So i 
 made
 a template to declare functions prototypes with the corresponding naming
 convention, here's what i got:

 template CUDAAPI(R, P ...)
 {
 version(Windows)
 alias extern(Windows) R function(P) CUDAAPI;
 else
 alias extern(C) R function(P) CUDAAPI;
 }
 ...
 CUDAAPI!(CUresult, uint) cuInit;

 This code actually compiles since its syntax is correct but when linking i
 relize that the linker is still looking for the "extern(D)" symbol and by 
 any
 means, no matter where i place the extern(X), the compiler is generating 
 the D
 mangled symbol (_D5cudad4cuda6cuInitPWkZE5cudad4cuda8CUresult, at least 
 the
 template is inserted in the context).
 I've tried with DMD 1.030 and the latest 1.069, both with the same result.

 I also did a mixin flavored template that also compiles but is even worse
 because the linker is still stuck with a templated/D mangled symbol, take 
 a look:

 template CUDAAPI(string N, R, P ...)
 {
 version(Windows)
 mixin("extern(Windows) R " ~ N ~ "(P);");
 }
 ...
 mixin CUDAAPI!("cuInit", CUresult, uint);

 The generated symbol for this code is:
 __D5cudad4cuda55__T7CUDAAPIVG6aa6_6375496e6974TE5cud
 ad4cuda8CUresultTkZ6cuInitWkZE5cudad4cuda8CUresult 4. As you can see, the
 symbol is still recognized as a template so i discard this code.

 I found templates to be a very interesting case of study, templates give
 languages the fun or the exciting part of programming by presenting 
 challenges
 in code complexity but still i can not get some parts of my code to work.

 Any aproach or ideas on how to accomplish this template or multi extern
 declaration?

 Thank you so much for reading. 

Jul 30 2011
next sibling parent reply Heinz <malagana15 yahoo.com> writes:
Thanks, extern(System) seems to do the job under windows at least, i hope it
switch to extern(C) for other systems, can't test it right now. The System
version
works even with the old DMD 1.030. If this defined version is that old then why
it
is not documented yet with newer releases?

Thank you for this solution.
Jul 30 2011
parent "Daniel Murphy" <yebblies nospamgmail.com> writes:
It is documented!
http://www.digitalmars.com/d/1.0/attribute.html#linkage
http://www.digitalmars.com/d/2.0/attribute.html#linkage

"Heinz" <malagana15 yahoo.com> wrote in message 
news:j12itk$2o99$1 digitalmars.com...
 Thanks, extern(System) seems to do the job under windows at least, i hope 
 it
 switch to extern(C) for other systems, can't test it right now. The System 
 version
 works even with the old DMD 1.030. If this defined version is that old 
 then why it
 is not documented yet with newer releases?

 Thank you for this solution. 

Jul 30 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Why is there both a System and Windows linkage type if they're the
same? Is this a C++ legacy?
Jul 31 2011
prev sibling next sibling parent Trass3r <un known.com> writes:
Am 31.07.2011, 17:34 Uhr, schrieb Andrej Mitrovic  
<andrej.mitrovich gmail.com>:

 Why is there both a System and Windows linkage type if they're the
 same? Is this a C++ legacy?

Well Windows always means stdcall while System changes its meaning on Posix.
Jul 31 2011
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Oh damn I didn't finish reading the sentence:

"System is the same as Windows on Windows platforms, and C on other platforms."

Heh. :)
Jul 31 2011