I have written some code in C which I want to call from Java. What I have done is I have a function in my c code which calls another c function from libspotify and I am trying to write a Java Wrapper using JNA to call my c function.
I have written a simple login function for spotify in c which is actually working. Here is a link to that c file which has the method
https://github.com/shroffrushabh/libspotify_java/blob/master/jukebox.c
The next step I followed is, instead of using the make file provided in the libspotify examples I used the following cmd to compile and create a .so file
gcc -o libspot.so -shared jukebox.c appkey.c
This is what my java file looks like
import com.sun.jna.Library;
import com.sun.jna.Native;
public class SpotifyTest {
public interface JukeBox extends Library {
public int login();
}
static public void main(String argv[]) {
JukeBox jk = (JukeBox) Native.loadLibrary("spot", JukeBox.class);
jk.login();
}
}
The following are the commands to compile and run the java file
javac -classpath jna-4.0.0.jar SpotifyTest.java
java -classpath jna-4.0.0.jar:. SpotifyTest
Following is the exception I get:
java.lang.UnsatisfiedLinkError: /home/rushabh/libctest.so: undefined symbol: sp_session_create
I am not sure what is going wrong here, but here is what I am thinking, there is a sp_session_create function in libspotify(the C api which spotify has provided) which I am calling in my c code, so I think I need to somehow link the libspotify library when I am trying to generate my .so file. It would be great if you could give me some suggestions on how to solve this problem
You need to link in the spotify library.
This should be done when you're compiling libspot.so. This can be done with:
-L/path/to/spotify/library
This should be something/libspotify/lib, and is likely the directory where you built libspot.so. You may also need to specify:
-I/path/to/spotify/includes
after 2 days of researching this is how I got it to work, following is the command I used to generate the .so file.
gcc -L~/Downloads/libspotify-12.1.51-Linux-i686-release/lib -shared appkey.c jukebox.c -lspotify -o libspot.so
Rest of the steps to execute to Java file are same as above.
Thank you Erick Robertson and Petesh for your help :)
Related
I want to check that a filesystem is ntfs or fat32 and so on, and when i want to run it i get this:
java.lang.UnsatisfiedLinkError: Unable to load library 'Kernel32': Native library (linux-x86-64/libKernel32.so) not found in resource path ([file:/home/nszabo/workspace/Vidux/bin/, file:/home/nszabo/workspace/Vidux/external/common/org-json-2010-12-28.jar, and so on...
I tried this:
java -Djava.library.path="VolumeInformation.java"> -jar /usr/share/java/jna.jar
Error: Could not find or load main class .usr.share.java.jna.jar
What can be a problem? Thanks all for the help!
UPDATE:
here is my code where drop the error.
Kernel32.INSTANCE.GetVolumeInformation(
"C:\\",
lpVolumeNameBuffer,
nVolumeNameSize,
lpVolumeSerialNumber,
lpMaximumComponentLength,
lpFileSystemFlags,
lpFileSystemNameBuffer,
nFileSystemNameSize);
next one:
public static void main(String[] args) {
getFileSystemName();
}
and the final in Kernel32.java:
public Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("Kernel32", Kernel32.class, WIN32API_OPTIONS);
In Linux you can run the mount command with Runtime.exec() and parse the output to check which filesystems are mounted and which type they have.
You are trying to run Windows API functions on linux. You need to call filesystem inspection functions appropriate to linux instead.
To do so requires either a separate mapping (getfsfile("/path/to/fs") and look at the fs_vfstype field within the returned structure), or you can invoke the mount command as a process and parse its results as suggested by #ralf-m-petter.
I want to create c library and use it in my java code on an Linux OS. I'm trying to understand and implement natural library concept.
I'm following this tutorial
http://diglib.stanford.edu:8091/~testbed/doc/JavaUsage/JNI/tutorial.txt
Which is helpful me to understand concept a little. However, I get errors when I try to do it myself. I searced for errors I am getting but none of solutions helped.
Main class code and class for natural library I wrote is as follows:
package natLib;
import natLib.getKeyPressed;
public class main {
public static void main(String[] args) {
getKeyPressed natlab=new getKeyPressed();
char c=natlab.keyboardPressedKey();
}
}
package natLib;
public class getKeyPressed {
static {
System.loadLibrary("natlab");
}
public native char keyboardPressedKey();
}
when I write "javac main.java"
I get errors like
"main.java:6: error: cannot find symbol
getKeyPressed natlab=new getKeyPressed();"
And when I skip for main and just do javac prcess for class with native method, try to obtain a header file
javah -jni getKeyPressed.class
Although there is a file as getKeyPressed.class, I get errors like:
"Exception in thread "main" java.lang.IllegalArgumentException: Not a valid class name: getKeyPressed.class"
I try it without .class extention it says
"Error: Could not find class file for 'getKeyPressed'."
It says that even when I make getKeyPressed class file by copying getKeyPressed.class.
It seems I am making a major mistake, any suggestions to solve this?
javah expects a fully qualified classname. (e.g. natLib.getKeyPressed, not just getKeyPressed)
Here is the thing: I am trying to run the example program in the joda-time project.
The start of the Examples.java file looks like this:
package org.joda.example.time;
import java.util.Locale;
import org.joda.time.DateTime;
import org.joda.time.Instant;
/**
* Example code demonstrating how to use Joda-Time.
*
* #author Stephen Colebourne
*/
public class Examples {
public static void main(String[] args) throws Exception {
try {
new Examples().run();
} catch (Throwable ex) {
ex.printStackTrace();
}
}
And all the classes for compiling this Example.java is in a joda-time-2.3.jar.
I can successfully compile this program by using
javac -cp somewhere/joda-time-2.3.jar Example.java
And it generate an Example.class, but I jut cannot execute that.
So far I have tried:
java Examples
java -cp somewhere/joda-time-2.3.jar Examples
java -cp somewhere/joda-time-2.3.jar org.joda.example.time.Examples
But they all generate this kind of errors:
Error: Could not find or load main class org.joda.example.time.Example
Error: Could not find or load main class Examples
And I've tried both in the org/joda/example/time folder and the parent folder of org
Anyone can give an instruction on how to execute that? Really appreciate it!
Error: Could not find or load main class org.joda.example.time.Example
public class Examples {
Name of your class is Examples not Example
EDIT
Sorry for late reply...
To execute specific Java program you need to bring control to root directory so if your class is in abc/newdir/Examples.java you need to use cd command (in windows) to lead control to root directory and than compile or you can defeneitly go for the suggestion of kogut.
C:/abc/newdir>java -cp somewhere/joda-time-2.3.jar Examples
Modify your classpath parameter, so it should include directory where Example.class was generated.
In case of out/org/joda/example/time/Example.class you need to use
java -cp somewhere/jodata-time-2.3.jar:out org.joda.example.time.Example
OK, again having some problems with caliper.
I am now running on Linux, trying to use the beta snapshot. I am attempting to run Google's caliper via commandline using just the jar. (Beta snapshot)
I do not have access to maven on this machine, and installing it is out of the question. I would just like to use a jar and, maybe once this is working, I can write up a script or something.
Here is what I am doing:
1. Using small example Benchmark:
import com.google.caliper.Benchmark;
public class Tutorial {
public static class Benchmark1 {
#Benchmark void timeNanoTime(int reps) {
for (int i = 0; i < reps; i++) {
System.nanoTime();
}
}
}
}
2. Compile with javac -cp caliper-1.0-beta-SNAPSHOT-all.jar Tutorial.java
3. (Attempt to) run with
java -cp caliper-1.0-beta-SNAPSHOT-all.jar com.google.caliper.runner.CaliperMain Tutorial.Benchmark1, receive message Benchmark class not found: Tutorial.Benchmark1.
I've tried to work this out from bits and pieces of information from various sources but I am really having a heck of a time with this. I would appreciate any input.
I believe you really need no maven, this should work.
Your own class doesn't get found and I think it's a problem of your classpath. As they're usually more problem with nested classes try simply
java -cp caliper-1.0-beta-SNAPSHOT-all.jar com.google.caliper.runner.CaliperMain Tutorial
If the message changes to something like "class contains no benchmarks", then you'll know more. If you insists on using nested class, you may need to call Tutorial$Benchmark1 (unprobable, but possible; java class naming is sick).
Please try also
java -cp caliper-1.0-beta-SNAPSHOT-all.jar Tutorial.Benchmark1
to see if your class lies on the classpath (the message should change to something like "no main method").
See also this older post.
I use Eclipse Java 32Bit JDK. I am trying to import a 32-Bit DLL, which i got very few documentation for. I am using com.sun.jna.
The documentation tells me to call the method InitImagerIPC without any parameters.
As in this example i created an interface:
public interface ImagerIPC extends com.sun.jna.win32.StdCallLibrary{
HRESULT InitImagerIPC ();
}
When I try to import the DLL no error occurs.
ImagerIPC lib = (ImagerIPC) Native.loadLibrary ("ImagerIPC", ImagerIPC.class);
But I receive an UnsatisfiedLinkError if I mistype my DLL name. So I guess it's loaded correctly?
But when I try to call
lib.InitImagerIPC();
I get the UnsatisfiedLinkError. :(
Where's the mistake?
BTW: The DLL Export Viewer pulls out this info for the wanted method:
_InitImagerIPC#0 0x10001fc0 0x00001fc0 45 (0x2d)
ImagerIPC.dll J:\<my Path>\ImagerIPC.dll Exported Function
I am not sure about the naming. Do I also have to add the _?
Your DLL uses the stdcall calling convention, which typically has the compiler mangle function names to include the arguments' stack size. You need to use a StdCallFunctionMapper passed in as the Library.OPTION_FUNCTION_MAPPER option when you load your library (or recompile your library to use undecorated names).
Library.loadLibrary("myLib", myLib.class, new HashMap() { { put(Library.OPTION_FUNCTION_MAPPER, new StdCallFunctionMapper()); } });