Implementation principle of the getdelegateforfunctionpointer function in. NET 2.0 [draft]

Source: Internet
Author: User
Tags mscorlib

Junfeng Zhang'sArticle, What is new in. NET Framework 2.0 (7) --- marshal. getdelegateforfunctionpointer, describes how to use marshal. getdelegateforfunctionpointer in. NET 2.0 to generate delegate directly from the imported function pointer. This function can greatly reduce users' notes and make InterOP operations more natural. Examples in this articleCodeAs follows:

Using system. runtime. interopservices;
Using system;

Public class testclass
{
Public static void main (string [] ARGs)
{
Intptr USER32 = loadlibrary ("user32.dll ");
Intptr procaddr = getprocaddress (USER32, "messageboxw ");

Console. In. Readline ();

Mymessagebox mbx = (mymessagebox) Marshal. getdelegateforfunctionpointer (procaddr, typeof (mymessagebox ));
Mbx (intptr. Zero, "Hello, world", "a test run", 0 );
}

Internal delegate int mymessagebox (intptr hwnd, [financialas (unmanagedtype. lpwstr)] string text, [financialas (unmanagedtype. lpwstr)] string caption, int type );

[Dllimport ("kernel32.dll")]
Internal static extern intptr loadlibrary (string dllname );

[Dllimport ("kernel32.dll")]
Internal static extern intptr getprocaddress (intptr hmodule, string procname );
}

This feature is powerful, but the implementation code is very simple. We can see the following implementation through ildasm:

. Method public hidebysig static void main (string [] ARGs) cel managed
{
Il_0000: ldstr "user32.dll"
Il_0005: Call native int testclass: loadlibrary (string)
Il_000a: stloc.0

Il_000b: ldloc.0
Il_000c: ldstr "messageboxw"
Il_0011: Call native int testclass: getprocaddress (native int,
String)
Il_0016: stloc.1

Il_0022: ldloc.1
Il_0023: ldtoken testclass/mymessagebox
Il_0028: call class [mscorlib] system. Type [mscorlib] system. Type: gettypefromhandle (valuetype [mscorlib] system. runtimetypehandle)
Il_002d: call class [mscorlib] system. Delegate [mscorlib] system. runtime. interopservices. Marshal: getdelegateforfunctionpointer (native int,
Class [mscorlib] system. type)
Il_0032: castclass testclass/mymessagebox
Il_0037: stloc.2

Il_0038: ldloc.2
Il_0039: lds1_native int [mscorlib] system. intptr: Zero
Il_003e: ldstr "Hello, world"
Il_0043: ldstr "a test run"
Il_0048: LDC. i4.0
Il_0049: callvirt instance int32 testclass/mymessagebox: invoke (native int,
String,
String,
Int32)
Il_004e: Pop
Il_004f: Ret
} // End of method testclass: Main

In mscorlib. dll, the Marshal: getdelegateforfunctionpointer function is actually completed through a native function:

[Suppressunmanagedcodesecurity]
Public abstract sealed class implements al
{
[Securitypermission (securityaction. linkdemand, flags = securitypermissionflag. unmanagedcode)]
Public static delegate getdelegateforfunctionpointer (intptr, type T)
{
If (PTR = intptr. Zero) throw new argumentnullexception ("PTR ");

If (t = NULL) throw new argumentnullexception ("T ");

If (! (T is runtimetype) throw new argumentexception (environment. getresourcestring ("argument_mustberuntimetype"), "T ");

Type type1 = T. basetype;

If (type1 = NULL) | (type1! = Typeof (delegate) & (type1! = Typeof (multicastdelegate ))))
Throw new argumentexception (environment. getresourcestring ("arg_mustbedelegate"), "T ");

Return marshal. getdelegateforfunctionpointernal (PTR, t );
}

[Methodimpl (methodimploptions. internalcall)]
Internal static delegate getdelegateforfunctionpointerinternal (intptr, type T );

}

