Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
August 17, 2020 Template: get function name | ||||
---|---|---|---|---|
| ||||
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. |
August 17, 2020 Re: Template: get function name | ||||
---|---|---|---|---|
| ||||
Posted in reply to novice3 | 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 |
August 17, 2020 Re: Template: get function name | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen Kjærås | 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!
|
August 17, 2020 Re: Template: get function name | ||||
---|---|---|---|---|
| ||||
Posted in reply to novice3 | > 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:
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.
|
August 17, 2020 Re: Template: get function name | ||||
---|---|---|---|---|
| ||||
Posted in reply to novice3 | 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 } |
August 17, 2020 Re: Template: get function name | ||||
---|---|---|---|---|
| ||||
Posted in reply to novice3 | On Monday, 17 August 2020 at 09:59:21 UTC, novice3 wrote: > On Monday, 17 August 2020 at 09:45:55 UTC, novice3 wrote: >> access violation occur. > > reduced code https://run.dlang.io/is/U58t9R 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); } ``` |
August 17, 2020 Re: Template: get function name | ||||
---|---|---|---|---|
| ||||
Posted in reply to MoonlightSentinel | On Monday, 17 August 2020 at 10:11:29 UTC, MoonlightSentinel wrote:
> On Monday, 17 August 2020 at 09:59:21 UTC, novice3 wrote:
>> On Monday, 17 August 2020 at 09:45:55 UTC, novice3 wrote:
>>> access violation occur.
>>
>> reduced code https://run.dlang.io/is/U58t9R
>
> 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.
Nice, it works!
|
Copyright © 1999-2021 by the D Language Foundation