JNA undefined symbol - java

I'm trying to bind the dhcpctl library to Java using JNA. This is mi code (I didn't declare all the functions yet):
package com.abiquo.abicloud.omapi;
import com.abiquo.abicloud.omapi.DHCPControlStructure.DHCPCtrlDataString;
import com.abiquo.abicloud.omapi.DHCPControlStructure.DHCPHandle;
import com.abiquo.abicloud.omapi.OmapiControlStructure.OmapiObjectTypeT;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
/**
* Binding of the dhcpctl header.
* #author jdevesa#abiquo.com
*/
public interface DHCPControlLibrary extends Library
{
/**
* Create the loaded instance of the native library
*/
DHCPControlLibrary INSTANCE =
(DHCPControlLibrary) Native.loadLibrary("dhcpctl", DHCPControlLibrary.class);
/**
* Define as synchronized
*/
DHCPControlLibrary SYNC_INSTANCE=(DHCPControlLibrary) Native.synchronizedLibrary(INSTANCE);
int dhcpctl_initialize ();
int dhcpctl_connect (DHCPHandle handle1, String address, int port, DHCPHandle.ByValue handle2);
int dhcpctl_wait_for_completion (DHCPHandle handle, Pointer int1);
int dhcpctl_get_value (DHCPCtrlDataString dataString , DHCPHandle.ByValue handleValue, String str1);
int dhcpctl_get_boolean (Pointer int1, DHCPHandle.ByValue handleValue, String str1);
int dhcpctl_set_value (DHCPHandle.ByValue handleValue, DHCPCtrlDataString dataString, String str1);
... etc ...
}
dhcpctl uses omapi library to call the remote DHCP server. So, when I try to load the library with:
DHCPControlLibrary dhcpExecutor = DHCPControlLibrary.INSTANCE;
it throws the following error:
Exception in thread "main" java.lang.UnsatisfiedLinkError: Unable to load library 'dhcpctl': /usr/lib/libdhcpctl.so: undefined symbol: omapi_type_generic
at com.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:160)
at com.sun.jna.NativeLibrary.getInstance(NativeLibrary.java:228)
at com.sun.jna.Library$Handler.<init>(Library.java:140)
at com.sun.jna.Native.loadLibrary(Native.java:372)
at com.sun.jna.Native.loadLibrary(Native.java:357)
at com.abiquo.abicloud.omapi.DHCPControlLibrary.<clinit>(DHCPControlLibrary.java:40)
at com.abiquo.abicloud.omapi.DHCPexecution.main(DHCPexecution.java:11)
omapi__type__generic is an external variable stored in omapi.h. I think I have to do a sort of linking when i load the library, but I don't know how to do it.
Many thanks.

omapi_type_generic is not "an external variable stored in omap.h".
This variable must be defined in some .c file somewhere and hence in some .so or .a.
If it is not defined in any .c file then there is your problem right there. Find out why it is so and fix it and you should overcome this exception.

I think u forget extern "C" while writing c++ code.
In my case
c++ code:
#include <stdlib.h>
#include <iostream>
using namespace std;
extern "C"
{
void test() {
cout << "TEST" << endl;
}
int addTest(int a,int b)
{
int c = a + b ;
return c ;
}
}
and java code
import com.sun.jna.Library;
import com.sun.jna.Native;
public class jnatest1 {
public interface Clibrary extends Library {
Clibrary INSTANTCE = (Clibrary) Native.loadLibrary("hello",
Clibrary.class);
void test();
int addTest(int a,int b);
}
public static void main(String[] args) {
Clibrary.INSTANTCE.test();
int c = Clibrary.INSTANTCE.addTest(10,20);
System.out.println(c);
}
}
it works for me

Most likely you will need to either explicitly load the omapi library or ensure that it is in LD_LIBRARY_PATH so that the system can find it automatically when the dhcpctl library is loaded.

Related

Call a 86x Dll from Java

