Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the (fnptr)* type and how to create it?

The following IL code creates a Type instance named (fnptr)* (token 0x2000000 - invalid, module mscorlib.dll).

ldtoken method void* ()*
call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)

What's the purpose of this type? Is it possible to create this type instance in C# without writing any IL code, maybe with reflection? Module.ResolveType on the token throws ArgumentOutOfRangeException.

Edit:

It's clear the (fnptr) type is an internal CLR type representation of an IL method pointer type, though when removing the last *, it simply returns IntPtr.

Edit #2:

The (fnptr) comes from a function that can be seen in the SSCLI typestring.cpp:

// ...or function pointer
else if (ty.IsFnPtrType())
{
    // Don't attempt to format this currently, it may trigger GC due to fixups.
    tnb.AddName(L"(fnptr)");
}

Why basic fnptr returns IntPtr can be seen in typehandle.cpp:

OBJECTREF TypeHandle::GetManagedClassObject() const
{

[...]

        switch(GetInternalCorElementType()) {
        case ELEMENT_TYPE_ARRAY:
        case ELEMENT_TYPE_SZARRAY:
        case ELEMENT_TYPE_BYREF:
        case ELEMENT_TYPE_PTR:
            return ((ParamTypeDesc*)AsTypeDesc())->GetManagedClassObject();

        case ELEMENT_TYPE_VAR:
        case ELEMENT_TYPE_MVAR:
            return ((TypeVarTypeDesc*)AsTypeDesc())->GetManagedClassObject();

            // for this release a function pointer is mapped into an IntPtr. This result in a loss of information. Fix next release
        case ELEMENT_TYPE_FNPTR:
            return TheIntPtrClass()->GetManagedClassObject();

        default:
        _ASSERTE(!"Bad Element Type");
        return NULL;
        }
    }
}

So it looks they've forgotten to fix it.

like image 548
IS4 Avatar asked Nov 28 '14 20:11

IS4


1 Answers

I have no real idea what you are asking and why you think there is anything wrong. (fnptr)* is the type name of a pointer to an unmanaged function pointer. That it gets special treatment in the CLR is indeed odd, I suspect it is an archeological artifact. Dating back to a time before .NET and before delegates were invented. The CLR started life as the "universal runtime" in Project 42, a failed project before .NET.

Maybe some C++/CLI code to demonstrate how to generate one is useful, shows you how to create it:

#include "stdafx.h"

using namespace System;

typedef void (*functionPointer)(int);

ref class Example {
public:
    functionPointer* fp;
};

int main(array<System::String ^> ^args)
{
    auto field = Example::typeid->GetField("fp");
    auto name = field->FieldType->FullName; 
    Console::WriteLine(name);
    return 0;
}

Output: (fnptr)*

like image 132
2 revs Avatar answered Nov 15 '22 20:11

2 revs