Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to use 'libjulia.dll' in a C# application on Windows 8.1 #8931

Closed
sliekens opened this issue Nov 7, 2014 · 16 comments
Closed

Unable to use 'libjulia.dll' in a C# application on Windows 8.1 #8931

sliekens opened this issue Nov 7, 2014 · 16 comments
Assignees
Labels
system:windows Affects only Windows

Comments

@sliekens
Copy link

sliekens commented Nov 7, 2014

The documentation gave me the impression that I can use .NET P/Invokes to run Julia scripts in a .NET environment. I tried porting the embedding.c program to C#, but I always get one or more errors.

My code:

using System.Runtime.InteropServices;

class Program
{
    [DllImport("libjulia.dll")]
    public static extern void jl_init(string julia_home_dir);

    [DllImport("libjulia.dll")]
    public static extern void jl_eval_string(string str);

    static void Main(string[] args)
    {
        jl_init(null);
        jl_eval_string("print(sqrt(2.0))");
    }
}

When executed, it throws an AccessViolationException, which I believe is the .NET equivalent of a segfault.

.\Program.exe

Please submit a bug report with steps to reproduce this fault, and any error messages that follow (in their entirety). Thanks.
Exception: EXCEPTION_ACCESS_VIOLATION at 0x5a6e35f324 -- unknown function (ip: 1849029412)
unknown function (ip: 1849029412)
abstract_call_gf at inference.jl:622
unknown function (ip: 1840590556)
abstract_call at inference.jl:835
unknown function (ip: 1840590556)
abstract_eval_call at inference.jl:927
abstract_eval at inference.jl:952
unknown function (ip: 1840590556)
abstract_interpret at inference.jl:1115
unknown function (ip: 1840590556)
typeinf at inference.jl:1436
at (unknown line)
unknown function (ip: 1840590556)
typeinf_ext at inference.jl:1236
unknown function (ip: 1840590556)
unknown function (ip: 1840586610)
unknown function (ip: 1840588250)
unknown function (ip: 1840590657)
unknown function (ip: 1840641231)
unknown function (ip: 1840890118)
unknown function (ip: 1840863696)
unknown function (ip: 1840926177)
unknown function (ip: -1234565522)
unknown function (ip: -1235658528)
unknown function (ip: -1104811560)
unknown function (ip: -1104811200)
unknown function (ip: -1104811384)
unknown function (ip: -1104812144)
unknown function (ip: 1)
unknown function (ip: -879819355)
unknown function (ip: 373044544)
unknown function (ip: -1104811200)
unknown function (ip: -1235658528)
unknown function (ip: -1235658528)
unknown function (ip: -1104812144)
unknown function (ip: -1234565522)
unknown function (ip: -1104812112)
unknown function (ip: -1235658528)
unknown function (ip: -879819355)
unknown function (ip: -1102667552)
unknown function (ip: 1840926111)

Please submit a bug report with steps to reproduce this fault, and any error messages that follow (in their entirety). Thanks.
Exception: EXCEPTION_ACCESS_VIOLATION at 0x5a6e35f324 -- unknown function (ip: 1849029412)
unknown function (ip: 1840926112)

Please submit a bug report with steps to reproduce this fault, and any error messages that follow (in their entirety). Thanks.
Exception: EXCEPTION_ACCESS_VIOLATION at 0x5a6e35f324 -- unknown function (ip: 1849029412)
unknown function (ip: 1840926112)

Please submit a bug report with steps to reproduce this fault, and any error messages that follow (in their entirety). Thanks.
Exception: EXCEPTION_ACCESS_VIOLATION at 0x5a6e35f324 -- unknown function (ip: 1849029412)
unknown function (ip: 1840926112)

Please submit a bug report with steps to reproduce this fault, and any error messages that follow (in their entirety). Thanks.
Exception: EXCEPTION_ACCESS_VIOLATION at 0x5a6e35f324 -- unknown function (ip: 1849029412)
unknown function (ip: 1840926112)

Please submit a bug report with steps to reproduce this fault, and any error messages that follow (in their entirety). Thanks.
Exception: EXCEPTION_ACCESS_VIOLATION at 0x5a6e35f324 -- unknown function (ip: 1849029412)
unknown function (ip: 1840926112)

