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对象表示函数指针有意义吗?

每个会话由一个 SPSession < /Cord>对象表示,它是C++不透明结构。不过,当我初始化
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_会话本身。