Am trying to call a x86 DLL that I created using VC 6, from a java project on Eclipse, first try I got an error saying that I can't call a x86 DLL from a x64 envirement and that the DLL can't be loaded. So I installed a x86 jre and I have no more problem to charge the DLL.
But when I try to call my c++ function I get the following exception:
Exception in thread "main" java.lang.UnsatisfiedLinkError: mm.SimpleDLL.SimpleDLL_Calculation_Add(II)I
Can someone please help me ?
Thank you.
SimpleDLL.h
#ifndef SIMPLE_DLL_H
#define SIMPLE_DLL_H
namespace SimpleDll
{
extern class Calculation
{
public:
static __declspec(dllexport) int Add(int a, int b);
};
}
#endif SIMPLE_DLL_H
SimpleDLL.cpp
#include "SimpleDll.h"
namespace SimpleDll
{
int Calculation::Add(int a, int b)
{ return a + b; }
}
SimpleDLL.java
package mm;
public class SimpleDLL {
static
{
System.load("D:\\SimpleDLL.dll");
}
public static void main(String ar[])
{
System.out.println("Hello world from Java");
SimpleDLL t=new SimpleDLL();
int x = t.SimpleDLL_Calculation_Add(6, 7);
System.out.println("Resultat "+x);
}
public native int SimpleDLL_Calculation_Add(int a, int b);
}
Exported DLL Functions View
Resolved using the JNA library, I used this link to walkthrough
You need to build a 32-bit DLL and a .h file using javah for the exact signature Java expects. It is usually something like
JNIEXPORT jboolean JNICALL Java_Sample1_booleanMethod
(JNIEnv *, jobject, jboolean);
from https://medium.com/#bschlining/a-simple-java-native-interface-jni-example-in-java-and-scala-68fdafe76f5f
An alternative approach is to use a library like JNA or JNR-FFI which allow you to bind to a C library without writing this bridging code.

NuiGetSensorCount Java JNA

I am just learning how to use Java JNA, and I am trying to call a simple function from the Microsoft Kinect SDK. (NuiGetSensorCount) which just returns the number of connected kinects.
Here is my attempt:
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
public class Driver {
public interface KinectLibrary extends Library {
KinectLibrary INSTANCE = (KinectLibrary)Native.loadLibrary(("Microsoft.Kinect"),KinectLibrary.class);
//_Check_return_ HRESULT NUIAPI NuiGetSensorCount( _In_ int * pCount );
NativeLong NuiGetSensorCount(Pointer pCount);
}
public static void main(String[] args) {
Pointer devCount = new Pointer(0);
KinectLibrary.INSTANCE.NuiGetSensorCount(devCount);
System.out.println("Devices:"+devCount.getInt(0));
}
}
But I get:
Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'NuiGetSensorCount': The specified procedure could not be found.
at com.sun.jna.Function.<init>(Function.java:208)
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:536)
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:513)
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:499)
at com.sun.jna.Library$Handler.invoke(Library.java:199)
at $Proxy0.NuiGetSensorCount(Unknown Source)
at Driver.main(Driver.java:30)
Can anybody provide help of how to change my code so it finds the correct native function? And also provide some information/reference so that I could try to debug this myself (some way to see what function Java JNA is looking for, and compare it to what the .dll contains)
I figured out my problem. First, I used a program called dependency walker http://dependencywalker.com/ to view all the symbols in the DLL and I determined that the DLL I was using (Microsoft.Kinect.dll) did not actually contain the function I was trying to call. I found out that Kinect10.dll was the one I needed. After changing that, I had to make a small change to my pointer and it works perfectly!
Here is the fixed code.
import com.sun.jna.Native;
import com.sun.jna.NativeLong;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.win32.StdCallLibrary;
public class Driver{
public interface KinectLibrary extends StdCallLibrary {
KinectLibrary INSTANCE = (KinectLibrary)Native.loadLibrary(("Kinect10"),KinectLibrary.class);
//_Check_return_ HRESULT NUIAPI NuiGetSensorCount( _In_ int * pCount );
NativeLong NuiGetSensorCount(IntByReference pCount);
}
public static void main(String[] args) {
IntByReference a = new IntByReference();
KinectLibrary.INSTANCE.NuiGetSensorCount(a);
System.out.println("Devices:"+a.getValue());
}
}

Using DLL in java through JNA

I am using dll in java using JNA, but i am getting below error
Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'GetStatus': The specified procedure could not be found.
Not getting how to resolve this issue?
Please help.
Here is java code
import com.sun.jna.Library;
import com.sun.jna.Native;
/** Simple example of native library declaration and usage. */
public class First {
public interface TEST extends Library {
public String GetStatus();
}
public static void main(String[] args) {
TEST obj = (TEST ) Native.loadLibrary("TEST ", TEST .class);
System.out.println( obj.GetStatus());
}
}
This Nugget is super easy to use and works perfectly. https://www.nuget.org/packages/UnmanagedExports
You need Visual Studio 2012 (express).
Once installed, just add [RGiesecke.DllExport.DllExport] before any static function you want to export. That's it!
Example:
C#
[RGiesecke.DllExport.DllExport]
public static int YourFunction(string data)
{
/*Your code here*/
return 1;
}
Java
Add the import at the top:
import com.sun.jna.Native;
Add the interface in your class. Its your C# function name preceded by the letter "I":
public interface IYourFunction extends com.sun.jna.Library
{
public int YourFunction(String tStr);
};
Call your DLL where you need it in your class:
IYourFunction iYourFunction = (IYourFunction )Native.loadLibrary("full or relative path to DLL withouth the .dll extention", IYourFunction.class);//call JNA
System.out.println("Returned: " + IYourFunction.YourFunction("some parameter"));
EDIT:
If the DLL is 32bit, the JDK/JRE has to be 32bit as well. Add the following check to your code:
if(!System.getProperty("os.arch").equals("x86")) {
throw new Exception(".NET DLL " + "32bits JRE/JDK is required. Currently using " + System.getProperty("os.arch") + ".\r\nTry changing your PATH environement variable.");
}