The specific implementation of the marshal. getdelegateforfunctionpointer function is completed in marshalnative: getdelegateforfunctionpointernal in mscorwks. dll. The pseudocode is as follows:

Objectref implements alnative: getdelegateforfunctionpointernal (lpvoid pcallback, typehandle * type)
{
Helper_method_frame_begin_2 (type, null );

If (getthread ()-> m_state & ts_abortrequested = ts_abortrequested)
Thread: handlethreadabort ();

Objectref OBJ = comdelegate: converttodelegate (pcallback, type-> getmethodtable ());

If (getthread ()-> m_state & ts_abortinitiated = ts_abortinitiated)
Thread: handlethreadabort ();

Return OBJ;
}

In addition to stack protection and thread interruption processing at the beginning and end, financialnative: getdelegateforfunctionpointerinternal actually transfers most of the work to comdelegate: converttodelegate .. The comdelegate: converttodelegate function in Net Framework 2.0 is much more complex than the implementation in the rotor. In rotor, this function only needs to handle the callback pointer that has been processed by thunk, and directly throws a parameter error exception to the invalid pointer.

// Check whether the PTR pointing function entry has been processed by thunk.
// If yes, the actual endpoint address after processing is returned; otherwise, null is returned.
//
// VM \ i386 \ cgenx86.cpp: 4642
//
Umentrythunk * umentrythunk: Decode (lpvoid pcallback)
{
If (* (byte *) pcallback )! = 0xb8 |
(Size_t) pcallback) & 3 )! = 2 ){
Return NULL;
}
Return * (umentrythunk **) (1 + (byte *) pcallback );
}

// Events als an unmanaged callback to delegate
//
// VM \ comdelegate. cpp: 500
//
Objectref comdelegate: converttodelegate (lpvoid pcallback)
{
Throwscomplusexception ();

If (! Pcallback ){
Return NULL;
}

Umentrythunk * pumentrythunk = umentrythunk: Decode (pcallback );
If (! Pumentrythunk ){
Complusthrow (kargumentexception, ids_ee_notadelegate );
}
Return objectfromhandle (pumentrythunk-> getobjecthandle ());
}

In. NET 2.0, the comdelegate: converttodelegate function is relatively complex. You also need to handle unmanaged function pointers not processed by thunk. The pseudocode of the general process is as follows:

Objectref comdelegate: converttodelegate (lpvoid pcallback, methodtable * mttype)
{
If (PTR = NULL) return NULL;

If (g_pmdastaticheap.m_pmda = NULL)
{
// Initialize and process manageddebuggingassistants.
}

// Check whether the PTR pointing function entry has been processed by thunk.
// If yes, the actual endpoint address after processing is returned; otherwise, null is returned.
Umentrythunk * thunk = umentrythunk: Decode (pcallback );

If (Thunk)
{
// Find whether the pointer has been processed in the globally unique function pointer to the delegate cache hashmap
Delegate * D = s_pdelegatetofptrhash.lookupvalue (Thunk, null );

If (D! =-1) return D;
}

// Check whether the delegate has been generated by JIT.
Methoddesc * MD = finddelegateinvokemethod (mttype-> m_peeclass );

If (MD = NULL)
{
// Use the stublinkercpu class to construct the method body through the computedllimportstub Function
}

// For generic classes, use the creategenericdllimportstubfordelegate function for processing.

// Whether to enable global security settings
If (Security: s_dwglobalsettings & corsetting_security_off = 0)
{
Module * mod = mttype-> getmodule ();

Pefile * file = mod-> getpefile ();

Imdinternalimport * imp = file-> getmdimport ();

If (security of the input file section)
{
Declactioninfo * act = Security: detectdeclactions (MD, declsec_unmngd_access_demand );

If (ACT)
{
// Use stublinkercpu: emitsecurityinterceptorstub and other methods to add the security detection code
}
}
}

_ Unchecked_objectref oref;

Setobjectreferenceunchecked (& oref, mttype-> allocate ());

return unchecked_objectref_to_objectref (ORET);
}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.