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.");
}
Related
I want to wrap a C++ library (PCL) in Java code using JNI, but I am having inconsistent results. I have first created a PointXYZ class for testing and it looks like this:
package pcl;
public class PointXYZ extends NativeObject {
PointXYZ() { }
#Override
public native void alloc(); // creates pointer + handle on the native side
#Override
public native void dispose(); // sets handle to 0 and deletes pointer
public native float getX();
// ...
}
I have generated the C header for this class using javah, compiled everything using CMake, tested it using its getters and setters and everything works perfectly.
static {
System.setProperty("java.library.path", System.getProperty("user.dir") + "/lib");
System.loadLibrary("pcl_java_common");
}
#Test
void attributeAccessTest() {
PointXYZ p = new PointXYZ();
p.alloc();
p.setX(3);
assertEquals(p.getX(), 3);
p.dispose();
// all is good
}
Now I have done the exact same steps for a PointXYZRGB class which inherits from PointXYZ and when I try to test that it throws java.lang.UnsatisfiedLinkError. Here is the class:
package pcl;
public class PointXYZRGB extends PointXYZ {
public PointXYZRGB() { }
#Override
public native void alloc();
#Override
public native void dispose();
public native short getR();
// ...
}
I have checked the generated .dll using Dependency Walker and the PointXYZRGB methods are all present. Anyone knows what the problem could be?
UPDATE: Here are the .dll functions as requested in the comment:
The problem was that System.setProperty("java.library.path", System.getProperty("user.dir") + "/lib"); does not actually make Java look for .dll files in the given path. It essentially does nothing. Then why do the tests work for PointXYZ? This is was my mistake of having put an older .dll into the project root folder, so it was essentially looking for methods in that.
I have to use Java JNA to link a C library. This library has a Windows implementation and a Linux one. These differ one from other for a single method because this method is implemented only by Windows version.
MyJnaInterface INSTANCE = (MyJnaInterface) Native.loadLibrary("MyLibrary",
MyJnaInterface.class);
I would like to have just one version of my Java application, this may have a single interface with 2 implementation, one for windows os and one for linux os, obviously the linux implementation will have an empty method.
public interface MyJnaInterface
public class MyJnaWinImpl implements MyJnaInterface
public class MyJnaLinuxImpl implements MyJnaInterface
This works in windows, in linux OS at service startup JNA tries to find its native methods also in windows classes (also if this class is not used in runtime) and so it throws a UnsatifiedLinkError.
How to solve this deadlock?
I really cannot change the native library (it would be so simple...)
I suggest to use compilation toolbox in your project to compile java code runtime depending upon value returned by System.getProperty("os.name") . If it returns windows then you can add source code for MyJnaWinImpl in one string and pass that to JavaSourceCompiler class. Once that is compiled load class and create instance. On linux JavaSourceCompiler will compile MyJnaLinuxImpl. Ensure that before creating this instance libraries are loaded.
Below is a small test code snippet.
package test;
import org.abstractmeta.toolbox.compilation.compiler.*;
import org.abstractmeta.toolbox.compilation.compiler.impl.*;
import java.lang.ClassLoader;;
public class test {
public static void main(String[] args) throws ClassNotFoundException,InstantiationException,IllegalAccessException{
JavaSourceCompiler javaSourceCompiler = new JavaSourceCompilerImpl();
JavaSourceCompiler.CompilationUnit compilationUnit = javaSourceCompiler.createCompilationUnit();
String os = System.getProperty("os.name");
String SourceCode;
if ( os.contentEquals("Windows"))
{
SourceCode = "package com.test.foo;\n" +
"import MyJnaInterface.*;" +
"import MyJnaWinImpl " +
"public class Foo implements MyJnaWinImpl {\n" +
" public native void check();\n" +
" }";
}
else
{
SourceCode = "package com.test.foo;\n" +
"import MyJnaInterface.*;" +
"import MyJnaLinuxImpl " +
"public class Foo implements MyJnaLinuxImpl {\n" +
//" public native void check();\n" +
" }";
}
compilationUnit.addJavaSource("com.test.foo.Foo", SourceCode);
ClassLoader classLoader = javaSourceCompiler.compile(compilationUnit);
Class fooClass = classLoader.loadClass("com.test.foo.Foo");
Object foo = fooClass.newInstance();
}
}
I solved using static{} block.
public interface MyJnaInterface;
public interface MyJnaInterfaceWin implements MyJnaInterface; // this has the WinMethod method
...
private static MyJnaInterface INSTANCE;
static{
if(SystemUtils.IS_OS_LINUX){
INSTANCE=(MyJnaInterface) Native.loadLibrary("MyLibrary",MyJnaInterface.class);
}else{
INSTANCE=(MyJnaInterfaceWin) Native.loadLibrary("MyLibrary",MyJnaInterfaceWin.class);
}
}
...
public static void WinMethod(){
if(!SystemUtils.IS_OS_LINUX) ((MyJnaInterfaceWin)INSTANCE).WinMethod());
}
I'm assuming you're using direct mapping, since interface mapping won't look up your function until you invoke it.
Write a base class with the base implementation, then a derived class that includes the additional mapping. Only load the derived class where you know the underlying function exists.
class BaseInterface {
public native void nativeMethod();
public void extendedMethod() { /* empty stub */ }
}
class ExtendedInterface extends BaseInterface {
public native void extendedMethod();
}
if (needExtendedInterface) {
lib = /* load extended library */
}
else {
lib = /* load base library */
}
I need to call Windows Color System functions from Java. Following this tutorial i tried to call DLL function using Java Native Access. All examples from this tutorial works fine. When i try to load and use Mscms.dll (one of the WCS libraries) that DLL seems to be loaded successfully, but i can not call any functions. List of functions is here.
I got a message:
Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'GetColorDirectory'
What's wrong with my code? Could you help me please?
import com.sun.jna.Library;
import com.sun.jna.Native;
public class WCS_test {
public interface Mscms extends Library {
// http://msdn.microsoft.com/en-us/library/dd316928%28v=vs.85%29.aspx
boolean GetColorDirectory(String pMachineName, String[] pBuffer, int pdwSize);
}
private static Mscms mscms = (Mscms) Native.loadLibrary("C:/Windows/system32/Mscms.dll", Mscms.class);
public static void main(String[] args) {
if (mscms != null)
System.out.println("Library loaded\n");
else
System.err.println("Library loading error\n");
String[] pBuffer = new String[1024];
mscms.GetColorDirectory(null, pBuffer, pBuffer.length);
}
}
When you get a java.lang.UnsatisfiedLinkError that means that it could not find the function 'GetColorDirectory' inside of the Mscms.dll. Looking at the link from your source code http://msdn.microsoft.com/en-us/library/dd316928%28v=vs.85%29.aspx you should try the Unicode name GetColorDirectoryW.
I am new to accessing DLLs from Java using JNA. I need to access methods from a class within a DLL(written in .net). Form this sample DLL below, I am trying to get AuditID and Server ID. I am ending with the following error while I am running my code. Any guidance really appreciated.
/// Error ///
Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'GetEnrollcontext': The specified procedure could not be found.
//DLL File Code//
SampleDLL.ProfileEnroll enrollcontext = new SampleDLL.ProfileEnroll();
enrollcontext.Url =” url”;
enrollcontext.AuditIdType = SampleDLL.ProfileId;
enrollcontext.AuditId = “22222222 “;
enrollcontext.ServerId = “server1”;
/// Java Code ///
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Structure;
import dllExtract.DLLExtractTest.SampleDLL.Enrollcontext;
public class SampleDLLExtract {
public interface SampleDLL extends Library {
SampleDLL INSTANCE = (SampleDLL) Native.loadLibrary("SampleDLL",
SampleDLL.class);
public static class Enrollcontext extends Structure {
public String auditId;
public String serverId;
}
void GetEnrollcontext(Enrollcontext ec); // void ();
}
public static void main(String[] args) {
SampleDLL sdll = SampleDLL.INSTANCE;
SampleDLL.Enrollcontext enrollContext = new SampleDLL.Enrollcontext();
sdll.GetEnrollcontext(enrollContext);
System.out.println(sdll.toString(sdll.GetEnrollcontext(enrollContext)));
}
}
in fact there is a solution for you to use C#, VB.NET or F# code via JNA in Java (and nothing else)! and it is also very easy to use:
https://www.nuget.org/packages/UnmanagedExports
with this package all you need to do is, add [RGiesecke.DllExport.DllExport] to your methods like that:
C# .dll Project:
[RGiesecke.DllExport.DllExport]
public static String yourFunction(String yourParameter)
{
return "CSharp String";
}
Java Project:
public interface jna extends Library {
jna INSTANCE = (jna) Native.loadLibrary("yourCSharpProject.dll", jna.class);
public String yourFunction(String yourParameter);
}
use it in the code:
System.out.println(jna.INSTANCE.yourFunction("nothingImportant"));
Viola!
As already mentioned it works very easy, but this solution has some limitations:
only available for simple datatypes as parameter & return values
no MethodOverloading available. yourFunction(String yourParameter) and yourFunction(String yourParameter, String yourSecondParameter) does not work! you have to name them differently
Use arrays as parameter or return values. (JNA offers StringArray, but I am not able to use them in C#) (maybe there is a solution, but I couldn't come up with one so far!)
if you export a method you can't call it internally in your C# code (simple to bypass that by the following:
.
[RGiesecke.DllExport.DllExport]
public static Boolean externalAvailable(String yourParameter)
{
return yourInternalFunction(yourParameter);
}
With C# it works great, with VB.NET and F# I have no experience.
hope this helps!
I have created a Mac Java Swing application, and i have set a file extension(*.pkkt) for it in the "Info.plist" file, so when double clicking that file it opens my application.
When i do that the program runs fine. Now i need to load the (*.pkkt) project in the program, but the file path is not passed as an argument to the main(...) method in Mac as happens in Windows Operating System.
After some search i found an Apple handling jar "MRJToolkitStubs" that has the MRJOpenDocumentHandler interface to handle such clicked files. I have tried using it to load that file by implementing that Interface in the main program class, but it is not working. The implemented method is never called at the program start-up.
How does this Interface run ?
------------------------------------------------- Edit: Add a Code Sample
Here is the code i am using :
public static void main( final String[] args ) {
.
.
.
MacOpenHandler macOpenHandler = new MacOpenHandler();
String projectFilePath = macOpenHandler.getProjectFilePath(); // Always Empty !!
}
class MacOpenHandler implements MRJOpenDocumentHandler {
private String projectFilePath = "";
public MacOpenHandler () {
com.apple.mrj.MRJApplicationUtils.registerOpenDocumentHandler(this) ;
}
#Override
public void handleOpenFile( File projectFile ) {
try {
if( projectFile != null ) {
projectFilePath = projectFile.getCanonicalPath();
System.out.println( projectFilePath ); // Prints the path fine.
}
} catch (IOException e) {}
}
public String getProjectFilePath() {
return projectFilePath;
}
}
As mentioned in the comment above "getProjectFilePath()" is always Empty !
On Java 9, use Desktop.setOpenFileHandler()
The proprietary com.apple.eawt packages have been removed from recent versions of Java and has been incorporated into various methods in the Desktop class. For your specific example:
import java.awt.desktop.OpenFilesHandler;
import java.awt.desktop.OpenFilesEvent;
import java.io.File;
import java.util.List;
public class MyOpenFileHandler implements OpenFilesHandler {
#Override
public void openFiles(OpenFilesEvent e) {
for (File file: e.getFiles()) {
// Do whatever
}
}
}
Then elsewhere, add this:
Desktop.getDesktop().setOpenFileHandler(new MyOpenFileHandler());
The OpenFilesEvent class also has a getSearchTerm() method. Say that a person used Spotlight on macOS to search for the word "StackOverflow", then decided to open up a document. With this method, can you determine that "StackOverflow" was the word they searched for, and choose to do something with that (perhaps highlight the first occurrence of the word).
You're going to want to use the Apple Java Extensions.
They should be included in any JDK that runs on Mac OS X, but the documentation is kind of hard to get. See this answer for more details.
Specifically, you'll want to make an OpenFilesHandeler.
This code snippet should work:
import com.apple.eawt.event.OpenFilesHandeler;
import com.apple.eawt.event.AppEvent;
import java.io.File;
import java.util.List;
class MacOpenHandler implements OpenFilesHandeler {
#Override
public void openFiles(AppEvent.OpenFilesEvent e) {
List<File> files = e.getFiles();
// do something
}
}
And somewhere:
import com.apple.eawt.Application;
...
MacOpenHandeler myOpenHandeler = new MacOpenHandeler();
Application.getApplication().setOpenFileHandler(myOpenHandeler);