[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