[core.reflect] autowrap example
Stefan Koch
uplink.coder at googlemail.com
Wed Oct 6 11:43:46 UTC 2021
Good Morning Everyone,
I have been working a little to present some real world example
of where core.reflect might be used.
One of them is automatic wrapper generation.
(For example you might want to call D functions from C# or
something).
There is a library called autowrap which does this using
templates and string mixins.
Which tries to get the `__traits` reflection data into string
form as soon as possible in order to avoid template overhead.
Here I am reimplemeting a very small part of their C# wrapper.
```D
import core.reflect.reflect;
import core.reflect.utils;
string getDlangInterfaceType(const Type type)
{
assert(isAggregateType(T));
auto u = unqualType(type);
auto slice_type = cast(TypeSlice) type;
if (slice_type !is null)
{
u = unqualType(slice_type.nextOf);
}
string result;
switch(u.serial)
{
case getType("Duration", ReflectFlags.Default, sc).serial
:
result = "Marshalled_Duration";
break;
case getType("DateTime", ReflectFlags.Default, sc).serial
:
case getType("Date", ReflectFlags.Default, sc).serial :
case getType("TimeOfDay", ReflectFlags.Default,
sc).serial :
result = "Marshalled_std_datetime_date";
break;
case getType("SysTime", ReflectFlags.Default, sc).serial :
result = "Marshalled_std_datetime_systime";
break;
default :
result = getAggregate(u).fqn();
}
if (slice_type)
{
return result ~= "[]";
}
return result;
}
static assert(() {
auto st = nodeFromName("SysTime");
return st.getType().getDlangInterfaceType();
} () == "Marshalled_std_datetime_systime");
// works at compile time.
struct S
{
DateTime[] dates;
}
static immutable s = nodeFromName("S", ReflectFlags.Members);
void main()
{
string result;
printf("%s\n", getType(s)
.fields()[0]
.getType()
.getDlangInterfaceType().ptr
);
// works at runtime as well -- output:
"Marshalled_std_datetime_date[]"
// perhaps with some garbage at the end if you are
unlucky and it's not a '\0'
}
```
Note the functions `getType`,`getAggregate`, `fields` `fqn` and
`unqualType` are defined in the core.reflect utility module
As a comparison here is the version which exists in
`autowrap/csharp` today:
```D
private string getDLangInterfaceType(T)() {
import core.time : Duration;
import std.datetime.date : Date, DateTime, TimeOfDay;
import std.datetime.systime : SysTime;
import std.traits : fullyQualifiedName, Unqual;
alias U = Unqual!T;
// FIXME This code really should be reworked so that there's
no need to
// check for arrays of date/time types, but rather it's part
of the general
// array handling.
static if(is(U == Duration))
return "Marshalled_Duration";
else static if(is(U == DateTime) || is(U == Date) || is(U ==
TimeOfDay))
return "Marshalled_std_datetime_date";
else static if(is(U == SysTime))
return "Marshalled_std_datetime_systime";
else static if(is(U == Duration[]))
return "Marshalled_Duration[]";
else static if(is(U == DateTime[]) || is(U == Date[]) || is(U
== TimeOfDay[]))
return "Marshalled_std_datetime_date[]";
else static if(is(U == SysTime[]))
return "Marshalled_std_datetime_systime[]";
else
return fullyQualifiedName!T;
}
```
As you can see the version in auto-wrap appears to be shorter.
mainly because there are no separate lines for the types
`DateTime` `Time` and `TimeOfDay`.
Also note that you cannot use the getType which takes a string at
runtime.
the only reason this works is because the cases are supposed to
be constant expressions and at compile time it gets
constant-folded into
```D
case 2658LU:
{
result = "Marshalled_Duration";
break;
}
case 53134LU:
case 55933LU:
case 56951LU:
{
result = "Marshalled_std_datetime_date";
break;
}
case 99806LU:
{
result = "Marshalled_std_datetime_systime";
break;
}
```
More information about the Digitalmars-d
mailing list