digitalmars.D.learn - boilerplate generation
- Carl Sturtivant (15/15) Dec 29 2013 I want to be able to define a number of extern(C) functions that
- Dicebot (36/36) Dec 29 2013 Does this look clean enough? (Not sure I have completely
- Carl Sturtivant (6/43) Dec 29 2013 Very nice. Only one problem: when I use dmd/win32 to build the
- Dicebot (45/50) Dec 29 2013 Ah, yeah, have missed that. Such thing is expected if symbol is
- Carl Sturtivant (4/5) Dec 30 2013 Never heard of pragma(mangle)! Very useful. What role does it
- John Colvin (4/9) Dec 30 2013 It's unrelated to the target architecture, it's just for naming.
- Carl Sturtivant (5/7) Dec 30 2013 Apologies, I was perhaps unclear. I'm just wondering if
- Dicebot (7/11) Dec 30 2013 Nature of reference compiler is that anything implemented there
I want to be able to define a number of extern(C) functions that will define a C API in a DLL, varying only in their names, each as follows. export extern(C) int f( uint argc, A* argv) { return Wrapper!f( argc, argv); } Here Wrapper!f is a wrapper around a D function named f that does the work, called from C via the f defined here. I'd like a piece of D machinery that provides a short clean way to embed one of these in a program, where the name f is specified once, and the code is invisible. I've had no success at solving this problem with templates or mixin templates. I can use CTFE so I can write mixin( Export("f")); to introduce the definition for f. Is this the best way to proceed? What are other options?
Dec 29 2013
Does this look clean enough? (Not sure I have completely understood the question) /* export extern(C) int f( uint argc, A* argv) { return Wrapper!f( argc, argv); } */ struct A {} int Wrapper(alias func, T...)(T args) { return 42; } template ExternC(alias existingFunc) { import std.string : format; import std.traits : ReturnType; static assert(is(typeof(&existingFunc) : int function(uint, A*))); mixin(format( "export extern(C) int %s(uint argc, A* argv) { return Wrapper!(%s)(argc, argv); }", __traits(identifier, existingFunc), __traits(identifier, existingFunc) )); } // to avoid name clash, assuming you have different module in real code struct X { static int fff(uint, A*) { return 42; } } mixin ExternC!(X.fff); pragma(msg, typeof(fff)); // extern (C) int(uint argc, A* argv) void main() { }
Dec 29 2013
On Sunday, 29 December 2013 at 22:01:19 UTC, Dicebot wrote:Does this look clean enough? (Not sure I have completely understood the question) /* export extern(C) int f( uint argc, A* argv) { return Wrapper!f( argc, argv); } */ struct A {} int Wrapper(alias func, T...)(T args) { return 42; } template ExternC(alias existingFunc) { import std.string : format; import std.traits : ReturnType; static assert(is(typeof(&existingFunc) : int function(uint, A*))); mixin(format( "export extern(C) int %s(uint argc, A* argv) { return Wrapper!(%s)(argc, argv); }", __traits(identifier, existingFunc), __traits(identifier, existingFunc) )); } // to avoid name clash, assuming you have different module in real code struct X { static int fff(uint, A*) { return 42; } } mixin ExternC!(X.fff); pragma(msg, typeof(fff)); // extern (C) int(uint argc, A* argv) void main() { }Very nice. Only one problem: when I use dmd/win32 to build the DLL, and analyze the resulting export, it's _D5mixin43__T7ExternCS28_D5mixin1X3fffFkPS5mixin1AZiZ3fffUkPS5mixin1AZi and not _fff or similar. So somehow the extern(C) hasn't led to a C symbol.
Dec 29 2013
On Sunday, 29 December 2013 at 22:28:00 UTC, Carl Sturtivant wrote:Very nice. Only one problem: when I use dmd/win32 to build the DLL, and analyze the resulting export, it's _D5mixin43__T7ExternCS28_D5mixin1X3fffFkPS5mixin1AZiZ3fffUkPS5mixin1AZi and not _fff or similar. So somehow the extern(C) hasn't led to a C symbol.Ah, yeah, have missed that. Such thing is expected if symbol is nested and can't have clear C mangling (then extern(C) only impacts ABI). It is kind of weird that this is also the case for mixin templates as those are injected into target scope but makes sense once you remember that even mixin templates conform symbol hygiene. It can be forced by pragma(mangle) though. Updated code: struct A {} int Wrapper(alias func, T...)(T args) { return 42; } template ExternC(alias existingFunc) { import std.string : format; import std.traits : ReturnType; static assert(is(typeof(&existingFunc) : int function(uint, A*))); private enum name = __traits(identifier, existingFunc); mixin(format( q{pragma(mangle, "%s") export extern(C) int %s(uint argc, A* argv) { return Wrapper!(%s)(argc, argv); }}, name, name, name )); } // to avoid name clash, assuming you have different module in // real code struct X { static int fff(uint, A*) { return 42; } } mixin ExternC!(X.fff); pragma(msg, typeof(fff)); // extern (C) int(uint argc, A* argv) pragma(msg, fff.mangleof); // fff void main() {}
Dec 29 2013
On Monday, 30 December 2013 at 04:35:34 UTC, Dicebot wrote:It can be forced by pragma(mangle) though. Updated code: [...]Never heard of pragma(mangle)! Very useful. What role does it play in D? Is it guaranteed implemented on x86 or amd64? Thanks for the answer, very nice.
Dec 30 2013
On Monday, 30 December 2013 at 17:33:13 UTC, Carl Sturtivant wrote:On Monday, 30 December 2013 at 04:35:34 UTC, Dicebot wrote:It's unrelated to the target architecture, it's just for naming. See dlang.org/abi.htmlIt can be forced by pragma(mangle) though. Updated code: [...]Never heard of pragma(mangle)! Very useful. What role does it play in D? Is it guaranteed implemented on x86 or amd64? Thanks for the answer, very nice.
Dec 30 2013
On Monday, 30 December 2013 at 17:46:57 UTC, John Colvin wrote:It's unrelated to the target architecture, it's just for naming. See dlang.org/abi.htmlApologies, I was perhaps unclear. I'm just wondering if pragma(mangle) is guaranteed to be implemented, so I can safely put it in portable D. It's not mentioned in http://dlang.org/pragma.html
Dec 30 2013
On Monday, 30 December 2013 at 20:04:00 UTC, Carl Sturtivant wrote:Apologies, I was perhaps unclear. I'm just wondering if pragma(mangle) is guaranteed to be implemented, so I can safely put it in portable D. It's not mentioned in http://dlang.org/pragma.htmlNature of reference compiler is that anything implemented there is approved as part of spec. I guess one implementing it just forgot to add matching documentation entry as it is relatively new addition. https://d.puremagic.com/issues/show_bug.cgi?id=11846
Dec 30 2013