Template: get function name
Simen Kjærås
simen.kjaras at gmail.com
Mon Aug 17 08:55:49 UTC 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
More information about the Digitalmars-d-learn
mailing list