natenho
natenho

Reputation: 5601

Loading dependent .NET assemblies using JNA

I have a .NET (C#) dll which is exporting functions through Unmanaged Exports which is being consumed by a Java application.

This C# dll (let's call it A.dll) has another managed dependency F3BC4DNI.dll.

So, the dependency chain is like: Java class <- JNA <- A.dll <- F3BC4DNI.dll

Don't need to say that all the dlls are included together in the application bin folder.

However, all java binaries run under a process called javaw.exe, then when I try to consume A.dll through JNA, it's looking for F3BC4DNI.dll inside the javaw.exe path instead of the same folder as A.dll as can be seen in Process Monitor:

Dependency being searched inside javaw directory

My guess is that A.dll (.NET) is assuming the process path when looking for dependencies.

I've tried a lot of possible solutions like setting PATH environment var, setting JNA library path and also I tried to load the B.dll assembly explicitly inside A.dll using Assembly.LoadFrom.

The result is always the same when the Java application is run:

Exception in thread "main" java.lang.Error: Invalid memory access
    at com.sun.jna.Native.invokePointer(Native Method)
    at com.sun.jna.Function.invokePointer(Function.java:470)
    at com.sun.jna.Function.invokeString(Function.java:651)
    at com.sun.jna.Function.invoke(Function.java:395)
    at com.sun.jna.Function.invoke(Function.java:315)
    at com.sun.jna.Library$Handler.invoke(Library.java:212)

When I copy these dlls to the Program Files\Java...bin\ folder, it works, but obviously I don't want to deploy it this way in production.

After all, the only thing I'm assuming is that it's not a problem with Java or JNA side, because it's a .NET related dependency, so I have to somehow tell javaw.exe that .NET dependencies are in another folder.

Upvotes: 1

Views: 986

Answers (1)

natenho
natenho

Reputation: 5601

[...]I have to somehow tell javaw.exe that .NET dependencies are in another folder.

Just like I suspected, when manually telling to .NET where the dependency is, the problem has been solved, using the answer from this post.

/// <summary>
/// Initializes a new instance of the <see cref="T:System.Object"/> class.
/// </summary>
static A()
{
    AppDomain.CurrentDomain.AssemblyResolve += (sender, e) =>
    {
        var path = Path.Combine(Directory.GetCurrentDirectory(), "bin\\F3BC4DNI.DLL");
        return Assembly.LoadFile(path);
    };
}

Upvotes: 0

Related Questions