Platform Invoke
Methods defined in a native DLL may be invoked using the PInvoke (platform invoke) functionality of the CLR. PInvoke will handle everything needed to make the call work. It will automatically switch from managed to unmanaged state and back and also handle necessary conversions. Methods that need to be called using PInvoke are marked as pinvokeimpl. In addition, the methods must have the implementation attriubtes native and unmanaged (see 11.5.4.4).
pinvokeimpl takes in parentheses the name of the DLL with any number of PInvoke attributes. After the name of the DLL, an as clause may be inserted that specifies an alias that may be used to call the method. While the name of the method must exactly match the name of the method as declared in the DLL, the alias may be used as an alternative name for the method in IL. This may be useful, since some compilers use cryptic names for methods in DLLs.
<methAttr> ::= | Description | Section |
pinvokeimpl ( <QSTRING> [as <QSTRING>] <pinvAttr>* ) | pinvokeimpl( <DLL name> [as <alias>] <attribute>*) |
|
| … |
| 11.5.4 |
A method declared with pinvokeimpl may not have a body, since it was declared to be native.
pinvokeimpl methods may be global methods as well as methods of classes. Only static methods may be pinvokeimpl. The CLR PInvoke feature does not support instance or virtual methods.
A call to a pinvokeimpl method is just like any other call to a static method.
Note: The disassembler ildasm may output pinvokeimpl declarations with no DLL name, e.g. when VC++ code is disassembled, and the assembler ilasm does accept pinvokeimpl declaration with no DLL. However, this is invalid IL and the produced code will fail to execute. PEVerify will report pinvokeimpl declarations without a specified DLL as errors.
The following grammar shows the attributes of a pinvokeimpl instruction.
<pinvAttr> ::= | Description |
ansi | ANSI character set. |
| autochar | Determine character set automatically. |
| cdecl | Standard C style call. |
| fastcall | C style fastcall. |
| lasterr | Indicates that method supports C style last error querying. |
| nomangle | Use the member name as specified – do not search for ‘A’ (ascii) or ‘W’ (widechar) variants in the Win32 DLLs |
| ole | Indicates method signature is mangled to return HRESULT, with the return value as a parameter. |
| stdcall | Standard C++ style call. |
| thiscall | The method accepts an implicit this pointer. |
| unicode | Unicode character set. |
| winapi | Pinvoke will use native call convention appropriate to target windows platform. |
Example:
The following shows the declaration of the method MessageBeep located in the Windows DLL user32.dll:
.method public static pinvokeimpl("user32.dll" cdecl) int8 MessageBeep(unsigned int32) native unmanaged {}
The above method may be called like any other static method from IL code.
1.1.1.1.1 Name Mangling in DLLs
Some compilers, like VC++, convert human readable names into cryptic names that contain additional information like types, etc. This process is called name mangling.
ilasm does not support automatic name mangling for PInvoke calls. Thus, it is important to use the exact mangled name of the method. The mangled name of the method can be obtained using the dumpbin tool applied to the DLL:
dumpbin /symbol <dllname>
The alias used with pinvokeimpl gives an opportunity to declare explicitly the unmangled name of the method.