java - 处理 JNA 回调函数中的 va_list 参数

标签 java callback jna variadic-functions libgphoto2

如何使用 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.PointerString[]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/

相关文章:

java - 在 Java 8 中禁用 TLS 1.0

c++ - 如何使用 std::function 作为 C 风格的回调

javascript - ng-if 从范围中删除指令后执行的指令回调

javascript - 地理位置表单不等待回调

Java JNA 写入内存 boolean 值

java - 从android studio中的mysql数据库检索图像

java - 如何使用私有(private)构造函数测试最终类?

Java 和 XML : How to get list of included files

java - 从 Java 传递到 C 后未初始化的 JNA 结构数组

java - 使用 java 检查 Internet 连接,无需 URL 测试连接