I am trying to use the C ++ API in Java with JNA. This API uses callbacks to handle session events.
The only resource I found on how to register callbacks with JNA is and it deals with C callbacks, and I don’t really know how to extend this to non-static C ++ callbacks.
EDIT: I found this resource , I think the chapter “Revisiting Callbacks” can help.
All function pointers for callbacks are stored in the following sp_session_callbacks structure:
typedef struct sp_session_callbacks { void (__stdcall *logged_in)(sp_session *session, sp_error error); void (__stdcall *logged_out)(sp_session *session); void (__stdcall *connection_error)(sp_session *session, sp_error error); void (__stdcall *message_to_user)(sp_session *session, const char *message);
The generated Java class described in this structure is as follows:
public class sp_session_callbacks extends Structure{ public Function logged_in; public Function logged_out; public Function connection_error; public Function message_to_user; }
Does it make sense to represent pointers to com.sun.jna.Function functions in this case, in your opinion?
Each session is represented by an sp_session object, which is an opaque C ++ structure. I have a handle to the sp_session_callbacks object when I initialize it.
Here is a snippet of code from my main class:
JLibspotify lib = (JLibspotify)Native.loadLibrary("libspotify", JLibspotify.class); sp_session_config cfg = new sp_session_config(); sp_session_callbacks sessCallbacks = new sp_session_callbacks();
How do I register the callbacks function to actually do something on the Java side when they start?
Thanks!
EDIT
New code using callback instead of function:
public class sp_session_callbacks extends Structure{ public LoggedIn logged_in; } public interface LoggedIn extends StdCallCallback { public void logged_in(sp_session session, int error); }
Main class:
JLibspotify lib = (JLibspotify)Native.loadLibrary("libspotify", JLibspotify.class); sp_session_config cfg = new sp_session_config(); /* Some cfg config here */ sp_session_callbacks sessCallbacks = new sp_session_callbacks(); // Handle on my sp_session_callbacks object LoggedIn loggedInCallback = new LoggedIn(){ public void logged_in(sp_session session, int error){ System.out.println("It works"); } }; sessCallbacks.logged_in = loggedInCallback; /* Setting all the other callbacks to null */ cfg.callbacks = sessCallbacks; PointerByReference sessionPbr = new PointerByReference(); int errorId = lib.sessionCreate(cfg, sessionPbr); sp_session session = new sp_session(sessionPbr.getValue()); // handle on my sp_session object
Calling sessionCreate () causes a false JRE error (EXCEPTION_ACCES_VIOLATION 0x0000005) when cfg.logged_in is not null but an instance of LoggedIn. The strange thing is that the 2 callbacks logged_in and the connection error have the same signature, and when cfg.connection_error is set, it throws nothing.