Please submit a bug report with steps to reproduce this fault, and any error messages that follow (in their entirety). Thanks.
Exception: EXCEPTION_ACCESS_VIOLATION at 0x5a6e35f324 -- unknown function (ip: 1849029412)
unknown function (ip: 1840926112)

Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at Brain2.Julia.Console.Program.jl_init(String julia_home_dir)
at Brain2.Julia.Console.Program.Main(String[] args)

I'm using Visual Studio 2012 and .NET 4.5

Tested with v0.3.2 (Current Release) for both x86 and x64 and also with v0.4.0-dev-7a7110b-win64

Julia Version 0.4.0-dev+1318
Commit 7a7110b* (2014-10-27 03:52 UTC)
Platform Info:
System: Windows (x86_64-w64-mingw32)
CPU: Intel(R) Core(TM) i7-4700MQ CPU @ 2.40GHz
WORD_SIZE: 64
BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Haswell)
LAPACK: libopenblas
LIBM: libopenlibm
LLVM: libLLVM-3.3

@sliekens sliekens changed the title Unable to use 'julialib.dll' in a C# application Unable to use 'libjulia.dll' in a C# application Nov 7, 2014
@ihnorton ihnorton added the system:windows Affects only Windows label Nov 7, 2014
@ihnorton
Copy link
Member

ihnorton commented Nov 7, 2014

What OS? I've tested the same code under Windows 7 and it worked fine. However, another user reported such an access violation on Windows 8.1.

@sliekens
Copy link
Author

sliekens commented Nov 7, 2014

Windows 8.1, not tested on any other platform.

@sliekens
Copy link
Author

sliekens commented Nov 7, 2014

What's confusing is that the interactive shell has no such problems, even on windows 8. What is my program doing that the interactive shell is doing differently? It's just two lines of code.

@sliekens sliekens changed the title Unable to use 'libjulia.dll' in a C# application Unable to use 'libjulia.dll' in a C# application on Windows 8.1 Nov 7, 2014
@ihnorton
Copy link
Member

ihnorton commented Nov 7, 2014

p/invoke'ing unmanaged code is quite different from running the interactive shell. It is entirely possible that there is some weird DLL interaction - this wouldn't be the first time.

However, a very quick google suggested that people have seen these violations with p/invoke'd code due to corrupt .NET installations when the system has been upgraded from Win7->8. If that is the history of your computer, you could consider updating or reinstalling the .NET SDK.

I'm not sure if any of the active developers have access to Win8/8.1 (I don't) so we will likely have to rely on detailed debugging feedback from you (and patches are very much encouraged!). A first step would be to run the code under the Visual Studio debugger and see if you can step in to jl_init.

@sliekens
Copy link
Author

sliekens commented Nov 7, 2014

I've dabbled in C before, but not nearly enough to even know how to attach a debugger to this thing and figure out why the code crashes.

By the way, Microsoft offers pre-built virtual machines and evaluation licenses of every major version of their operating system, including Windows 8. See: https://www.modern.ie/en-us/virtualization-tools#downloads

The offer is meant for web developers, but it doesn't seem like the license is restricted to web development.

@tkelman
Copy link
Contributor

tkelman commented Nov 7, 2014

I have Windows 2012 R2 in a packer VM that I can try this on, but my knowledge of .NET is almost nonexistent. I think I can get VS 2012 express installed command-line via chocolatey. Is there a command-line way to compile the C# example? I'm not sure if the VS IDE will be usable enough under a VM.

@vtjnash
Copy link
Sponsor Member

vtjnash commented Nov 8, 2014

also possible that the stack of your .NET application is too small. default is 1MB, recommended is 8MB (the linux default). you need at least a 3MB stack to build julia.

@sliekens
Copy link
Author

I'm targeting the precompiled binaries in my [DllImport] code. Any chance that the way that those binaries were compiled has anything to do with this "weird DLL interaction"? Can I compile the source myself using Microsoft's VC++ compiler?

@tkelman
Copy link
Contributor

tkelman commented Nov 10, 2014

@StevenLiekens do you mean the libjulia source code? Yes you can (or, should be able to... I hope) compile it from source with MSVC, see #7761, but it's pretty hacky, experimental, not first-class or documented yet, and many things in Julia are broken due to limitations of MSVC. If you want to help improve these matters that'd be awesome.

@sliekens
Copy link
Author

