0

I was trying to use a .NET DLL from Java code, the tsMemberFunctions.DLL is loaded successfully, but the code fails to call the actual function.

See the snippet below:

public class tsMemberFunctions {  
    public native void GetMemberJSONSample();

    static {
        System.loadLibrary("tsMemberFunctions");
        System.out.println("Loaded");
    }

    public static void main(String[] args) {
        new tsMemberFunctions().GetMemberJSONSample();

    }
}

On executing above method I am getting below error:

Loaded
Exception in thread "main" java.lang.UnsatisfiedLinkError: tsMemberFunctions.GetMemberJSONSample()V
    at tsMemberFunctions.GetMemberJSONSample(Native Method)
    at tsMemberFunctions.main(tsMemberFunctions.java:12)

Can someone please tell me if I missed anything or anything is incorrect in the code or suggest better alternative for this use case. TIA.

Himanshu Arora
  • 688
  • 1
  • 9
  • 20
  • Why do you need a native library to get JSON? I'd figure out how to make an HTTP call and get it that way. Native code is not the most portable thing you can choose. – duffymo May 09 '19 at 18:19
  • Hi, you could ignore the function name, the main aim of this snippet is to call a method from dll file which is not happening with the current code. – Himanshu Arora May 09 '19 at 18:27
  • My concern still stands. You should think of another way. Read this if you must: https://docs.oracle.com/javase/8/docs/technotes/guides/jni/ – duffymo May 09 '19 at 18:27

1 Answers1

0

You have to be very careful with the names and exports.

Let's say you have this super simple lib

// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include "jni.h"
#include <stdio.h>

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

extern "C" JNIEXPORT void JNICALL Java_recipeNo001_HelloWorld_displayMessage

(JNIEnv* env, jclass obj) {

    printf("Hello world!\n");

}

You have to make sure to build your DLL for proper architecture (it will depend on Java version you have - 32/64 bit).

Let's say you have x64 DLL and x64 JDK, you can call your lib like this

package recipeNo001;

public class HelloWorld {

    public static native void displayMessage();

    static {
        System.load("C:\\Users\\your_name\\Source\\Repos\\HelloWorld\\x64\\Debug\\HelloWorld.dll");
    }

    public static void main(String[] args) {
      HelloWorld.displayMessage();
    }
}

In your case, I bet you don't have extern "C" in your code - this is why your symbol can't be found by JVM.

When it comes to tools, I suggest Visual Studio 2019 (when it comes to creating DLL) and IntelliJ for Java code.

You can find lots of samples here: http://jnicookbook.owsiak.org/ and here: https://github.com/mkowsiak/jnicookbook

Oo.oO
  • 12,464
  • 3
  • 23
  • 45
  • OP used the term ".NET DLL" which could mean they're using a managed C++ or C# DLL that depends on the .NET framework. I'm not sure that they even have an `extern "C"` interface. – Romen May 29 '19 at 18:33
  • If this is the case (you have a managed DLL), it will be necessary to use C/C++ native bridge. Inside the bridge, you will have to load .Net DLL and run the code from the lib. – Oo.oO May 29 '19 at 18:37