3 messages in net.java.dev.jna.usersincorrect call-by-value semantics?
FromSent OnAttachments
David MonniauxMar 13, 2008 8:01 am 
David MonniauxMar 13, 2008 8:49 am 
Timothy WallMar 13, 2008 10:30 am 
Actions with this message:
Paste this link in email or IM:
Paste this link in email or IM:
Atom feed for this thread
Paste this URL into your reader:
Subject:incorrect call-by-value semantics?Actions...
From:David Monniaux (Davi@imag.fr)
Date:Mar 13, 2008 8:01:07 am
List:net.java.dev.jna.users

Platform: IA32 Linux, if that matters.

There is I think something wrong with the way that JNA handles objects that are returned-by-value by a C function (here, f1), then later passed by reference to another C function (here, f2). These objects carry a dynamic type implementing the interface Structure.ByValue, even though their static type does not. When JNA calls the f2 function, it apparently tests whether to pass the parameter by value or by reference not according to the type signature of f2 (type Foobar vs type Foobar.ByValue) but according to the dynamic type of the parameter.

As a consequence the following program prints out: $ java -Djna.library.path=. -classpath .:jna.jar CallByValueBug 42 0x812ab58->x = 5 Called by value!!!

The same f2 function is first called by reference (correct) but f2(vRet) calls it by value...

Current workaround: any object returned by value (of type Foobar.ByValue) should be copied field-by-field into an object of type Foobar before attempting any further calls.

Regards, DM

import com.sun.jna.Library; import com.sun.jna.Native; import com.sun.jna.Structure;

public class CallByValueBug { public static class Foobar extends Structure { public int x; public static class ByValue extends Foobar implements Structure.ByValue {} }

public interface CallByValueBugLibrary extends Library { CallByValueBugLibrary INSTANCE = (CallByValueBugLibrary) Native.loadLibrary("callbyvaluebug", CallByValueBugLibrary.class);

Foobar.ByValue f1(); void f2(Foobar v); }

public static void main(String[] args) { Foobar vRet = CallByValueBugLibrary.INSTANCE.f1(); System.out.println(vRet.x); System.out.flush(); Foobar vCreated = new Foobar(); vCreated.x = 5; CallByValueBugLibrary.INSTANCE.f2(vCreated); CallByValueBugLibrary.INSTANCE.f2(vRet); } }

#include <stdio.h>

struct foobar { int x; };

struct foobar f1(void) { struct foobar r = { 42 }; return r; }

void f2(struct foobar *v) { if (v != (struct foobar*) 42) { printf("%p->x = %d\n", v, v->x); } else { printf("Called by value!!!\n"); } }