Still poking around with this. The call to jl_init() executes without crashing if I explicitly specify a path for julia_home_dir. The call to jl_eval_string() still crashes with an AccessViolationException.

Almost forgot to mention that this behavior is for a .2.x release (just because). I'll go try a 0.3.x release now.

Update: the same jl_init() code does not work for anything newer than .2.

class Program
{
    [DllImport("libjulia.dll")]
    public static extern void jl_init(string julia_home_dir);

    [DllImport("libjulia.dll")]
    public static extern void jl_eval_string(string str);

    static void Main(string[] args)
    {
        // Pass
        jl_init(@"C:\Users\steven liekens.BRAIN2\AppData\Local\julia-e44b593905\bin");

        // Crash
        jl_eval_string("print(sqrt(2.0))");
    }
}

@JeffBezanson
Copy link
Sponsor Member

Have you tried telling .NET to use a larger stack (see @vtjnash comment above)? Unfortunately I don't know how to do this, so I can't help much further.

@vtjnash
Copy link
Sponsor Member

vtjnash commented Dec 13, 2014

jl_eval_string may do some messy setjmp stuff on the stack. i'm hoping to remove that extra bit of complication with #9266. not sure if that could be directly the cause however, since the net result should be minor

@ihnorton ihnorton self-assigned this Feb 20, 2015
@ihnorton
Copy link
Member

this code works fine on 0.4 with x86 windows 8.1. Note the change in calling convention attribute; before that change, I had a PInvokeStackBalance warning for both calls (although they worked correctly). No stack size changes were made, so not sure if this is:

  • not an issue on x86
  • fixed by some part of Jameson's recent work
  • something else

But in any case as I can't reproduce and there has been no update, I will close. Please comment if this is still an issue and we will reopen.

@kp-cn
Copy link

kp-cn commented Apr 13, 2017

I am not able to initialize Julialib.dll using Julia-0.4.7 (64-Bit) from C# .net (Framework v4.6)

We explicitly require 64 bit of julia to do our work

Please let me know if anyone has a solution.

@vtjnash
Copy link
Sponsor Member

vtjnash commented Apr 13, 2017

The Discourse forum is a better place for getting help on usage questions. It'll be easier to answer your question over there, where there are better controls for message formatting and threading.

@ststeiger
Copy link

ststeiger commented Jun 7, 2018

This works for me:


namespace TelSearch
{


    class Program
    {

#if true 
        private const string SHARED_OBJECT_EXTENSION = @".dll";
        private const string JULIA_HOME = @"D:\Programme\Julia-0.6.3\";
        
        private const string JULIA_CPP_DLL = JULIA_HOME + @"bin\libstdc++-6.dll";
        private const string JULIA_LLVM_DLL = JULIA_HOME + @"bin\LLVM.dll";
        private const string JULIA_DLL = JULIA_HOME + @"bin\libjulia.dll";

#else
        private const string SHARED_OBJECT_EXTENSION = @".so";
        private const string JULIA_HOME = "/root/Downloads/julia-d55cadc350/";
        
        private const string JULIA_CPP_DLL = JULIA_HOME + "lib/julia/libstdc++.so.6";
        private const string JULIA_LLVM_DLL = JULIA_HOME + "lib/julia/libLLVM.so";
        private const string JULIA_DLL = JULIA_HOME + "lib/libjulia.so";

#endif


        delegate void jl_init_t();
        delegate void jl_eval_string_t(string message);
        delegate void jl_atexit_hook_t(int status);


        //private const string DLL = "libjulia.so";
        //private const string DLL = "/usr/lib/x86_64-linux-gnu/julia/libjulia.so";
        private const string DLL = "/root/Downloads/julia-d55cadc350/lib/libjulia.so";


        enum JL_IMAGE_SEARCH : int 
        {
            JL_IMAGE_CWD = 0,
            JL_IMAGE_JULIA_HOME = 1,
            //JL_IMAGE_LIBJULIA = 2,
        }


        // typedef enum { JL_IMAGE_CWD = 0, JL_IMAGE_JULIA_HOME = 1, //JL_IMAGE_LIBJULIA = 2, } JL_IMAGE_SEARCH;
        // JL_DLLEXPORT void julia_init(JL_IMAGE_SEARCH rel);
        [System.Runtime.InteropServices.DllImport(DLL)]
        static extern void jl_init(JL_IMAGE_SEARCH rel);

