I have found libraries that would export managed code as unmanaged so you can use it by unmanaged languages like C/C++. But I did not find anything that would explain how it's done (which is what I'm more interested in)
I'm looking for information, tutorials, articles, code sources or anything that could help me to understand how this works
On a side note, if you found some hooks/detours resources in your bookmarks I would love to read them too :)
Thanks in advance and have a wonderful day.
I'll post an answer, collecting the comments I wrote.
The most famous library for doing it is (as today) the UnmanagedExports. Its page is https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports . Sadly there is no source code available, but it is licensed under the MIT license, so it is probably ok to use IlSpy to take a look at it.
There are a few references about how it is done.
There are at least two articles on Codeproject: How to Automate Exporting .NET Function to Unmanaged Programs that seems to be for .NET 2.0 and Unmanaged code can wrap managed methods that sadly is about .NET 1.1.
There is some reference in the book Expert .NET 2.0 IL Assembler around page 384.
You can surely do another thing: observe what UnmanagedExports
do: UnmanagedExports
in the end is "composed" of two parts: an assembly RGiesecke.DllExport.Metadata.dll
containing a "stupid" attribute DllExportAttribute
plus two assemblies (that on my computer the nuget installs in the packages\UnmanagedExports.1.2.6\tools folder): RGiesecke.DllExport.dll
and RGiesecke.DllExport.MSBuild.dll
. The nuget installer of UnmanagedExports
adds some lines to the csproj, like:
<Import Project="packages/UnmanagedExports.1.2.6/tools/RGiesecke.DllExport.targets" Condition="Exists('packages/UnmanagedExports.1.2.6/tools/RGiesecke.DllExport.targets')" />
that cause the execution of the class RGiesecke.DllExport.MSBuild.DllExportAppDomainIsolatedTask
contained in the assembly RGiesecke.DllExport.MSBuild.dll
. This class, using This program simply calls Mono.Cecil
, rewrites the assembly doing some code reweaving. ildasm
to generate the il code source, modifies the il code source and then uses ilasm
to generate back the "original" .dll/.exe . So simply put, generate two assemblies, one with the <Import />
and another with the <Import />
commented out, then do a
ildasm yourdll.dll /out=source.il
of both files and compare it with your favourite file comparer.
Another interesting link is here. There are some comments to how to make it work on x64.
If I had to build something similar, I would probably try to integrate it to Fody. In this way I would have the whole post-build Task for free (because it is done by Fody)
Can't be done with Mono.Cecil
... Mono.Cecil
can't write mixed-mode assemblies (that are needed to export symbols). You have to use the same "trick" used by UnmanagedExports (and by the various other examples)... Generate the IL file, modify it (it is a text file in a fixed format... quite easy to modify), re-generate the .dll/.exe .