Platform-dependent compilation of C# DLL - c#

I'm trying to set up a bunch of managed C# dlls to work inside Unity3D, but I'm struggling to get that done:
Imagine having C# managed Platform.dll for platform A and Platform.dll for platform B.
Now I want to build a C# managed dll, say Core.dll, that depends on Platform.dll, but does itself not have any Platform-dependent code in it. I thought that it should be possible to build a single managed C# dll, which looks up the right Platform.dll at runtime (given that only one of the Platform.dlls is enabled).
Is this possible and if yes how? Or do I have to stick with different Core.dlls which are again platform-dependent, because the underlying Platform.dll is?

If you setup your dlls in Unity correctly (i.e. in-/exclude them for the relevant platforms), Unity should only include one Platform.dll into the build. If Core.dll doesn't use any interface that is only present in a subset of your Platform.dlls, it should work fine. Otherwise you'll get an exception when trying to build the Unity project for any platform where the respective Platform.dll is incompatible with the Core.dll.

Related

Expose a class in my unity game to a DLL that is loaded at runtime by the same game?

I would like to expose some objects and classes for DLL plugins for a Unity 5 game.
The plugins(DLL/.net assemblies) are loaded at runtime later. But these DLLs need to access classes and objects already created by the main game.
I use the Assembly.LoadFrom() method to load the plugins DLLs: Use assembly class without the assembly object
Since there does not seem to be any header files in C# as in C++, how do I expose the game program's(.exe) classes to plugins?
Reference UnityEngine.dll and your Assembly-CSharp.dll
Whenever the Unity editor compiles C# code, it most often generates one DLL (it generates more if you're using UnityScript, for example) - that DLL is called Assembly-CSharp.dll, and it gets stored in the Library/ScriptAssemblies folder of your Project files in the Editor.
Just like any other DLL, you need to reference it. As it uses the Unity API, you'll need to reference UnityEngine.dll too, which can be found in, for example, c:/Program Files/Unity/Editor/Data/PlaybackEngines/androidplayer/Managed/UnityEngine.dll
For most platforms, UnityEngine.dll is the same (i.e. the above is using the one which gets compiled into an Android build), so it doesn't matter too much which one you use, however, you should use the one for your target platform.
Platforms this doesn't work for
As a side note, keep in mind that DLL loading doesn't work on a variety of platforms - iOS and WebGL as well known examples (because they don't run .NET IL at all).
After a build has been made
You'll want to make sure you reference the correct DLL after a build has been made. With a Windows standalone, for example, you'll easily find it again within the built *-Data folder. On android, it can be extracted from the APK too.
In Summary
In general, when you build the game, you'll need to recompile your DLL (referencing the latest Assembly-CSharp.dll).
As a side note, you can also precompile your whole codebase into a DLL and use that in your project, but keep in mind that this breaks #preprocessor directives so you have to rebuild it when you swap platforms. However, at least you have full control over when that DLL rebuilds (and as a result, when your referencing ones need to).

Cannot find type System.ApplicationException in module CommonLanguageRuntimeLibrary

