Missing Members
To support mcs I previously added some limited support for missing members. This has now been extended substantially to allow full fidelity reading/writing of assemblies. Normally IKVM.Reflection behaves like System.Reflection in how it tries to resolve member and assembly references, but now it is possible to customize this to enable reading a module without resolving any dependencies.
Roundtripping
To test this version of IKVM.Reflection, I've roundtripped 1758 (non-C++/CLI) modules from the CLR GAC plus the Mono 2.10 directories on my system. Roundtripping here means reading in the module and writing it back out. The original module and resulting module are both disassembled with ildasm and the resulting IL files compared (after going through two dozen regex replacements to filter out some trivial differences).
The code I used for the roundtripping is an (d)evolution of the linker prototype code. It is available here. Note that it is very far from production quality, but does make for a good case study in how to use the advanced IKVM.Reflection functionality.
Unmanaged Exports
A cool CLR feature is the ability to export static managed methods as unmanaged DLL exports. The only languages that support this, AFAIK, are C++/CLI and ILASM, but now you easily do it with IKVM.Reflection as well. Below is a Hello World example. Note that while this example exports a global method, you can export any static method. Note also that the string passed in must be ASCII, may be null and that the ordinal must be a 16 bit value that is unique (in the scope of the module).
using IKVM.Reflection;
using IKVM.Reflection.Emit;
class Demo
{
static void Main()
{
var universe = new Universe();
var name = new AssemblyName("ExportDemo");
var ab = universe.DefineDynamicAssembly(name, AssemblyBuilderAccess.Save);
var modb = ab.DefineDynamicModule("ExportDemo", "ExportDemo.dll");
var mb = modb.DefineGlobalMethod("HelloWorld", MethodAttributes.Static, null, null);
var ilgen = mb.GetILGenerator();
ilgen.EmitWriteLine("Hello World");
ilgen.Emit(OpCodes.Ret);
mb.__AddUnmanagedExport("HelloWorld", 1);
modb.CreateGlobalFunctions();
ab.Save("ExportDemo.dll", PortableExecutableKinds.Required32Bit, ImageFileMachine.I386);
}
}
The resulting ExportDemo.dll can now be called from native code in the usual ways, for example:
typedef void (__stdcall * PROC)();
HMODULE hmod = LoadLibrary(L"ExportDemo.dll");
PROC proc = (PROC)GetProcAddress(hmod, "HelloWorld");
proc();
Creating unmanaged exports is supported for I386 and AMD64. Itanium (IA64) support has not been implemented.
What's Missing
It should now be possible to write an ILDASM clone using IKVM.Reflection, however to be able to write ILASM there are still a couple of things missing:
- Function pointers (used by C++/CLI).
- API to create missing type.
- Preserving interleaved modopt/modreq ordering.
- Various C++/CLI quirks (e.g. custom modifiers on local variable signatures).
- Ability to set file alignment.
Changes:
- Added support for using missing members in emitted assembly.
- If you build IKVM.Reflection with the STABLE_SORT symbol defined, all metadata sorting will be done in a stable way, thus retaining the order in which the items are defined.
Read more: IKVM.NET Weblog
0 comments:
Post a Comment