Using a "pure" .NET library generated from C++/clr in WebPlayer

Hi All,

This question is mainly about finding out why this does not work rather than any benefits of using C++/clr over C#.

I am attempting to get a purely IL DLL assembly generated from C++/clr code to run correctly in a Unity WebPlayer project.

Basically I am using the 2005 Visual C++ compiler in the following way:

> cl /clr:safe /LD *.cpp

This generates a .DLL that .NET Reflector and ildasm tells me is identical to one I compiled with the 2005 C# compiler.
Most importantly, the Target Runtime is confirmed to be v2.0.50727. This DLL can also work in Silverlight, again confirming that there is no native code in it (mainly due to the /clr:safe flag).

I am using the 2005 version of cl.exe so to ensure that the target framework is 2.0 and not higher.

It runs great in Unity for all exporters apart from the WebPlayer where it comes up with Loading script assembly “Assets/Libraries/Test.dll” failed. The editor log includes as follows.

Non platform assembly: C:\Users\kpedersen\Documents\NetSandbox\Assets\Libraries\Test.dll (this message is harmless)
Failed loading assembly Assets/Libraries/Test.dll
Loading script assembly "Assets/Libraries/Test.dll" failed!

Again, when using the C# DLL as a direct substitute, this just works.

Additional things I have tried include:

cl /clr:safe /clr:nostdlib /d1clr:nomscorlib /FU"C:\Program Files (x86)\Unity\Editor\Data\Mono\lib\mono\unity_web\mscorlib.dll"
cl /clr:safe /clr:nostdlib /d1clr:nomscorlib /FU"C:\Program Files (x86)\Unity\Editor\Data\Mono\lib\mono\unity\mscorlib.dll"

Though I think this is going in the wrong direction because the C# version of the DLL does not need to use the mscorlib from the Unity distribution.

This is just annoying because I think the IL code is fine, I think there must be some kind of metadata embedded into the .DLL that Unity’s web player build system is rejecting.

Any suggestions would be greatly appreciated.

Karsten

Could you explain what the code does? Here is a compatibility table that shows what is supported in the web player, just in case you are not meeting those requirements:

I have made two test DLLs using the bare minimum of functionality just to test the loading.
The C++/clr does nothing different from the control test (The working C# DLL).

So I am quite sure that I am not using any language features that are not supported by the web player. Infact, when I use .NET reflector to decompile my C++/clr DLL into C#, I get back 100% identical code to what is in my C# version of the test DLL.

C# (Test.cs)

using UnityEngine;

public class Test
{
  public void DoSomething()
  {
    Debug.Log("Test");
  }
}

C++/clr (Test.h)

using namespace UnityEngine;

public ref class Test
{
public:
  void DoSomething()
  {
    Debug::Log("Test");
  }
}

Both reference the same UnityEngine.dll (for UnityEngine.Debug) and yet the C# dll is fine and the C++/clr dll fails to be loaded by Unity.

I have made sure not to use C++/clr specific language features either (like auto_handle, RAII or destructors) because those generate very complex IL. So both DLLs currently provide identical IL and nothing that the restricted subset web player runtime cannot handle.

So just to summarize…

Both C++/clr and C# DLLs work fine when Unity is in standalone player mode.
Only the C# DLL works when Unity is in web player mode.

Ok, I got this figured out (more like a workaround).

I was comparing the output IL of the two DLLs using ILdasm. I noticed they were almost exactly the same. Therefore I tried to simply compile the IL disassembly of the C++ library back to a DLL via ILasm.
Interestingly this worked great in Unity WebPlayer.

Therefor, my build system now entails a system like…

call cl /clr:safe /LD *.cpp /FU"C:\Program Files (x86)\Unity\Editor\Data\Managed\UnityEngine.dll" /Fe"_ClrTest.dll"
ildasm _ClrTest.dll /out:_ClrTest.il
ilasm /dll /output:"ClrTest.dll" _ClrTest.il

Now what is really cool is that the parts of C++/clr that generate very complex IL still work (including the awesome auto_handle!) so it is now possible to take advantage of a language implicitly supporting deterministic cleanup in Unity!

The above technique should also work for other compilers producing pure IL (i.e IronPython and A# (Ada))

Thanks for sharing the solution!