I ran a 3rd party Android library through CodenameOne's version of IKVM and successfully imported the output .dll as a reference to my UWP app in Visual Studio. Upon trying to compile the project I get a single build error:
(from the Error List window)
Cannot find type System.ApplicationException in module CommonLanguageRuntimeLibrary
(from the Output window)
Program Files (x86)\MSBuild\Microsoft\WindowsXaml\v14.0\8.2\Microsoft.Windows.UI.Xaml.Common.targets(352,5): Xaml Internal Error error WMC9999: Cannot find type System.ApplicationException in module CommonLanguageRuntimeLibrary.
From what I've read System.ApplicationException is depreciated in .Net for UWP and instead you're supposed to just use System.Exception
I don't know how to work around and/or correct this since it's coming from a library and not my own code.
Thanks in advance.
Our port of IKVM isn't quite turn-key. IKVM is compiled using .Net 2.0, and some things (e.g. reflection stuff, some date things, threads, etc...) are factored out using interfaces that need to be included in the UWP project that uses it.
If you haven't implemented these interfaces, or you are using code paths that we don't need for CN1, then you may be embarking of parts of the JDK or IKVM runtime that use .Net 2.0 classes (e.g. this exception).
Currently there are only two interfaces that need to be implemented in your UWP project:
RuntimeReflectionHelper.
NativeThreadHelper
You can see, in the CN1 port how they are initialized here
Here are the implementations for the RuntimeReflectionHelper and NativeThreadHelper
Implementing these inside the UWP project gets around fact that IKVM is compiled for .Net 2.0, so that these implementations can use UWP APIs directly.
Even with this, you will probably run into issues. This port of IKVM is evolving along side the CN1 port, and it is really only tested for our uses cases. Some common methods may be unimplemented if we didn't require them for CN1.
Some other limitations you should be aware:
The IKVM-compiled code in a project needs to be part of a single .dll file if you want it to refer to each other. E.g. If you compile two libraries, lib1.jar and lib2.jar to lib1.dll and lib2.dll, then code from lib1 can't references classes from lib2 and vice versa. In CN1 I bundle all .class files into a single .jar before running it through IKVM so that isn't an issue for us (hence why I didn't spend much time trying to fix it).
If your goal is to publish to the Windows store, there is currently a bug in their DotNetNative toolchain that causes it to choke on synchronized methods that include try/catch blocks. This will likely be fixed by Microsoft in future releases, but I get around this by running a pre-transformation on all classes to convert all such methods into a form that is acceptable to their native toolchain. Here the part of our ANT task that applies this preprocessing. Here is the class preprocessor project for the ANT task that this uses to do the actual preprocessing.
As I said before, expect to run into difficulties if you're exploring outside the trails that have already been blazed.

How can I add a reference to a project of a Windows native DLL?

I'm trying to add Windows/System32/Shell32.dll DLL to my project. The issue is, it copies the reference to the directory! Since this is a windows file, it shouldn't have to come with me if I were to deploy my application.
I have tried stopping it from copying to the directory, tried looking for how to embed the resource in the application and even added reference paths to System32. It seems so much more challenging than the program just using the local DLL from the system...
What can I do?
Shell32.dll is a COM component. You should not get a copy of it in your project. What you get instead is Interop.Shell32.dll. Which is a .NET assembly, not a copy of Shell32.dll. It contains the COM interface and class declarations, converted from the type library definition inside Shell32.dll to friendly .NET declarations that the CLR knows how to easily handle.
This is an optimization, it avoids having to make the conversion at runtime. Which is expensive, subject to various options (check the MSDN docs for Tlbimp.exe) and may easily fail because there is no general requirement that the type library is also available on the target machine.
You must deploy Interop.Shell32.dll to the target machine, just like you do with any .NET class libraries you'd use.
Do note that this interop library is no longer needed on .NET 4 and VS2010. Which acquired the "Embed Interop Types" feature. In other words, instead of keeping the interop types in a separate assembly, the C# and VB.NET compilers can now embed them in your program. Very highly recommended, just set the option to True in the Properties window view of the Shell32 reference.

How do I add a reference to an assembly that wasn't built with the Silverlight Runtime?

I am looking for a possible solution where I can add ShapeMap.dll as a reference,
but when I try to add the reference I get an error stating:
You can't add reference to ShapeMap.dll, as it was not build against the Silverlight runtime. Silverlight projects will only work with Silverlight Assemblies"
What do I do now?
While Silverlight code may look and smell like good old .NET-backed logic, the runtime for Silverlight is different from that supporting regular .NET applications.
It is useful to think of the Silverlight runtime as a subset of the .NET runtime: Silverlight is meant to run in a "sandbox" whereby many the unsafe features such as direct access to the file system are not allowed.
For this reason, one can only add Silverlight assemblies to a Silverlight project.
The error you're getting is therefore as said: the version of ShapeMap.dll you have wasn't build for Silverlight runtime.
There are two ways out of this situation:
find or build a Silverlight-backed version of the DLL
somehow refactor the Silverlight application so that it leverages the features of the DLL by way of WebServices (if that makes sense, for the name ShapeMap.dll indicates that this may deal with UI objects which are hard/impossible to deal with remotely)
To get a Silverlight-backed version of the DLL:
First choice: It may just be that you can get the binary of the Silverlight version of the assembly where you found the .NET version.
Second choice: it may be that you can get the the source code of the [.NET targeting] DLL.
If so you can try -and I stress "TRY"- to make a Silverlight assembly out of it. The problem may be that the source code uses .NET-only idioms/API calls and you'll then need to convert these; several just .NET-to-SL "gotchas" can easily be converted, others are absolute roadblocks (eg. direct access to the file system, registry etc.), although, it may be possible to merely comment-out the offending sections of the code, if, somehow the Silverlight was not going to use the underlying features of the DLL.
Now... for sake of full disclosure...
there are a few techniques which allow "fooling" Visual Studio so that .NET assembly be accepted within a SilverLight project. See for example "Reusing .NET assemblies in Silverlight". Beware, however, that while very insightful as to the nature of the .NET and Silverlight runtimes, and possibly useful in some cases, these techniques are undocumented and, more importantly, depending on the subset of .NET API used by the DLL, may merely allow to get over over the build-time blocking, to fall into various run-time errors (when/if the application makes calls into the DLL to methods which in turn invoke .NET-only methods of the runtime).
If you have access to the source files for that assembly (dll), create a new Silverlight Class Library project and add all the existing source files to your new project. Then attempt to build the project. Depending on the amount of dependencies you may succeed in building a silverlight compatible version of the assembly.
If you don't have the source code, then sorry you're out of luck.
Silverlight works in a "subset" of the .net framework, some stuff is organized differently and works not like a regular WPF application (like that everything needs to be async in order to keep the UI responsive). You can see it as a "protected" .net environment, and therefor you may not reference or use non-silverlight dll's.
Like the previous answer states, use the source code and copy paste it into a SL library project, compile, and use that.

How would i use a C++/CLI dll that wraps native code with multiple dependent libraries in C#?

I am wondering how I would go about correctly setting up a C++/CLI library that wraps native c++ code that has several dependencies. I have tried both statically and dynamically linking the native library to its dependent libraries with no luck.
The Managed C++/CLI dll builds just fine and can be added as a reference to a C# project. However when I attempt to use any of the defined classes i receive either a BadImageFormatException or FileNotFoundException depending how i linked. I believe I need to specify the dependent libraries in the CLI library so it is loaded in the manifest but I am unsure of the process. Also because i know it will come up, I have verified that all of the libraries involved are built on the x86 architecture.
I figured out the problem and everything is working correctly now. It was a combination of several incorrect things all happening together.
If anyone has the same issue, I resolved it by setting up the following:
1) The Boost libraries that were referenced (specifically boost_thread) needed to be compiled with BOOST_THREAD_USE_DLL preprocessor (other boost libraries may need BOOST_ALL_DYN_LINK to just dynamically link everything). This is apparently a common issue.
2) I verified that all dependencies were in system Path (like R Ubben reiterated)
3) I used the DependencyWalker (depends.exe from sourceforge) to analyze my compiled managed DLL. It turned out that the libpq.lib library being used actually referenced additional DLLs that were not included in the lib folder but in the bin folder. So that need to be added to the Path.
4) Part of my wrapper was using the #include header for lists. This forced my library to link against 2.0 framework dependent libraries. This was not compatible with my 4.0 client targeted C# application. This was only made known by parsing through the Warnings from compiling (previously hidden due to C++ generating too many..foolish i know). However this was resulting in a System.BadImageFormateException being thrown despite everything targeting the same x86 architecture.
Hope that helps anyone else who has the same problem. The BadImageFormateException and FileNotFoundException were entirly too vague and unhelpful.
You should make the C++ dll in release mode and use extern "C" for public static things.
I have gotten that error when the dependent libraries were not in the path. The wrapper library is found because of the reference, but the reference does not also take care of the dependent libraries. Try placing them explicitly where the program is executing.

Categories

Resources