如何使用Java处理va_list参数,从本地库接收它?在JNA回调函数中处理va_list参数
我正在使用便于通过回调函数进行日志记录的C库。该库是libghoto2,我正在使用JNA封装器libgphoto2-java访问其功能。 有关应如何完成日志记录的示例,请参见this C file中的errordumper
方法。
我已经设法使用库的gp_log_add_func
添加一个Java编写的回调函数。唯一的问题是,回调函数的签名包含一个va_list
参数,我不知道如何处理。
由于C example from earlier显示,va_list args
直接传递到vfprintf
。读取vfprintf
manual,很明显它是某种可迭代的数据结构,它已经被“va_start
宏初始化”,并且在迭代使用va_arg
后需要使用va_end
进行清理。 但我发现保留JVM不会崩溃的唯一方法是使args
类型参数的类型为com.sun.jna.Pointer
,而String[]
或Object[]
会更合适。
如何从这个va_list中获取数据?
N.B.为了得到gp_log_add_func访问,我添加了一些Java代码:
添置org.gphoto2.jna.GPhoto2Native:
int gp_log_add_func(int logLevel, LogFunc func, Pointer data);
创建org.gphoto2.jna.LogFunc:
public interface LogFunc extends Callback {
public static final int GP_LOG_ERROR = 0;
public static final int GP_LOG_VERBOSE = 1;
public static final int GP_LOG_DEBUG = 2;
public static final int GP_LOG_DATA = 3;
public static final int GP_LOG_ALL = GP_LOG_DATA;
//the args argument is a va_list
public void log(int logLevel, String domain, String format, Pointer args, Pointer data);
}
org.gphoto2.jna.LogFunc的实施和使用:
LogFunc callback = new LogFunc() {
public void log(int logLevel, String domain, String format, Pointer args, Pointer data) {
System.out.println("[" + domain + "] " + format);
System.out.println(args.toString());
}
};
GPhoto2Native.INSTANCE.gp_log_add_func(LogFunc.GP_LOG_ALL, callback, null);
您必须查看相关平台上的va_list的实际实现(从头文件(vararg.h)开始,并且可能需要深入研究编译器细节)。 va_list通常是一个指向堆栈的指针,各种提取参数只是简单地抵消将指针移动一个适当大小偏移量的操作。你必须使用指针手动提取东西,使用指针等各种数据提取方法。getInt(int offset),取决于您尝试访问的类型。 – technomage
这就是我所害怕的。从纯粹主义的角度来看,JNA/Java业务应该与任何本地业务分开。这是特别令人担忧的,因为我目前正在使用openSuse进行开发,并可能稍后想要在OS X上进行部署。不幸的是,我不太了解C/C++,但是有没有办法使用第二个本地库来转换va_list更多JNA可管理? – derabbink
JNA应该为va_list处理提供映射当然是一个有争议的案例。随意在上面打开一个问题。 – technomage