如何使用 Java 处理从 native 库接收到的 va_list 参数?
我正在使用一个 C 库,该库有助于通过回调函数进行日志记录。图书馆是libghoto2我正在使用 JNA 包装器 libgphoto2-java以访问其功能。
请参阅errordumper
this C file中的方法有关如何完成日志记录的示例。
我已经成功使用库的 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 中获取数据?
注意为了访问 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);
最佳答案
这是一个可变参数实现示例,其中包含一些有关可变参数宏正在执行的操作的提示:
int printf(const char* fmt, ...) {
va_list argp;
va_start(argp, fmt); // usually something like: argp = (char *)&fmt - sizeof(void *);
int arg1 = va_arg(argp, int); // *(int *)argp; argp += sizeof(int);
void *arg2 = va_arg(argp, void*); // *(void **)argp; argp += sizeof(void *);
float arg3 = va_arg(argp, float); // *(float *)argp; argp += sizeof(float);
va_end(argp); // no-op
}
所以它基本上是一堆使用堆栈指针的指针算术。 JNA 的问题在于您无权访问堆栈指针,并且您可能需要在 native 级别扩展 JNA 的回调机制以专门处理可变参数回调以提供堆栈指针。
即使这样也可能存在问题。从上面的示例中可以看出,您实际上需要可变参数函数签名的最后一个命名参数的地址才能访问可变参数。一般来说,这会非常棘手。
关于java - 处理 JNA 回调函数中的 va_list 参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10977219/