digitalmars.D.learn - Template: get function name
- novice3 (27/27) Aug 17 2020 Hello.
- Simen =?UTF-8?B?S2rDpnLDpXM=?= (58/86) Aug 17 2020 Take the function as an alias parameter and wrap the entire call:
- novice3 (2/6) Aug 17 2020 Thank you, Simen!
- novice3 (32/35) Aug 17 2020 Simen, for some reasons, your code dont respect api arg with
- novice3 (13/14) Aug 17 2020 reduced code https://run.dlang.io/is/U58t9R
- MoonlightSentinel (19/22) Aug 17 2020 The wrapper parameters don't inherit the storage classes from
- novice3 (3/11) Aug 17 2020 Nice, it works!
Hello. I have wrapping Windows API functions, wich return 0 on success and erroro code on failure. I copy wenforce template as: ``` private T denforce(T, S)(T value, lazy S msg = null, string file = __FILE__, size_t line = __LINE__) { import core.sys.windows.winerror: NO_ERROR; import std.conv: to; if (value != NO_ERROR) throw new WindowsException(value, to!string(msg), file, line); return value; } ``` and use it: ``` DhcpEnumServers(0, null, servers, null, null).denforce("DhcpEnumServers"); ```` Then windows api - extern (Windows)DhcpEnumServers - return error, then Windows exception throwed with name of failed api "DhcpEnumServers". Can we change template to avoid api name dublicate? Can denforce template obtain "DhcpEnumServers" function name to format message "DhcpEnumServers api failed"? Thanks.
Aug 17 2020
On Monday, 17 August 2020 at 08:07:32 UTC, novice3 wrote:Hello. I have wrapping Windows API functions, wich return 0 on success and erroro code on failure. I copy wenforce template as: ``` private T denforce(T, S)(T value, lazy S msg = null, string file = __FILE__, size_t line = __LINE__) { import core.sys.windows.winerror: NO_ERROR; import std.conv: to; if (value != NO_ERROR) throw new WindowsException(value, to!string(msg), file, line); return value; } ``` and use it: ``` DhcpEnumServers(0, null, servers, null, null).denforce("DhcpEnumServers"); ```` Then windows api - extern (Windows)DhcpEnumServers - return error, then Windows exception throwed with name of failed api "DhcpEnumServers". Can we change template to avoid api name dublicate? Can denforce template obtain "DhcpEnumServers" function name to format message "DhcpEnumServers api failed"? Thanks.Take the function as an alias parameter and wrap the entire call: auto denforce(alias fn, string file = __FILE__, size_t line = __LINE__, Args...)(Args args) { import core.sys.windows.winerror: NO_ERROR; auto value = fn(args); if (value != NO_ERROR) { throw new WindowsException(value, __traits(identifier, fn)~" api call failed.", file, line); } return value; } unittest { denforce!DhcpEnumServers(0, null, servers, null, null); } For bonus points, you could also get the error message for the returned error code: string convertErrorCode(uint code) { import core.sys.windows.winbase : FormatMessage, LoadLibrary, FORMAT_MESSAGE_FROM_SYSTEM, FORMAT_MESSAGE_IGNORE_INSERTS, FORMAT_MESSAGE_FROM_HMODULE; wchar[512] buf; auto written = FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, null, code, 0, buf.ptr, buf.length, null); if (!written) { auto inst = LoadLibrary("Ntdsbmsg.dll"); if (inst) { written = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS, inst, code, 0, buf.ptr, buf.length, null); } } if (written) { import std.conv : to; return buf.ptr.to!string; } else { import std.format : format; return format("An unknown error occured: %x", code); } } unittest { import core.sys.windows.winerror : ERROR_INVALID_FUNCTION; import std.stdio; writeln(convertErrorCode(ERROR_INVALID_FUNCTION)); writeln(convertErrorCode(1234567891)); } -- Simen
Aug 17 2020
On Monday, 17 August 2020 at 08:55:49 UTC, Simen Kjærås wrote:Take the function as an alias parameter and wrap the entire call: auto denforce(alias fn, string file = __FILE__, size_t line = __LINE__, Args...)(Args args)Thank you, Simen!
Aug 17 2020
On Monday, 17 August 2020 at 08:55:49 UTC, Simen Kjærås wrote:Simen, for some reasons, your code dont respect api arg with "out" attribute. For example, i have ``` extern (Windows) DhcpEnumServers( in DWORD Flags, // must be zero in LPVOID IdInfo, // must be NULL out LPDHCP_SERVER_INFO_ARRAY Servers, // output servers list in LPVOID CallbackFn, // must be NULL in LPVOID CallbackData // must be NULL ); ``` and then i use it: ``` LPDHCP_SERVER_INFO_ARRAY servers; denforce!DhcpEnumServers(0, null, servers, null, null); ``` access violation occur. In disassembler we can see that servers parameter passed by value (initial 0 instead of address). In my earler code it wass passed properly, by ref. May be this not matter of your code, and i can bypass it by change extern declaration to LPDHCP_SERVER_INFO_ARRAY *Servers, but it will be interest to know the reasons... Any way, tnaks you for your code, i will use it.Take the function as an alias parameter and wrap the entire call:
Aug 17 2020
On Monday, 17 August 2020 at 09:45:55 UTC, novice3 wrote:access violation occur.reduced code https://run.dlang.io/is/U58t9R void test(out int x) { x = 42; } void call (alias fn, Args ...)(Args args) { fn(args); } void main(){ int a; a = 111; test(a); assert(a == 42); // OK a = 222; call!test(a); assert(a == 42); // FAIL }
Aug 17 2020
On Monday, 17 August 2020 at 09:59:21 UTC, novice3 wrote:On Monday, 17 August 2020 at 09:45:55 UTC, novice3 wrote:The wrapper parameters don't inherit the storage classes from the wrapped function. Try using std.traits.Parameters instead: https://run.dlang.io/is/wTyJWD. ``` import std.traits : Parameters; void test(out int x) { x = 42; } void call (alias fn)(Parameters!fn args) { fn(args); } void main() { int a; a = 111; test(a); assert(a == 42); a = 222; call!test(a); assert(a == 42); } ```access violation occur.reduced code https://run.dlang.io/is/U58t9R
Aug 17 2020
On Monday, 17 August 2020 at 10:11:29 UTC, MoonlightSentinel wrote:On Monday, 17 August 2020 at 09:59:21 UTC, novice3 wrote:Nice, it works!On Monday, 17 August 2020 at 09:45:55 UTC, novice3 wrote:The wrapper parameters don't inherit the storage classes from the wrapped function. Try using std.traits.Parameters instead: https://run.dlang.io/is/wTyJWD.access violation occur.reduced code https://run.dlang.io/is/U58t9R
Aug 17 2020