Quantcast
Channel: Questions in topic: "dllimport"
Viewing all articles
Browse latest Browse all 160

C# DLL calling functions from native DLL

$
0
0
Hello. I've developed a C# dll (let's call it WrapperClass) which exports a static class to wrap some functions from a native dll (let's call it NativeClass) using the [DllImport][1] attribute. So WrapperClass will have something like the following: namespace Wrapper { public static class WrapperClass { [DllImport("NativeClass.dll", CallingConvention = CallingConvention.Cdecl] extern static int NativeFunction (); public static int WrapperFunction() { return NativeFunction(); } } } Everything works fine but I'd like to be able to programmatically find the NativeClass dll rather than keeping it in the same runtime directory as the game. It is a dll which will be installed and maintained by an external process, so the path to it will depend on where the user installs it. To do this I turned to the registry, since the external installer writes to it. However it seems calls to [Microsoft.Win32.Registry.GetValue][2] only ever return null from within Unity, regardless of if it's inside of a Mono script or in my C# dll. I tried to work around this, by creating a second native dll (let's call it RegGetter) for the express purpose of retrieving registry values, loading RegGetter itself from within WrapperClass using a hardcoded position in the Assets directory. WrapperClass has a static constructor, and in this constructor I save the path RegGetter produces to a class level variable before calling [AddDllDirectory][6] to include the path in [DllImport][1]'s search path. So now WrapperClass looks like this: namespace Wrapper { public static class WrapperClass { [DllImport("/Assets/Product/DLLs/RegGetter.dll", CallingConvention = CallingConvention.Cdecl] extern unsafe static sbyte* GetPathFromReg(); public static String SearchPath = ""; static WrapperClass() { unsafe { String SearchPath = new String(GetPathFromReg()); AddDllDirectory(SearchPath); } } [DllImport("NativeClass.dll", CallingConvention = CallingConvention.Cdecl] extern static int NativeFunction (); public static int WrapperFunction() { return NativeFunction(); } } } So far, so good. I have a standalone tester C# program which has RegGetter successfully finding the path and WrapperClass successfully importing NativeClass and calling functions on it. However, in Unity I'm experiencing the following curious behavior: Unity will display a [DllNotFound][4] exception looking for NativeClass in the log and crash gracelessly on trying to access it UNLESS I access some data from the WrapperClass before trying to access NativeClass. Which data it is is inconsequential. I can put the exact same code inside of the WrapperClass function (e.g. int tmp = SomeClassLevelInterger), to no effect - Unity needs to access it. In other words, this works: using UnityEngine; using Wrapper; public class WrapperConsumer: MonoBehaviour { string tmp = Wrapper.SearchPath; int tmp1 = Wrapper.WrapperFunction(); } This doesnt: using UnityEngine; using Wrapper; public class WrapperConsumer: MonoBehaviour { int tmp1 = Wrapper.WrapperFunction(); } I've been banging my head against this for two days straight and am at a loss at how to proceed. Am I running into some kind of static constructor nonsense? Is there a freaking easier way to get into the Registry from within Unity? Two options that are not available are 1) leaving the pointless statements in and 2) upgrading to pro to forgo the wrapper altogether - we're trying to build something to put on the Asset store that free users can use (and understand). [1]: http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute(v=vs.110).aspx [2]: http://msdn.microsoft.com/en-us/library/microsoft.win32.registry.getvalue(v=vs.110).aspx [4]: http://msdn.microsoft.com/en-us/library/vstudio/system.dllnotfoundexception(v=vs.100).aspx [6]: AddDllDirectory

Viewing all articles
Browse latest Browse all 160

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>