C++;非静态回调和JNA 我尝试使用java中的C++ API和JNA。此API使用回调来处理会话事件 P> >我发现如何用JNA登记回调,它处理C++回调,我不知道它如何扩展到C++非静态回调。
编辑:我刚刚发现,“重新访问回调”一章可能会有所帮助 回调的所有函数指针都存储在以下C++;非静态回调和JNA 我尝试使用java中的C++ API和JNA。此API使用回调来处理会话事件 P> >我发现如何用JNA登记回调,它处理C++回调,我不知道它如何扩展到C++非静态回调。,java,c++,pointers,callback,jna,Java,C++,Pointers,Callback,Jna,编辑:我刚刚发现,“重新访问回调”一章可能会有所帮助 回调的所有函数指针都存储在以下sp\u session\u回调结构中: /** * 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 (
sp\u session\u回调
结构中:
/**
* 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.function对象表示函数指针有意义吗?
每个会话由一个sp\u session\u回调对象时,它确实有一个句柄
以下是我的主类的代码片段:
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
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
当这些回调被触发时,我应该如何注册这些回调函数以在Java端实际执行某些操作?
谢谢大家!
编辑
使用回调而不是函数的新代码:
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
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
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
当cfg.logged\u in未设置为null而是设置为LoggedIn的实例时,sessionCreate()调用将引发JRE致命错误(异常\u访问\u冲突0x0000005)。奇怪的是,登录的两个回调和连接错误具有相同的签名,当设置cfg.connection\u error时,它不会抛出任何东西。来自javadoc函数的表示本机方法,如果要调用java方法,必须为每个函数指针创建一个
若您只使用java回调而并没有使用本机函数,那个么您可以用回调替换函数。(根据使用的调用约定,您可能希望改用StdCallLibrary.StdCallCallback)
基本上,为了将任何类型的回调连接到对象的成员函数中,它必须传递目标函数和对象的实例以满足第一个不可见参数。这里的问题是JNA只接受特定的函数格式。因此,你必须尽可能地解决这个问题。可悲的是,在C++中,这会导致使用临时全局变量,但是只要您专注于将控制传递回对象,就可以保持良好的面向对象设计。
它与“C vs C++”无关。您只需要了解成员函数调用的含义,以及它的编译结果
myObject.memberFunction(); // This is what the programmer sees.
memberFunction(&myObject); // This is what the compiler sees.
成员函数是简单地将对象作为第一个参数的函数的奇特描述。它只是在实际参数列表中不可见
void MyClass::memberFunction() // This is the declaration the programmer sees.
void memberFunction(MyClass* this) // This is what the compiler sees.
<>从这里,C++添加了特殊的语义,使其易于以面向对象的方式工作。
简而言之,在JNA本身添加了这样的机制之前,实际上你永远无法直接将一个对象的成员函数直接连接到。你的例子中的所有函数指针都是C,没有C++特性来与JNA混淆。是一个典型的C++。Strut,因为它是标准C的一部分。我不明白你的意思是用非静态字段,只有静态字段的结构是没有用的。(然后,我又是一个java程序员,所以我可能会混淆静态的意思)。@josefx好的。我也是一名Java程序员,对C/C++不太了解,这就是为什么我问这个问题。我所说的非静态字段,是指一个可以为结构的两个不同实例保存不同值/对象的字段。我认为这个概念是由OOP带来的,所以我假设这在不是OO语言的C中是不可能的,但我没有当然。@josefx谢谢你,在阅读了我引用的第二篇文章之后,我认为这是解决方案。我在我的第一篇文章中添加了新代码。@josefx我在传递error
参数时遇到了问题,该参数的类型为sp\u error
(整数枚举)。当我使用int或IntByReference时,它不起作用。我该怎么做?(我在最初的帖子末尾添加了代码)。谢谢!@josefx Oops,对不起,上一条评论中的信息错误。只有登录才会导致JRE崩溃。所以我想这是因为它实际上被调用了。@nathanb sp_错误不是通过引用传递的,所以为了类型安全,您应该使用int本身或创建一个只包含int的类。@nathanb您通过引用传递sp_会话吗?我忘了在我的示例代码中,它应该使用指向sp_会话的指针,而不是sp_会话本身。