I am trying to use a C++ API in Java with JNA. This API uses callbacks to handle sessions events.
The only resource I found on how to register callbacks with JNA is this, and it deals with C callbacks, and I don't really know how it can be extended to C++ non-static callbacks.
EDIT: I just found this resource, I think the "Revisiting Callbacks" chapter might help.
All the function pointers for the callbacks are stored in the following sp_session_callbacks
structure:
/**
* Session callbacks
*
* Registered when you create a session.
* If some callbacks should not be of interest, set them to NULL.
*/
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);
// Other callbacks function pointers
} sp_session_callbacks;
The Java class I created to described this structure is the following:
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 the function pointers by com.sun.jna.Function objects in this case in your opinion?
Each session is represented by a sp_session
object, which is a C++ opaque struct. I do have a handle on the sp_session_callbacks
object when I initialize it though.
Here is a code snippet from my 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
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
How should I register those callbacks function to actually do something on the Java side when they are triggered?
Thank you!
EDIT
New code using Callback instead of Function:
public class sp_session_callbacks extends Structure{
public LoggedIn logged_in;
/* Other callbacks... */
}
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
The sessionCreate() call is throwing a JRE fatal error (EXCEPTION_ACCES_VIOLATION 0x0000005) when cfg.logged_in is not set to null but to an instance of LoggedIn. The weird thing is that the 2 callbacks logged_in and connection-error have the same signature, and when cfg.connection_error is set, it doesn't throw anything.