title: processing va_list argument in JNA callback function
body: <p>How can I process a va_list argument with Java, having received it from the native library?</p>
  
  <p>I am using a C library that facilitates logging through a callback function. The library is <a href="http://gphoto.org/proj/libgphoto2/" rel="nofollow">libghoto2</a> and I am using a JNA wrapper <a href="http://code.google.com/p/gphoto2-java/" rel="nofollow">libgphoto2-java</a> to access its features.
  See the <code>errordumper</code> method in <a href="http://fossies.org/unix/privat/libgphoto2-2.4.14.tar.gz%3aa/libgphoto2-2.4.14/examples/preview.c" rel="nofollow">this C file</a> for an example of how the logging should be done.</p>
  
  <p>I've managed to add a Java-written callback function using the library's <a href="http://gphoto.org/doc/api/gphoto2-port-log_8h.html#93c15da75612eccac26bf835e5ee75ca" rel="nofollow"><code>gp_log_add_func</code></a>. The only problem is, the callback function's signature contains a <code>va_list</code> argument that I don't know how to process.</p>
  
  <p>As the <a href="http://fossies.org/unix/privat/libgphoto2-2.4.14.tar.gz%3aa/libgphoto2-2.4.14/examples/preview.c" rel="nofollow">C example from earlier</a> shows, <code>va_list args</code> is passed directly into <code>vfprintf</code>. Reading the <a href="http://www.thinkage.ca/english/gcos/expl/c/lib/vfprin.html" rel="nofollow"><code>vfprintf</code> manual</a> it becomes clear that it is some sort of iterable data structure that has "been initialized with the <code>va_start</code> macro" and after iterating using <code>va_arg</code> a cleanup with <code>va_end</code> is required.
  But the only way I found for keeping the JVM from crashing, is to make the <code>args</code> parameter of type <code>com.sun.jna.Pointer</code> while a <code>String[]</code> or <code>Object[]</code> would be more suitable.</p>
  
  <p><strong>How do I get the data out of this va_list?</strong></p>
  
  <p>N.B. In order to get access to <a href="http://gphoto.org/doc/api/gphoto2-port-log_8h.html#93c15da75612eccac26bf835e5ee75ca" rel="nofollow">gp_log_add_func</a>, I added some Java code:</p>
  
  <p>Additions to <em>org.gphoto2.jna.GPhoto2Native</em>:</p>
  
  <pre><code>int gp_log_add_func(int logLevel, LogFunc func, Pointer data);
  </code></pre>
  
  <p>Created <em>org.gphoto2.jna.LogFunc</em>:</p>
  
  <pre><code>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);
  }
  </code></pre>
  
  <p>The implementation and usage of <em>org.gphoto2.jna.LogFunc</em>:</p>
  
  <pre><code>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);
  </code></pre>