        // JL_DLLEXPORT void jl_init_with_image(const char* julia_home_dir, const char* image_relative_path);
        [System.Runtime.InteropServices.DllImport(DLL)]
        static extern void jl_init(string julia_home_dir, string image_relative_path);

        // no function with such signature in julia...
        // [System.Runtime.InteropServices.DllImport(DLL)]
        // public static extern void jl_init(string julia_home_dir);

        // JL_DLLEXPORT void jl_init(void);
        [System.Runtime.InteropServices.DllImport(DLL)]
        static extern void jl_init();

        // JL_DLLEXPORT jl_value_t *jl_eval_string(const char *str);
        [System.Runtime.InteropServices.DllImport(DLL)]
        static extern void jl_eval_string(string message);


        // JL_DLLEXPORT void jl_atexit_hook(int status);
        [System.Runtime.InteropServices.DllImport(DLL)]
        static extern void jl_atexit_hook(int status);


        public static void SetPath()
        {
            bool isPosixOs = System.Environment.OSVersion.Platform == System.PlatformID.Unix;
            // System.PlatformID.Unix = true for Linux & Mac & Unix 
            string envSeparator = isPosixOs ? ":" : ";";
            char pathSeparator = System.IO.Path.DirectorySeparatorChar;

            string[] paths = new string[]
            {
                 JULIA_HOME 
                ,System.IO.Path.Combine(JULIA_HOME, "bin") 
                ,System.IO.Path.Combine(JULIA_HOME, "lib") 
                ,System.IO.Path.Combine(JULIA_HOME, "lib", "julia") 
            };

            for (int i = 0; i < paths.Length; ++i)
            {
                if (paths[i].EndsWith(pathSeparator))
                {
                    paths[i] = paths[i].Substring(0, paths[i].Length - 1);
                } // End if (paths[i].EndsWith(System.IO.Path.DirectorySeparatorChar)) 

            } // Next i 
            
            string additional_paths = string.Join(envSeparator, paths);

            string path = System.Environment.GetEnvironmentVariable("PATH");
            if (!path.EndsWith(envSeparator))
            {
                if (!string.IsNullOrEmpty(additional_paths))
                {
                    path += envSeparator;
                    path += additional_paths;
                    System.Environment.SetEnvironmentVariable("PATH", path, System.EnvironmentVariableTarget.Process);
                    
                    if (isPosixOs)
                    {
                        //System.Environment.SetEnvironmentVariable("LD_LIBRARY_PATH", "/usr/lib/x86_64-linux-gnu/julia"); //, System.EnvironmentVariableTarget.Process);
                        System.Environment.SetEnvironmentVariable("LD_LIBRARY_PATH", additional_paths);
                    } // End if (isPosixOs) 

                } // End if (!string.IsNullOrEmpty(additional_paths)) 

            } // End if (!path.EndsWith(envSeparator))

            if (isPosixOs)
                System.Environment.SetEnvironmentVariable("LD_PRELOAD", DLL);
        } // End Sub SetPath 


        public static void Ancient()
        {
            // string home = "/usr/lib/x86_64-linux-gnu/julia";
            // string home = "/usr/lib/x86_64-linux-gnu";
            // string home = "/usr/lib";
            // System.IO.Directory.SetCurrentDirectory("/usr/bin");
            // System.IO.Directory.SetCurrentDirectory("/root/Downloads/julia-d55cadc350/bin");

            // string home = "/usr/bin";
            // string home = "/root/Downloads/julia-d55cadc350";
            // string home = "/root/Downloads/julia-d55cadc350/lib/julia";
            // string home = "/root/Downloads/julia-d55cadc350/bin";

            // jl_init(null);
            // jl_init(home);

            jl_init();
            jl_eval_string("println(sqrt(2.0))");
            jl_atexit_hook(0);
        } // End Sub Ancient 



        public static void foo()
        {
            jl_init(@"C:\Users\steven liekens.BRAIN2\AppData\Local\julia-e44b593905\bin", "");


        }