JNA access to 64-bit DLL (Windows7 64-bit)

Could you please advice. I have simple DLL (under Windows 7 64-bit) and simple Java code with JNA access to this DLL.
The problem is when I use 64-bit version of this DLL looks like I can't get parameter from Java in my DLL test function giveIntGetInt, and I have no problem when I use 32-bit DLL.
Where I was wrong?
Thank you!
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
import com.sun.jna.Pointer;
/** Simple example of native library declaration and usage. */
public class HelloWorld {
public interface simpleDLL extends Library {
simpleDLL INSTANCE = (simpleDLL) Native.loadLibrary(
(Platform.isWindows() ? "simpleDLL" : "simpleDLLLinuxPort"), simpleDLL.class);
int giveIntGetInt(int a); // int giveIntGetInt(int a);
}
public static void main(String[] args) {
int b = simpleDLL.INSTANCE.giveIntGetInt(2);
System.out.println("Hello, World\n");
System.out.println(String.format("Argument %d", b));
}
}
this is C dll method:
int simpleDLL::giveIntGetInt(int a)
{
return 2*a;
}
For example, this is I've got with 64-bit dll:
Hello, World
Argument 181140
32-bit dll:
Hello, World
Argument 4

JNA - Unable to get a call from native function to a callback function

I am using JNA to call functions of a dll file.
One of the functions requires a pointer to a callback function
// Dll function
void MyFunction (*CallBackFnName);
Below is the JNA proxy interface in java
import com.sun.jna.Callback;
import com.sun.jna.Library;
import com.sun.jna.Pointer;
public interface Dll extends Library {
interface CallBackFnName extends Callback {
void callback(Pointer dataBuffer, int dataLen);
}
public void MyFunction(Dll.CallBackFnName fn);
public int StartReading(short arg1, short arg2);
}
According to the API of the dll, after passing the pointer to a callback function to the function MyFunction(*CallBackFnName), whenever you call StartReading() function it will send data to the callback function.
When I am trying to do that, It is not calling my callback function. It is not throwing any exception also.
Below is the code from which I am calling functions:
import com.sun.jna.Native;
import com.sun.jna.Pointer;
public class Start {
private static Dll dll = (Dll) Native.loadLibrary("MyDll", Dll.class);
private static Dll.CallBackFnName fn = new Dll.CallBackFnName() {
#Override
public void callback(Pointer dataBuffer, int dataLen) {
System.err.println("Callback function is called successfully");
}
};
public static void main(String[] args) throws InterruptedException {
dll.MyFunction(fn); //passed the pointer to the callback function
short arg1 = 0;
short arg2 = 0;
dll.StartReading(arg1, arg2));
Thread.sleep(10 * 1000);
}
}
After running the above code, I am getting the following on the console:
DeviceAttach: received and accepted attach for vendor id 0x3eb, product id 0x2ffd, interface 0, device handle 0x037825E8
Main Menu (active Dev/Prod/Interface/Alt. Setting: 0x3eb/0x2ffd/0/0)
Read FailReadWritePipesMenu: WDU_Transfer(control receive) failed: error 0x2000000e ("
Read Fail")
Read FailReadWritePipesMenu: WDU_Transfer(control receive) failed: error 0x2000000e ("
Read Fail")
Read FailReadWritePipesMenu: WDU_Transfer(control receive) failed: error 0x2000000e ("
Read Fail")
Transferred 0 bytes
0 0
Don't know if you still need the answer , but to anyone else who has this problem,
I had this problem before.I had to create an anonymous class as such (using the above example),
dll.myfunc(new Dll.CallBackFnName() {
#Override
public void callback(Pointer dataBuffer, int dataLen) {
System.err.println("Callback function is called successfully");
} } );
This worked for me . although i can't explain why.

Categories