Я пытаюсь использовать C ++ API в Java с JNA. Этот API использует обратные вызовы для обработки событий сеансов.
Единственный ресурс, который я нашел о том, как зарегистрировать обратные вызовы с помощью JNA, - это this , и он имеет дело с обратными вызовами C, и я не знаю, как его можно распространить на нестатические обратные вызовы C ++.
РЕДАКТИРОВАТЬ: Я только что нашел этот ресурс , я думаю, что глава "Пересмотр обратных вызовов" может помочь.
Все указатели функций для обратных вызовов хранятся в следующей структуре sp_session_callbacks
:
/**
* 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;
Java-класс, который я создал для описания этой структуры, выглядит следующим образом:
public class sp_session_callbacks extends Structure{
public Function logged_in;
public Function logged_out;
public Function connection_error;
public Function message_to_user;
}
Имеет ли смысл представлять указатели на функции com.sun.jna. По вашему мнению, функциональные объекты в этом случае?
Каждый сеанс представлен объектом sp_session
, который является непрозрачной структурой C ++. У меня действительно есть дескриптор объекта sp_session_callbacks
, когда я его инициализирую.
Вот фрагмент кода из моего основного класса:
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
Как мне зарегистрировать функцию обратного вызова, чтобы на самом деле что-то делать на стороне Java, когда они запускаются?
Спасибо!
EDIT
Новый код с использованием функции обратного вызова вместо функции:
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);
}
Основной класс:
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
Вызов sessionCreate () вызывает фатальную ошибку JRE (EXCEPTION_ACCES_VIOLATION 0x0000005), когда для cfg.logged_in задано не нулевое значение, а экземпляр LoggedIn. Странно то, что 2 обратных вызова logged_in и connection-error имеют одинаковую сигнатуру, и когда установлен cfg.connection_error, он ничего не выдает.