        // export LD_PRELOAD="/root/Downloads/julia-d55cadc350/lib/libjulia.so"
        // dotnet TelSearch.dll 
        static void Main(string[] args)
        {
            SetPath();
            
            // D:\Programme\Julia-0.6.3\bin\libstdc++-6.dll
            // D:\Programme\Julia-0.6.3\bin\libstdc++-6.dll

            // System.IntPtr hmoduleCPP = Platform.SharedLibrary.Load(JULIA_CPP_DLL);
            // System.IntPtr hmoduleLLVM = Platform.SharedLibrary.Load(JULIA_LLVM_DLL);
            System.IntPtr hmodule = Platform.SharedLibrary.Load(JULIA_DLL);
            
            jl_init_t init = Platform.SharedLibrary.LoadSymbol<jl_init_t>(hmodule, "jl_init");
            jl_eval_string_t eval_string = Platform.SharedLibrary.LoadSymbol<jl_eval_string_t>(hmodule, "jl_eval_string");
            jl_atexit_hook_t atexit_hook = Platform.SharedLibrary.LoadSymbol<jl_atexit_hook_t>(hmodule, "jl_atexit_hook");

            init();
            eval_string("println(sqrt(2.0))");
            atexit_hook(0);
            

            Platform.SharedLibrary.Unload(hmodule);
            // Platform.SharedLibrary.Unload(hmoduleLLVM);
            // Platform.SharedLibrary.Unload(hmoduleCPP);

            System.Console.WriteLine(System.Environment.NewLine);
            System.Console.WriteLine(" --- Press any key to continue --- ");
            System.Console.ReadKey();
        } // End Sub Main 


    } // End Class Program 
    

} // End Namespace TelSearch 

namespace Platform
{

    // superseeded by 
    // D:\username\Documents\Visual Studio 2017\Projects\libWkHtml2X\libWkHtmlToX\Loader
    public class SharedLibrary
    {

