You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Apologies if this is something obvious but I've looked through the docs, google forum, and stack overflow and couldn't find anything.
I'm having an issue passing a union by value whose first field is an int. I've simplified the issue to the following:
(Note - the library is implemented in C++ and is accessed through a stable ABI layer in C; details below the code sections)
C/C++
typedef union{
int a;
double b;
int c;
} test_union;
EXTERN_C_SPEC_ DLL_SPEC_ int
UnionTest_ABI( int a, int b, test_union test, int c, int d);
int
UnionTest_ABI( int a, int b, test_union test, int c, int d)
{
switch(b){
case 0:
std::cout<< "UNIONTEST: 0 : a=" << a << " b=" << b << " VAL="
<< test.a << " c=" << c << " d=" << d << std::endl;
break;
case 1:
std::cout<< "UNIONTEST: 1 : a=" << a << " b=" << b << " VAL="
<< test.b << " c=" << c << " d=" << d << std::endl;
break;
case 2:
std::cout<< "UNIONTEST: 2 : a=" << a << " b=" << b << " VAL="
<< test.c << " c=" << c << " d=" << d << std::endl;
}
return 0;
}
Java
public interface CLib extends Library {
public static class TestUnion extends Union {
public int a;
public double b;
public int c;
public static class ByValue extends TestUnion implements Union.ByValue {
};
}
int UnionTest_ABI( int a, int b, TestUnion.ByValue v, int c, int d);
}
The int/union is not being passed in and args 'c' and 'd' are one position to the 'left'. Some type of alignment issue I guess? As you can imagine this does or does not crash in different ways depending on the function.
But, if I change the Java Union to the following, it works:
public static class TestUnion extends Union {
public long a;
public double b;
public int c;
public static class ByValue extends TestUnion implements Union.ByValue {
};
}
I think I can explain the problem - and indeed this is a bug. If I read the ABI document correctly https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-1.0.pdf , Page 21+22), the union should be passed as an INTEGER class. But JNA sets the ffi_type of the union to double, which is class SSE. The size and also the alignment will be right, but the argument will be passed wrong.
INTEGER and SSE parameter are passed via different registers. And this also explains the visible effect, the integer parameter seem to be shifted, because native expects five parameters in INTEGER class registers, while ffi only passes four in integer registers.
FWIW, by replacing the ints with longs in the (Java) union I was able to get it to work on x86 and x64, on windows and linux; but given my limited understanding of JNA/ffi I have no idea how fragile that temporary workaround is.
Apologies if this is something obvious but I've looked through the docs, google forum, and stack overflow and couldn't find anything.
I'm having an issue passing a union by value whose first field is an int. I've simplified the issue to the following:
(Note - the library is implemented in C++ and is accessed through a stable ABI layer in C; details below the code sections)
C/C++
Java
Test
C Output
The int/union is not being passed in and args 'c' and 'd' are one position to the 'left'. Some type of alignment issue I guess? As you can imagine this does or does not crash in different ways depending on the function.
But, if I change the Java Union to the following, it works:
JRE
JNA
System
Lib
Thanks,
jon
The text was updated successfully, but these errors were encountered: