11

I've been trying to use the extension "Unmanaged Exports" by Robert Giesecke in a Visual Studio 2010 pro/C# project. Yet, I can't make it work - when I check the compiled DLL for exports, the viewer (http://www.nirsoft.net/utils/dll_export_viewer.html) always comes up empty, no exports seem to be defined at all.

I have all but copied the example and set build/config manager/active platform to x86. Can I somehow check if the MSBuild task that does all the magic is actually run or not? What should the project file contain (it seems to be suspiciously empty to me?)

svick
  • 236,525
  • 50
  • 385
  • 514
user2489608
  • 119
  • 1
  • 1
  • 3
  • 1
    You can also use http://www.dependencywalker.com/ to view the exported functions. I've used the above approach before, but it's hard to tell what might be going wrong without more information. Probably will need to see the entire project to debug what is going wrong. – Joel Lucsy Jun 15 '13 at 21:37

2 Answers2

25

I would recommend you do this the documented way instead of relying on a undocumented hack from an author who doesn't provide support. Let's do it with an example:

namespace Publics {
    public class Class1 {
        public static void Run() { 
            // Stuff...
        }
    }
}

Add a new C++/CLI class library to your project. Right-click the solution, Add, New Project. Open the "Other Languages" node, Visual C++, CLR, and pick the "Class Library" project template. Right-click the new project, Properties, Common Properties, Framework and References, click the Add New Reference button. From the Projects tab, pick the C# project whose method(s) you want to export.

Delete the pre-generated empty class with the //TODO comment and write this kind of code:

extern "C" __declspec(dllexport)
void __stdcall Example() 
{
    Publics::Class1::Run();
}

Build your solution. Check that the Example function got exported by running dumpbin.exe /exports on the DLL. You should see something similar to this:

      1    0 00001020 _Example@0 = _Example@0

Beyond the name and the calling convention, you now also have lots of choices to tweak the exported function. If you want to export an instance method instead of a static method you could write the function like this for example:

extern "C" __declspec(dllexport)
void __stdcall Example() 
{
    Publics::Class1^ obj = gcnew Publics::Class1;
    obj->Run();
}

Etcetera, some familiarity with the C++/CLI language is required if you are going to make this elaborate. Last but not least, you are also likely to find out what went wrong in your original attempt to make Giesecke's IL rewriter work. It otherwise uses the exact same technique that the C++/CLI compiler uses to export the managed method.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • 2
    +1 I really appreciate this tutorial. I learnt something. I always assumed that UnmanagedExports was performing some kind of black magic. Very nice to learn otherwise. – David Heffernan Jun 16 '13 at 09:57
  • does this work in mono? – denfromufa Jan 20 '15 at 16:36
  • Will the function "Example()" from the mixed mode assembly/DLL created by compiling the C++/CLI class library you inserted in your post be accessible from UNmanaged code (e.g. Delphi, native C++) as if it was an usual pure unmanaged DLL? Is the CLR automatically started when unmanaged code invokes the exported function? – Niklas Peter Sep 08 '15 at 20:09
  • 1
    @HansPassant I was confused, because this article seems to use one additional layer: C# => C++/CLI => *native C++* => unmanaged client, whereas your method is: C# => C++/CLI => unmanaged client http://blogs.microsoft.co.il/sasha/2008/02/16/net-to-c-bridge/ Has your method compared to a managed COM server disadvantages except from the need to write the C++/CLI (however you will have to add some code in the unmanaged application, too, when using COM). I think the performance using C++/CLI as you suggested is better compared to COM? Yes, I will try it. – Niklas Peter Sep 08 '15 at 20:21
  • Well, that guy isn't the first one to think that it could be done automatically. God have mercy on your soul when you have to debug it. – Hans Passant Sep 08 '15 at 20:35
  • 1
    Wouldn't this result in two assemblies (one mixed and one managed)? – Ray Apr 29 '18 at 22:07
1

I've been using version 1.1.3 and see there is now a newer version with NuGet support. I just did a test with that.

Can I somehow check if the MSBuild task that does all the magic is actually run or not?

You can get more detail from MSBuild using the command line or adjust the verbosity that Visual Studio requests: Tools > Options > Project and Solutions > Build and Run > MSBuild project build output verbosity [VS 2010]. You'll probably want to reset it as soon as you are done troubleshooting.

I saw the target and task were being called but didn't see any results until I switched the project platform to x86. Then I see various, relevant log entries including Adding .vtentry:0 .export....

What should the project file contain (it seems to be suspiciously empty to me?)

There isn't much needed in the project file. NuGet does it all: A reference to the DllExport assembly and an include for the target file.

A couple things that I can think of that might be tripping you up:

  1. Make sure you are actually building the project. The Solution Build Manager can have some projects not set to build for the selected solution configuration.
  2. Make sure you are checking the right DLL. The build task writes the path into the build log. The line starts with Assembling.
Tom Blodget
  • 20,260
  • 3
  • 39
  • 72
  • was struggling around for hours... And your mentioned **point #2** was the resolution! There are so many output folders of VS containing a built `*.dll` file but all were not working (weren't exporting functions), only the one in `..\ClassLibrary1\bin\x86\Debug` actually did. Probably a beginner's mistake, but Thanks :D – Martin Schneider Nov 23 '17 at 13:46