I want to call functions I implemented in c/c++ within my Java code using JNA.
Path for my bridge file, which loads the library:
main/java/com/identifier/projectname/BridgeFile.java
Path for my library I want to call:
main/libs/lib1/functions.c and main/libs/lib1/functions.h
from my functions.c file I call functions from other libs contained within my libs folder (main/libs/lib2/, main/libs/lib3/). The files are more or less "loose" and I call them within my functions.c.
I include jna within my build.gradle:
dependencies {
implementation 'net.java.dev.jna:jna:5.12.1'
}
My Viewer (file where I load the library) looks like the following:
package com.identifier.projectname;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
public class Viewer extends SimpleViewManager<TextureView> {
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary("finder", CLibrary.class);
int testFunc();
}
// Calling it like this: int testval = CLibrary.INSTANCE.testFunc();
}
The native code of testFunc inside of my functions.c (declared in functions.h) looks like the following:
int testFunc(){
return 1;
}
When I call my testFunc() within another Java file, my app crashes, because I don't know how to include the other files with my make file to my functions.c so JNA can find the methods or my lib can't be found under the name finder.
If all of the above code is correct, how do I build my c/c++ library so I can include the headers/source files (.c + .cpp) from the other lib folders and use the lib with JNA?
Another solution path would be to try to create a small binary executable, which will call your method, which it is located, not in the executable, but in a shared library, so you could perhaps better target the cause of your problem which may not be related to JNA
We also use JNA with Java here, I will be happy to help you if you provide more example of c codes and compilation parameters
Related
I am having a .dll file which has a wrapper in C,C++, .Net and python, but not in Java. I am successful in loading the .dll file using following code in my Java
public class
public static void main(String[] {
// print when the program starts
System.out.println("Program starting...");
System.out.println("Loading Library...");
Runtime.getRuntime().loadLibrary("HelloJava");
System.out.println("Library Loaded.");
}
}
which gives the following output:
Now my question is that if this file is loaded, How do I access it's functions to use in my Java workspace?
Since it is the C-DLL, so How should I fetch the module values from this .dll.
Note:
I have made a folder named dll under my Java project path from where I loaded the library in the above code.
I browsed for the concept for JNA and JNI but lacked the understanding concept, that's why posted the question.
Thanks in advance.
I think you need to know the methods in your DLL first. I really don't know how to list the methods using JNA or JNI, but you have to know the method's signature before starting, maybe from a documentation, because you normally can find the DLL's documentation on the web, or you even can use a Reflector (like red-gate) to find out your methods.
Then:
Download the JNA .jar file and add it to your build in your Java project.
Put the .dll in the root directory of your Java project.
Create an Interface that contains the functions from the dll that you want to use.
For example, lets say your HelloWorld DLL has a String hello(String hey) method in C++, then in your Java project you will have to do something like:
import com.sun.jna.Library;
import com.sun.jna.Native;
public class Main {
public interface Ihello extends Library {
public String hello(String hey);
}
public static void main(String args[]) {
//"hello-world is the name my DLL, for example.
Hello h = Native.load("hello-world", Hello.class);
System.out.println(h.hello(" John! ");
}
}
Here is a good example, regards.
1). I know how to access the java fields and object in beanshell from my question Use java class fields in beanshell. However, it is not so clean way to implement as I need to first set the java variable in beanshell and then I can use it. However, in Jmeter it provides very clean way of using maps in beanshell similar way as we do in java, but JMeter has developed it's know library (class) which helps to access get/put methods for maps. I want to achieve similar way to access Map in beanshell.
I have checked JMeter for more information and I want to know that, I have created user define variable temp and assign value error, now in BSF process I just write a line vars.put('Name','temp Value') and it has updated value for temp variable. So, the question is I have not created JMeterVariables object vars but still beanshell allows to update values in map without setting any values as mention in your answer. I want to know how this works, need more depth information.
2). I have created my own class in java and in beanshell I am importing this class but it is giving Command not found: BSClass() below is the entire code
Java class
package test;
public class BSClass {
public void BSCMethod(){
System.out.println("I am from BSClass method BSCMethod");
}
}
sample.bsh
import test.BSClass;
c=BSClass();
c.BSCMethod();
print("I am from BeanShell Script");
Calling sample.bsh file java class
package test;
import java.io.FileNotFoundException;
import java.io.IOException;
import bsh.*;
public class DynamicVariable {
public static void main(String[] args) throws FileNotFoundException, IOException, EvalError {
new bsh.Interpreter().source("\\src\\test\\sample.bsh");
}
}
Note:
I don't need help in JMeter, it is to use in core java and beanshell.
All the files are in my project.
BSClass.class is under bin folder of my project
I would appreciate your inputs
In Beanshell you can add any Object you want including a Map
In JMeter, JMeterVariables is special implementation of Map that is added to Beanshell Interpreter before evaluate and also special Object as JMeterContext is added which even includes JMeterVariables inside. Code:
JMeterContext jmctx = JMeterContextService.getContext();
JMeterVariables vars = jmctx.getVariables();
try {
bshInterpreter.set("ctx", jmctx);//$NON-NLS-1$
bshInterpreter.set("Label", getName()); //$NON-NLS-1$
bshInterpreter.set("prev", jmctx.getPreviousResult());//$NON-NLS-1$
bshInterpreter.set("props", JMeterUtils.getJMeterProperties());
bshInterpreter.set("vars", vars);//$NON-NLS-1$
In your case with map you can do similar as you describe in comment:
bshInterpreter.set("myMap", javaMyMapObject);"
Then in Beanshell get the specific key from map:
myMap.get("aField");
To create class you should use new keyword, call:
c= new BSClass();
instead of c=BSClass();
If you create your own class, Class should be inside jar in relevant package .
The jar should be located in lib folder and not in bin folder, see JMeter's getting started:
Any jar file in such a directory will be automatically included in
user.classpath, jar files in sub directories are ignored. The given
value is in addition to any jars found in the lib directory. All
entries will be added to the class path of the system class loader and
also to the path of the JMeter internal loader.
I'm developing an android test app and i'm going to access all internal class of android.view package. android.view is a package that is present in jar file. I tried by loading package name but it doesn't display the classes if any one tried
this already, please help.
Here's what I tried so far:
public static void main() throws ClassNotFoundException{
Class o =Class.forName("android.view");
Class[] C=o.getDeclaredClasses();
for(int i=0;i<C.length;i++) {
Classname = C[i].getName();
ClassesDisplayActivity.your_array_list3.add(Classname);
Log.i("Ramu","classname "+ C[i].getName());
}
}
}
It is not possible to determine at runtime all of the classes that are in a package using a standard class loader.
You might have some luck with this library though:
https://code.google.com/p/reflections/
Package is not a class. You cannot call Class.forName() for package and access classes that belong to class using getDelcaredClasses().
I do not know what do you really need, so I'd recommend you to explain this in separate question. probably you will receive better solutions.
However if you really need this you have to do the following:
Get your classpath by calling System.getProperty(java.class.path)
split this property to its elements by colon
iterate over the list and read each resource. If resource is jar you can use ZipInputStream, if it is a directory use File class.
filter list of resources you got at #3.
Fortunately you can use 3rd party library named Reflections that helps you to do all this without writing code.
I have a library which is written in C++ (actually a Firefox plugin, xyz.dll) and I need to access its methods from Java.
public class AccessLibrary {
public interface Kernel32 extends Library {
public void showVersion();
}
public static void main(String[] args) {
Kernel32 lib = (Kernel32) Native.loadLibrary("xyz.dll", Kernel32.class);
lib.showVersion();
}
}
While executing got the following error:
java -jar dist/accessLibrary.jar
Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'showVersion': The specified procedure could not be found.
In the native library source code, the method is defined like this
void CPlugin::showVersion() {
/* ... */
}
I am very new to Java. May be I am missing something basic. Looked into similar questions but none of them solves my problem.
Forgot to mention I am using Windows 7 64bit and Java 7.
First, you cannot export a class method and load it into java. The name will get mangled, and java wouldn't know how to call it properly. What you need to do is break it out into a separate function on its own.
After that:
As already pointed out, make sure you export the function. You can export using one of two ways. The first is what is mentioned, which is to use __declspec( dllexport ). The second is to put it into the def file.
Additionally, make sure you mark it as extern "C" otherwise the name will get mangled. All the details are here: Exporting functions from a DLL with dllexport
So the the signature should be something like this:
extern "C" __declspec(dllexport) void showVersion () {
}
Finally, the depends tool can be downloaded here: http://www.dependencywalker.com/
I think your native library needs to provide a C-style interface, for example
__declspec( dllexport ) void showVersion() {
/* ... */
}
Ideally, take a look at your DLL with depends.exe (which is available through the Windows SDK), there you'll see if your DLL provides the correct function exports.
I am new in Java, searched for this question in google and stackoverflow, found some posts, but still I can't understand.
I want to use DLL libary (C++) methods from Java. I use JNA for this purpose. JNA found my library but it can't find my method:
Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'LoadCurrentData': The specified procedure could not be found.
My code:
package javaapplication1;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
import com.sun.jna.Pointer;
public class JavaApplication1 {
public interface LibPro extends Library {
LibPro INSTANCE = (LibPro) Native.loadLibrary(
(Platform.isWindows() ? "LibPro" : "LibProLinuxPort"), LibPro.class);
public short LoadCurrentData();
}
public static void main(String[] args) {
LibPro sdll = LibPro.INSTANCE;
sdll.LoadCurrentData(); // call of void function
}
}
I looked in my DLL with Depency Walker Tool and saw that my function name has prefix and suffix - it looks like _LoadCurrentData#0
Thanks for response!
P.S. I found good example which works http://tutortutor.ca/cgi-bin/makepage.cgi?/articles/rjna (Listing 6).
I'd say that you need to apply correct name mapper, as you noticed function name got mangled, you need to register CallMapper that will implement the same mangling as your compiler.
Here is a revelant entry from JNA homepage:
Use a dump utility to examine the names of your exported functions to make sure they match (nm on linux, depends on Windows). On Windows, if the functions have a suffix of the form "#NN", you need to pass a StdCallFunctionMapper as an option when initializing your library interface. In general, you can use a function mapper (FunctionMapper) to change the name of the looked-up method, or an invocation mapper (InvocationMapper) for more extensive control over the method invocation.
Here is a possibly revelant question: renaming DLL functions in JNA using StdCallFunctionMapper