Mona the Monad
Mona the Monad

Reputation: 2455

Using C# DLL in managed C++ (command line)

I've looked over a few questions with a title just like this one, but they either do not talk about command line, or don't seem to work for me for some reason. From what I have read, it seemed as if I could "simply" do the following:

The dummy code (C#):

using System;

public static class Foo {
    public static void Bar() {
        Console.WriteLine("o3o");
    }
}

More dummy code (Visual C++):

#using <test.dll>

int main() {
    Foo::Bar();
    return 0;
}

C# DLL compiled using:

csc /out:test.dll /t:library src\cs\Foo.cs

Visual C++ object file compiled using:

cl /Ox /clr /AI. /c src\vc\test.cpp

Executable compiled using:

link /out:test.exe test.obj

The following exception is thrown upon running the executable:

Unhandled Exception: System.TypeLoadException: Could not load type 'Foo' from assembly 'test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
   at main()
   at mainCRTStartup()

I have a strong feeling that I was supposed to also reference the DLL in the link phase, but I couldn't find any option for linking a DLL similar to GCC's -l option. Attempting to pass the DLL along with the .obj to link causes it to tell me that linking assemblies is not supported. Interestingly, though, if I build a .netmodule instead of a DLL, i.e. by:

csc /out:test.dll /t:module src\cs\Foo.cs

and changing the #using directive to

#using <test.netmodule>

the executable runs without error. This feels a bit weird, for I don't think anybody packages code in .netmodules (what are .netmodules, anyway?).

Upvotes: 1

Views: 1100

Answers (1)

Lucas Trzesniewski
Lucas Trzesniewski

Reputation: 51430

All of your steps should have worked, but one very simple issue is preventing your program from running.

Namely: Your C# DLL assembly name is test, and your C++/CLI exe assembly has the same name. They both have the same identity.

So when looking for Foo::Bar in the test assembly, the loader first checks if the assembly is loaded in the AppDomain. It is - it's your C++/CLI exe, and you can't have several assemblies with the same identity loaded simultaneously within the same AppDomain. Your C# dll wasn't even given a try.

Just change either one of them and everything will work fine:

link /out:test2.exe test.obj

As for what's a .netmodule, it's the format used for linking managed code statically, that's why you managed to link your C# code with your C++/CLI code without issues. It's roughly the equivalent of a .lib file for managed code.
And you're right, it's not used very often.

Upvotes: 3

Related Questions