        [System.Runtime.InteropServices.DllImport("kernel32.dll", CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall
            , ExactSpelling = true, SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
        protected static extern System.IntPtr LoadLibraryW(string lpFileName);

        [System.Runtime.InteropServices.DllImport("kernel32.dll", CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall 
            , ExactSpelling = true, SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Ansi)]
        protected static extern System.IntPtr GetProcAddress(System.IntPtr hModule, string procName);

        [System.Runtime.InteropServices.DllImport("kernel32.dll", CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall 
            , ExactSpelling = true, SetLastError = true)]
        [return: System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)]
        protected static extern bool FreeLibrary(System.IntPtr hModule);
        



        // See http://mpi4py.googlecode.com/svn/trunk/src/dynload.h
        protected const int RTLD_LAZY = 1; // for dlopen's flags
        protected const int RTLD_NOW = 2; // for dlopen's flags

        [System.Runtime.InteropServices.DllImport("libdl", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl
            , CharSet = System.Runtime.InteropServices.CharSet.Ansi)]
        protected static extern System.IntPtr dlopen(string filename, int flags);

        [System.Runtime.InteropServices.DllImport("libdl", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl
            , CharSet = System.Runtime.InteropServices.CharSet.Ansi)]
        protected static extern System.IntPtr dlsym(System.IntPtr handle, string symbol);

        [System.Runtime.InteropServices.DllImport("libdl", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl
            , CharSet = System.Runtime.InteropServices.CharSet.Ansi)]
        protected static extern int dlclose(System.IntPtr handle);

        [System.Runtime.InteropServices.DllImport("libdl", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl
            , CharSet = System.Runtime.InteropServices.CharSet.Ansi)]
        protected static extern string dlerror();



        public static T LoadSymbol<T>(System.IntPtr handle, string symbol)
        {
            System.IntPtr function = System.IntPtr.Zero;
            
            
            if (System.Environment.OSVersion.Platform == System.PlatformID.Unix)
            {
                function = dlsym(handle, symbol);
                if (function == System.IntPtr.Zero)
                {
                    string message = dlerror();
                    System.Console.WriteLine(message);
                } // End if (hSO == System.IntPtr.Zero) 
            }
            else
            {
                function = GetProcAddress(handle, symbol);
                if (function == System.IntPtr.Zero)
                {
                    System.ComponentModel.Win32Exception ex = new System.ComponentModel.Win32Exception(System.Runtime.InteropServices.Marshal.GetLastWin32Error());
                    System.Console.WriteLine(ex.Message);
                } // End if (hSO == System.IntPtr.Zero) 
            }


            if (function == System.IntPtr.Zero)
            {
                throw new System.ApplicationException("Cannot find symbol \"" + symbol + "\".");
            } // End if (hSO == IntPtr.Zero)

            System.Type type = typeof(T);

            if(!type.IsSubclassOf(typeof(System.Delegate)))
            {
                throw new System.InvalidOperationException($"Type \"{type.Name}\" is not a delegate type");
            }

            System.Delegate delegateInstance = System.Runtime.InteropServices.Marshal
                .GetDelegateForFunctionPointer(function, typeof(T));
            
            return (T) (object) delegateInstance;
        }



        // Note: Not thread safe, but OK on app-start / end
        protected static System.Collections.Generic.Dictionary<string, System.IntPtr> m_dict_LoadedDlls =
            new System.Collections.Generic.Dictionary<string, System.IntPtr>();

        public static System.IntPtr Load(string strFileName)
        {
            System.IntPtr hSO = System.IntPtr.Zero;

            try
            {

                if (System.Environment.OSVersion.Platform == System.PlatformID.Unix)
                {
                    hSO = dlopen(strFileName, RTLD_NOW);
                    if (hSO == System.IntPtr.Zero)
                    {
                        string message = dlerror();
                        System.Console.WriteLine(message);
                    } // End if (hSO == System.IntPtr.Zero) 
                }
                else
                {
                    hSO = LoadLibraryW(strFileName);
                    if (hSO == System.IntPtr.Zero)
                    {
                        System.ComponentModel.Win32Exception ex = new System.ComponentModel.Win32Exception(System.Runtime.InteropServices.Marshal.GetLastWin32Error());
                        System.Console.WriteLine(ex.Message);
                    } // End if (hSO == System.IntPtr.Zero) 

                } // End if (Environment.OSVersion.Platform == PlatformID.Unix)

            } // End Try
            catch (System.Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
            } // End Catch

            if (hSO == System.IntPtr.Zero)
            {
                throw new System.ApplicationException("Cannot open " + strFileName);
            } // End if (hSO == IntPtr.Zero)

            m_dict_LoadedDlls.Add(strFileName, hSO);

            return hSO;
        } // End Function LoadSharedObject


        public static bool Unload(System.IntPtr hSO)
        {
            bool bError = true;

            if (hSO == System.IntPtr.Zero)
            {
                throw new System.ArgumentNullException("hSO");
            } // End if (hSO == IntPtr.Zero)

            try
            {

                if (System.Environment.OSVersion.Platform == System.PlatformID.Unix)
                {
                    // If the referenced object was successfully closed, dlclose() shall return 0. 
                    // If the object could not be closed, or if handle does not refer to an open object, 
                    // dlclose() shall return a non-zero value. 
                    // More detailed diagnostic information shall be available through dlerror().

                    // http://stackoverflow.com/questions/956640/linux-c-error-undefined-reference-to-dlopen
                    if(dlclose(hSO) == 0)
                        bError = false;

                    if (bError)
                        throw new System.ApplicationException("Error unloading handle " + hSO.ToInt64().ToString()
                            + System.Environment.NewLine + "System error message: " + dlerror());
                }
                else
                {
                    // FreeLibrary: If the function succeeds, the return value is nonzero.
                    // If the function fails, the return value is zero. 
                    // To get extended error information, call the GetLastError function.
                    bError = !FreeLibrary(hSO);

                    if(bError)
                        throw new System.ComponentModel.Win32Exception(System.Runtime.InteropServices.Marshal.GetLastWin32Error()); 

                } // End if (Environment.OSVersion.Platform == PlatformID.Unix)

            } // End Try
            catch (System.Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
            } // End Catch

            if (bError)
            {
                throw new System.ApplicationException("Cannot unload handle " + hSO.ToInt64().ToString());
            } // End if (hExe == IntPtr.Zero)

            return bError;
        } // End Function Unload


        public static void UnloadAllLoadedDlls()
        {
            foreach (string strKey in m_dict_LoadedDlls.Keys)
            {
                try
                {
                    Unload(m_dict_LoadedDlls[strKey]);
                }
                catch (System.Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine("Error unloading \"" + strKey + "\".");
                    System.Diagnostics.Debug.WriteLine(ex.Message);
                }

            } // Next strKey

        } // End Sub UnloadAllLoadedDlls


    } // End Class SharedLibrary


} // End Namespace Platform

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
system:windows Affects only Windows
Projects
None yet
Development

No branches or pull requests

7 participants