Recent Changes - Search:

edit SideBar

JNA

Wikipedia says: "Java Native Access provides Java programs easy access to native shared libraries without using the Java Native Interface."

Below are notes about JNA and some issues I faced.

Resources

JNA Debugging

  • Java properties: Invoke java with these properties set
    • -Djna.boot.library.path=${PTII}/lib ? If set, then it should contain the path to the jnidispatch native shared library
      • "The jna.boot.library.path property is mainly to support jna.jar being included in -Xbootclasspath, where java.library.path and LD_LIBRARY_PATH are ignored. It is also useful for designating a version of the library to use in preference to any which may already be installed on the system."
      • JNA Native Class docs
      • JNA Javadoc overview summary Loading
    • -Djna.debug_load=true Print out info about how the file is found - JNA FAQ
    • -Djna.debug_load.jna Trace how JNA looks for its own native libraries (jnidispatch) - JNA FAQ
    • -Djna.dump_memory=true Cause toString() on a jna Native to also print the memory. Excellent for finding alignment issues. - JNA FAQ
    • -Djna.encoding
    • -Djna.library.path
      • "The search path for loaded native libraries may be modified by setting jna.library.path and a few other properties. You may also bundle native libraries in a jar file and have JNA automatically extract them for loading. See NativeLibrary for details. "
      • JNA Javadoc overview summary
      • Native.getWebStartLibraryPath() docs mention jna.library.path
    • jna.noclasspath=true If set, then don't use the Java classpath to find libraries. JNA Native Class docs
    • -Djna.nosys=true If set, then System.loadLibrary() is not called when looking for the JNA native library. JNA Native Class docs
    • -Djna.nounpack=true. If set, avoid automatic unpacking of the native library (useful for forcing failure if the JNA native library is not setup properly. JNA Native Class docs
    • -Djna.tmpdir Native.getTempDir() mentions jna.tmpdir
  • Java calls

Varags

JNA Varargs

"The C varargs function definition may be mapped to a Java varargs method definition. For example,
// Original C code
extern int printf(const char* fmt, ...);

// Equivalent JNA mapping
interface CLibrary extends Library {
int printf(String fmt, ...);
}
"Varargs are not supported with direct mapping. The reason for this is that the direct mapping optimization does little to no translation of the incoming arguments, and any Object arguments would require introspection that defeats the purpose of the direct-mapping optimizations. It's also a lot more work than the benefit you get from implementing it."
"Hello, I'm new to JNA so first of all I would just like to say that I think it's very awesome"
"Now for my question. I'm using direct mapping and I read on the project front page that a few types of arrays are not supported (Pointer/String/WString/NativeMapped) but since I didn't see Object in there I thought I would try using Object varargs since that translates to an Object array in bytecode. That blew up in my face when the class initializer ran though, giving the following error: class [Ljava.lang.Object; is not a supported argument type Are arrays not supported at all as argument types when using direct mapping?"
"I was trying to map the standard printf function by the way, using the signature int printf(String s, Object[] args)"
"Such a callback is problematic because there is no way for the native callback stub to generically the types of the varargs parameters in order to convert them into java objects or primitives. The type information is (presumably) embedded in the format string, rather than in the objects themselves, and that information isn't available to JNA."
"Mapping the second arg to Pointer is actually more accurate, since it represents the position of the arguments on the stack. Since your application knows how to parse the format string, it can walk the argument stack and extract each value appropriately using Pointer.getXXX functions with appropriate offsets. Not particularly elegant, but it should work."
"For dll functions which have "char *" or "...", I can use String and Java Varargs as method parameters and it works like a charm."
"However, when I tried to do the same with Callback:"
typedef int (*PFKT) (char *format, ...);

public interface PFKT extends Callback {
int callback(String format, Object ... parameters);
}
"JNA claims that it cannot find the right conversion to "parameters". It would run if I declare "parameters" as Pointer instead, but it is evidently not the best solution."
Any pointers on the issue?
  • Stack Overflow processing va_list argument in JNA callback function (June, 2012
    "You'll have to look at the actual implementation of va_list on the platform in question (start with the header file (vararg.h), and possibly delving into compiler specifics). va_list is usually a pointer onto the stack, with the various extraction args simply offset operations that move the pointer along by the appropriate size offset. You'll have to extract the stuff manually using the Pointer, using the various data extraction methods like Pointer.getInt(int offset), depending on the type you're attempting to access. –"
  • https://groups.google.com/forum/#!msg/jna-users/k-xidZOv04M/noanEPj7l98J Eric Chiu asking about JNA Varargs on the JNA list in November, 2012)
  • RFC: variadic closures in x86/x86_64 in December, 2013
    • D. Hogan asked for feedback about modify libffi to support variadic callbacks
    • Andrew Haley replied: "Why do you not define a variadic C function which does this:"
      void f1(int n, ...) {
      va_list ap;

      jintArray argsArray = (*env_p)->NewIntArray(n);
      jint *args = (*env_p)->GetIntArrayElements(argsArray, NULL);

      int argno = 0;
      va_start(ap, n);
      while (argno < n) {
      args[argno++] = va_arg(ap, int);
      }
      va_end(ap);
      (*env_p)->ReleaseIntArrayElements(argsArray, args, 0);
      (*env_p)->CallStaticVoidMethod(clsH, printargs, argsArray);
      }
      "to call this variadic Java code:"

      public static void printargs(int... args) {
      for (int i : args)
      System.out.print(i + " ");
      System.out.println();
      }
      "There is no reason that JNA cannot use this mechanism, is there?"
    • D.Hogan replied: "I'm sure it would work. A similar suggestion is mentioned in the CFFI documentation. It would require a C function for every assumed variadic processing convention. For instance, FMI requires #<Type><valueReference># which is not a typical printf/logger convention. I didn't go down that path because I thought the manual was asking for patches for a different way."

Patching JNA to work with Varargs CallBacks

As the libffi maintainers don't seem interested in supporting the functionality we require, here are patching instructions

Resources

Procedure

A branch with the variadic extensions may be found at https://github.com/cxbrooks/jna.

git clone https://github.com/cxbrooks/jna jna-cxbrooks
cd jna-cxbrooks
ant
cp build/jna.jar $PTII/lib/jna-4.1.0-variadic.jar

For each of the platforms, we need to create the appropriate native jar. See https://github.com/twall/jna/blob/master/www/ReleasingJNA.md.

For Mac and Linux, do:

git clone https://github.com/cxbrooks/jna jna-cxbrooks
cd jna-cxbrooks
ant
git add lib/native/xxx.jar
git commit -m "Updated for variadic support." lib/native/xxx.jar
git push

For Windows, see https://github.com/twall/jna/blob/master/www/WindowsDevelopmentEnvironment.md and follow the steps above. I used Cygwin.

Below is how it was created.

git clone https://github.com/twall/jna.git jna.git
cd jna.git
git checkout -b 4.1.0-variadic-closures 4.1.0 # create a local branch based off the 4.1.0 tag.
patch -p1 < jna_4.0_diff.txt
ant
cp build/jna.jar $PTII/lib/jna-4.1.0-variadic.jar

Below are the older instructions from D. Hogan

git clone https://github.com/twall/jna.git jna.git
cd jna.git
git checkout -b 4.0-variadic-closures 4.0 # create a local branch based off the 4.0 tag.
patch -p1 < jna_4.0_diff.txt
ant
cp build/jna.jar /path/to/ptII/lib/jna-4.0.0-custom.jar

Building JNA from sources

See Patching JNA to work with Varargs CallBacks above.

These instructions are for unpatched JNA trees.

Building JNA Under Linux

2015-02-23

Under RHEL 6.x with Java 1.8,

 git clone https://github.com/twall/jna.git jna.git
 cd jna.git
 ant

Failed with:

     [exec] gcc -m64 -W -Wall -Wno-unused -Wno-parentheses -fPIC  -O2 -fno-omit-frame-pointer -fno-strict-aliasing  -D_REENTRANT -DHAVE_PROTECTION -I"/usr/lib/jvm/jdk1.8.0_31/jre/../include" -I"/usr/lib/jvm/jdk1.8.0_31/jre/../include/linux" -I"/home/cxh/src/jna/jna.git/build/native-linux-x86-64" -I/home/cxh/src/jna/jna.git/build/native-linux-x86-64/libffi/include -DJNA_JNI_VERSION='"4.0.1"' -DCHECKSUM='"1a6047467b59e8748f975e03016ce3d9"' -c dispatch.c -o /home/cxh/src/jna/jna.git/build/native-linux-x86-64/dispatch.o
     [exec] In file included from dispatch.c:82:
     [exec] /usr/lib/jvm/jdk1.8.0_31/jre/../include/linux/jawt_md.h:29:22: error: X11/Xlib.h: No such file or directory
     [exec] /usr/lib/jvm/jdk1.8.0_31/jre/../include/linux/jawt_md.h:30:23: error: X11/Xutil.h: No such file or directory
     [exec] /usr/lib/jvm/jdk1.8.0_31/jre/../include/linux/jawt_md.h:31:27: error: X11/Intrinsic.h: No such file or directory
     [exec] In file included from dispatch.c:82:
     [exec] /usr/lib/jvm/jdk1.8.0_31/jre/../include/linux/jawt_md.h:43: error: expected specifier-qualifier-list before ‘Drawable’
     [exec] dispatch.c: In function ‘Java_com_sun_jna_Native_getWindowHandle0’:
     [exec] dispatch.c:3004: error: ‘JAWT_X11DrawingSurfaceInfo’ has no member named ‘drawable’
     [exec] make: *** [/home/cxh/src/jna/jna.git/build/native-linux-x86-64/dispatch.o] Error 1

Solution: Install X11 includes.

  sudo yum install libX11-devel.i686

ant still failing:

 native:
     [exec] gcc -m64 -W -Wall -Wno-unused -Wno-parentheses -fPIC  -O2 -fno-omit-frame-pointer -fno-strict-aliasing  -D_REENTRANT -DHAVE_PROTECTION -I"/usr/lib/jvm/jdk1.8.0_31/jre/../include" -I"/usr/lib/jvm/jdk1.8.0_31/jre/../include/linux" -I"/home/cxh/src/jna/jna.git/build/native-linux-x86-64" -I/home/cxh/src/jna/jna.git/build/native-linux-x86-64/libffi/include -DJNA_JNI_VERSION='"4.0.1"' -DCHECKSUM='"1a6047467b59e8748f975e03016ce3d9"' -c dispatch.c -o /home/cxh/src/jna/jna.git/build/native-linux-x86-64/dispatch.o
     [exec] In file included from dispatch.c:82:
     [exec] /usr/lib/jvm/jdk1.8.0_31/jre/../include/linux/jawt_md.h:31:27: error: X11/Intrinsic.h: No such file or directory
     [exec] make: *** [/home/cxh/src/jna/jna.git/build/native-linux-x86-64/dispatch.o] Error 1

Solution:

   sudo yum install libXt-devel.x86_64

Building JNA Under MacOSX with Java 1.7

I wanted to build JNA under MacOSX so that I could do some debugging by modifying JNA.

Sadly, Apple's Java story is rather lacking. I installed the Java 1.7 preview for Mac OS X and now I can't seem to compile code that uses jni.h.

When compiling jna, I get:

[exec] dispatch.c:79:17: error: /System/Library/Frameworks/JavaVM.framework/Headers/jni.h: Too many levels of symbolic links

This is because jni.h is a link back on to itself:

lrwxr-xr-x 1 root wheel 30 Jul 28 2011 /System/Library/Frameworks/JavaVM.framework/Headers/jni.h -> ../../CurrentJDK/Headers/jni.h

I went to https://developer.apple.com/downloads/index.action downloaded "Java for Mac OS X 10.7 Developer Package" and installed it, and the problem was not solved.

It appears that the issue here is that Apple's Java 1.6 used the Mac OS X "Frameworks" directory layout and Java 1.7 from Oracle uses the Java directory layout. Personally, I prefer the Java layout, since Java is "write once, test everywhere". Having a different directory layout under Mac OS X made things more difficult.

I'm not sure how my directory structure was broken, but the directory Headers directory itself had mod times of February 16, 2012, which is probably when I upgraded to Mac OS X 10.7.3.

Apple is no longer supporting Java and it is really starting to show.

So, I decided to move forward with the Java 1.7 preview. I needed to remove the broken jni.h links, so I did:

sudo -i
cd /System/Library/Frameworks/JavaVM.framework
mv Headers Headers.1.6
ln -s /Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/include Headers

Download the jna sources using git:

git clone https://github.com/twall/jna.git

2. Run ant

Problem: ant fails with "checking whether the C compiler works... no"

(This problem did not occur when working with the JNA head on 2 Aug 2013)

native:
[exec] configure: WARNING: if you wanted to set the --build type, don't use --host.
[exec] If a cross compiler is detected then cross compConfiguring libffi (amd64)
[exec] ile mode will be used
[exec] checking build system type... x86_64-apple-darwin11.3.0
[exec] checking host system type... x86_64-apple-darwin
[exec] checking target system type... x86_64-apple-darwin
[exec] checking for gsed... sed
[exec] checking for a BSD-compatible install... /usr/bin/install -c
[exec] checking whether build environment is sane... yes
[exec] configure: error: in `/Users/cxh/src/jna/build-d64/native/libffi':
[exec] configure: error: C compiler cannot create executables
[exec] See `cchecking for amd64-apple-darwin-strip... no
[exec] checking for strip... strip
[exec] checking for a thread-safe mkdir -p... /Users/cxh/src/jnonfig.log' for more details
[exec] a/native/libffi/install-sh -c -d
[exec] checking for gawk... no
[exec] checking for mawk... no
[exec] checking for nawk... no
[exec] checking for awk... awk
[exec] checking whether make sets $(MAKE)... yes
[exec] checking for amd64-apple-darwin-gcc... gcc -m64
[exec] checking whether the C compiler works... no
[exec] make: *** [/Users/cxh/src/jna/build-d64/native/libffi/.libs/libffi.a] Error 77

What is happening here is that the Mac OS X Java 1.7.0_04-ea returns amd64 for various properties.

The solution is to do

ant clean
ant -DARCH=x86_64

Problem: "jni_md.h: No such file or directory"

(This problem did not occur when working with the JNA head on 2 Aug 2013) ant -DARCH=x86_64 fails with:

[exec] /System/Library/Frameworks/JavaVM.framework/Headers/jni.h:45:20: error: jni_md.h: No such file or directory

My solution was to edit jna/native/Makefile.

Change:

ifeq ($(OS),darwin)
JAVA_INCLUDES=-I/System/Library/Frameworks/JavaVM.framework/Headers

to

ifeq ($(OS),darwin)
JAVA_INCLUDES=-I/System/Library/Frameworks/JavaVM.framework/Headers -I/System/Library/Frameworks/JavaVM.framework/Headers/darwin

Rerun:

ant clean
ant -DARCH=x86_64

Problem: "‘JAWT_MacOSXDrawingSurfaceInfo’ undeclared"

(This problem did not occur when working with the JNA head on 2 Aug 2013)

[exec] dispatch.c:2865: error: ‘JAWT_MacOSXDrawingSurfaceInfo’ undeclared (first use in this function)

See http://www.mail-archive.com/bsd-port-dev@openjdk.java.net/msg01291.html

Workaround: Edit jna/native/dispatch.c and search for JAWT_MacOSXDrawingSurfaceInfo. Change

#elif __APPLE__
      // WARNING: the view ref is not guaranteed to be stable except during                          
      // component paint (see jni_md.h)                                                              
      JAWT_MacOSXDrawingSurfaceInfo* mdsi =
        (JAWT_MacOSXDrawingSurfaceInfo*)dsi->platformInfo;

to

#elif __APPLEXXX__
      // WARNING: the view ref is not guaranteed to be stable except during                          
      // component paint (see jni_md.h)                                                              
      JAWT_MacOSXDrawingSurfaceInfo* mdsi =
        (JAWT_MacOSXDrawingSurfaceInfo*)dsi->platformInfo;

Rerun:

ant clean
ant -DARCH=x86_64

That seemed to do it! jna.jar is created.

Test failures:

Not all the tests pass:

(This problem did not occur when working with the JNA head on 2 Aug 2013)

[junit] Testcase: testLoadJAWT(com.sun.jna.LibraryLoadTest): Caused an ERROR
[junit] Can't load JAWT
[junit] java.lang.UnsatisfiedLinkError: Can't load JAWT
[junit] at com.sun.jna.Native.getWindowHandle0(Native Method)
[junit] at com.sun.jna.Native$AWT.getComponentID(Native.java:1766)
[junit] at com.sun.jna.Native$AWT.getWindowID(Native.java:1742)
[junit] at com.sun.jna.Native.getWindowPointer(Native.java:262)
[junit] at com.sun.jna.LibraryLoadTest$AWT.loadJAWT(LibraryLoadTest.java:169)
[junit] at com.sun.jna.LibraryLoadTest.testLoadJAWT(LibraryLoadTest.java:42)
[junit]
[junit]
[junit] Testcase: testLoadLibraryWithUnicodeName(com.sun.jna.LibraryLoadTest): FAILED
[junit] Expected JNA native library at /Users/cxh/src/jna/build-d64/native/libjnidispatch.dylib \
is missing
[junit] junit.framework.AssertionFailedError: Expected JNA native library at /Users/cxh/src/jna/\
build-d64/native/libjnidispatch.dylib is missing
[junit] at com.sun.jna.LibraryLoadTest.testLoadLibraryWithUnicodeName(LibraryLoadTest.java:9\
6)

I'm not sure about the above.

(This problem did not occur when working with the JNA head on 2 Aug 2013)

[junit] Testcase: testLaunchedUnderWebStart(com.sun.jna.WebStartTest): Caused an ERROR
[junit] javaws executable not found
[junit] java.io.IOException: javaws executable not found
[junit] at com.sun.jna.WebStartTest.findJWS(WebStartTest.java:296)
[junit] at com.sun.jna.WebStartTest.runTestUnderWebStart(WebStartTest.java:151)
[junit] at com.sun.jna.WebStartTest.runTestUnderWebStart(WebStartTest.java:253)
[junit] at com.sun.jna.WebStartTest.runBare(WebStartTest.java:370)

Oddly, javaws is in my path?

Building a debug version of JNA

  1. Edit build.xml and change
<property name="debug.native" value="false"/>

to

<property name="debug.native" value="true"/>
  1. Edit native/Makefile and change
STRIP=strip -x

to

STRIP=echo

I also added

DEBUG=true

to the top.

Build with:

ant clean
ant native
ant jar
cp build/jna.jar $PTII/lib

Running with gdb under Mac OS X

See Debugging A Mac FMU

cd $PTII
gdb -java
r -classpath .:/Users/cxh/ptII:/Users/cxh/ptII/lib/junit-4.8.2.jar:/Users/cxh/ptII/lib/jna.jar:/Users/cxh/ptII/lib/JUnitParams-0.4.0.jar:/Users/cxh/ptII/lib/ptjacl.jar:/Users/cxh/ptII/lib/jna.jar org.junit.runner.JUnitCore org.ptolemy.fmi.driver.test.junit.FMUJUnitTest

Building JNA Under Windows

These notes are about building JNA from source without the Variadic extensions

Building JNA Under Cygwin

With a complete installation of Cygwin64 under Windows Server 2012R2, building JNA under Cygwin worked out of the box for me.

See Windows Development Environment (from twall's github) for what Cygwin packages need to be installed.

git clone https://github.com/twall/jna.git
cd jna.git
ant

However, the tests hung, see Running JNA Tests under Windows

Building JNA Under Microsoft Visual C

See Windows Development Environment (from twall's github) has a partial description of what is necessary, below are the changes that I had to make to build JNA from the git head on 2/24/2015:

Building using Open VS2012 x64 Native Tools Command

If you are not heavily using Cygwin, then try using the MSVC tools without Cygwin.

In Cygwin Bash, check out the tree:

git clone https://github.com/twall/jna.git

Start up "Open VS2012 x64 Native Tools Command" and run

cd jna.git
ant

Open VS2012 x64 Native Tools Command problem: The build is done with gcc, not cl

The variables in Windows Development Environment (from twall's github) need to be set or else the build will occur with gcc.

24-Feb-2015: I stopped using Open VS2012 x64 here and focused on using Cygwin below

Building under Cygwin Bash with MSVC tools: Set up environment variables

Windows Development Environment (from twall's github) says "Sample configuration, setting up INCLUDE/LIB:" and then lists what looks like bash commands for setting variables.

export MSVC="/c/Program Files (x86)/Microsoft Visual Studio 10.0/vc"
export WSDK="/c/Program Files (x86)/Microsoft SDKs/Windows/v7.0A"
export WSDK_64="/c/Program Files/Microsoft SDKs/Windows/v7.1"

export INCLUDE="$(cygpath -m "$MSVC")/include;$(cygpath -m "$WSDK")/include"
# for 64-bit target
export LIB="$(cygpath -m "$MSVC")/lib/amd64;$(cygpath -m "$WSDK_64")/lib/x64"
# for 32-bit target
export LIB="$(cygpath -m "$MSVC")/lib;$(cygpath -m "$WSDK")/lib"
  1. Under Windows Server 2012R2, I don't have C:/Program Files/Microsoft SDKs/Windows/v7.1 I looked in to installing it and got no where, so I decided to move forward and see what happened.
  2. When I adjusted the variables for my machine as follows:
    export MSVC=c:/Program\ Files\ \(x86\)/Microsoft\ Visual\ Studio\ 11.0/vc
    export WSDK=c:/Program\ Files\ \(x86\)/Microsoft\ SDKs/Windows/v7.0A
    export WSDK_64=c:/Program\ Files\ \(x86\)/Microsoft\ SDKs/Windows/v7.0A
    export INCLUDE="$(cygpath -m "$MSVC")/include;$(cygpath -m "$WSDK")/include"
    export LIB="$(cygpath -m "$MSVC")/lib/amd64;$(cygpath -m "$WSDK")/include"
    and then ran ant, then cl was not found.
  3. To get the proper variables, I started up "Open VS2012 x64 Native Tools Command" and ran
    env > env.out
    NOTE You are better off running ant in "Open VS2012 x64 Native Tools Commands" than using Cygwin bash.
  4. Optional: If you really want to use Cygwin bash, then follow this step' I then added the variables that contained the word microsoft to a script and made the following edits
    1. Changed backslashes to forward slashes
    2. Modified each line so that it because with export=" and ended with a double quote: "
  5. The resulting script is available as setupmsvc.txt and looks like
    export MSVC=c:/Program\ Files\ \(x86\)/Microsoft\ Visual\ Studio\ 11.0/vc
    export WSDK=c:/Program\ Files\ \(x86\)/Microsoft\ SDKs/Windows/v7.0A
    export WSDK_64=c:/Program\ Files\ \(x86\)/Microsoft\ SDKs/Windows/v7.0A
    export INCLUDE="$(cygpath -m "$MSVC")/include;$(cygpath -m "$WSDK")/include"
    export LIB="$(cygpath -m "$MSVC")/lib/amd64;$(cygpath -m "$WSDK")/include"

    export ExtensionSdkDir="C:/Program Files (x86)/Microsoft SDKs/Windows/v8.0/ExtensionSDKs"
    export FrameworkDir="C:/Windows/Microsoft.NET/Framework64"
    export FrameworkDIR64="C:/Windows/Microsoft.NET/Framework64"
    export FrameworkVersion="v4.0.30319"
    export FrameworkVersion64="v4.0.30319"
    export FSHARPINSTALLDIR="C:/Program Files (x86)/Microsoft SDKs/F#/3.0/Framework/v4.0/"

    export INCLUDE="C:/Program Files (x86)/Microsoft Visual Studio 11.0/VC/INCLUDE;C:/Program Files (x86)/Microsoft Visual Studio 11.0/VC/ATLMFC/INCL\
    UDE;C:/Program Files (x86)/Windows Kits/8.0/include/shared;C:/Program Files (x86)/Windows Kits/8.0/include/um;C:/Program Files (x86)/Windows Kits\
    /8.0/include/winrt;"

    export LIB="C:/Program Files (x86)/Microsoft Visual Studio 11.0/VC/LIB/amd64;C:/Program Files (x86)/Microsoft Visual Studio 11.0/VC/ATLMFC/LIB/am\
    d64;C:/Program Files (x86)/Windows Kits/8.0/lib/win8/um/x64;"

    export LIBPATH="C:/Windows/Microsoft.NET/Framework64/v4.0.30319;C:/Windows/Microsoft.NET/Framework64/v3.5;C:/Program Files (x86)/Microsoft Visual\
    Studio 11.0/VC/LIB/amd64;C:/Program Files (x86)/Microsoft Visual Studio 11.0/VC/ATLMFC/LIB/amd64;C:/Program Files (x86)/Windows Kits/8.0/Referen\
    ces/CommonConfiguration/Neutral;C:/Program Files (x86)/Microsoft SDKs/Windows/v8.0/ExtensionSDKs/Microsoft.VCLibs/11.0/References/CommonConfigura\
    tion/neutral;"

    export PATH="/cygdrive/c/Program Files (x86)/Microsoft Visual Studio 11.0/Common7/IDE/CommonExtensions/Microsoft/TestWindow:/cygdrive/c/Program F\
    iles (x86)/Microsoft Visual Studio 11.0/VC/BIN/amd64:/cygdrive/c/Windows/Microsoft.NET/Framework64/v4.0.30319:/cygdrive/c/Windows/Microsoft.NET/F\
    ramework64/v3.5:/cygdrive/c/Program Files (x86)/Microsoft Visual Studio 11.0/VC/VCPackages:/cygdrive/c/Program Files (x86)/Microsoft Visual Studi\
    o 11.0/Common7/IDE:/cygdrive/c/Program Files (x86)/Microsoft Visual Studio 11.0/Common7/Tools:/cygdrive/c/Program Files (x86)/HTML Help Workshop:\
    /cygdrive/c/Program Files (x86)/Microsoft Visual Studio 11.0/Team Tools/Performance Tools/x64:/cygdrive/c/Program Files (x86)/Microsoft Visual St\
    udio 11.0/Team Tools/Performance Tools:/cygdrive/c/Program Files (x86)/Windows Kits/8.0/bin/x64:/cygdrive/c/Program Files (x86)/Windows Kits/8.0/\
    bin/x86:/cygdrive/c/Program Files (x86)/Microsoft SDKs/Windows/v8.0A/bin/NETFX 4.0 Tools/x64:/cygdrive/c/Program Files (x86)/Microsoft SDKs/Windo\
    ws/v7.0A/Bin/x64:/cygdrive/c/Program Files (x86)/Microsoft SDKs/Windows/v8.0A/bin/NETFX 4.0 Tools:/cygdrive/c/Program Files (x86)/Microsoft SDKs/\
    Windows/v7.0A/Bin:/usr/bin:/usr/local/apache-ant-1.9.4/bin:/cygdrive/c/Program Files/Java/jdk1.8.0_31/bin:/cygdrive/c/ProgramData/Oracle/Java/jav\
    apath:/cygdrive/c/Windows/system32:/cygdrive/c/Windows:/cygdrive/c/Windows/System32/Wbem:/cygdrive/c/Windows/System32/WindowsPowerShell/v1.0:/cyg\
    drive/c/Program Files/MATLAB/R2014b/runtime/win64:/cygdrive/c/Program Files/MATLAB/R2014b/bin:/cygdrive/c/Program Files/MATLAB/R2014b/bin/win64:/\
    cygdrive/c/Program Files (x86)/Microsoft ASP.NET/ASP.NET Web Pages/v1.0:/cygdrive/c/Program Files/Microsoft SQL Server/110/Tools/Binn:/cygdrive/c\
    /Program Files/Microsoft/Web Platform Installer:/cygdrive/c/Program Files/TortoiseSVN/bin"

    export PSModulePath="C:/Windows/system32/WindowsPowerShell/v1.0/Modules/;c:/Program Files/Microsoft Security Client/MpProvider/"

    export WindowsSdkDir="C:/Program Files (x86)/Windows Kits/8.0/"
    export WindowsSdkDir_35="C:/Program Files (x86)/Microsoft SDKs/Windows/v7.0A/Bin/"
    export WindowsSdkDir_old="C:/Program Files (x86)/Microsoft SDKs/Windows/v8.0A/"

    export USE_MSVC=1
    Note that I also appended export USE_MSVC= because native/Makefile says:
    # The windows build requires a cygwin or MSYS installation. The build may use
    # MS tools or GCC/mingw. Define USE_MSVC in your environment and ensure cl.exe
    # and ml.exe are in your PATH to build with MS tools.
  6. In Cygwin bash, to set the variables, use the dot command:
    . setupmsvc.txt
  7. In Cygwin bash, check out the tree and run ant
    git clone https://github.com/twall/jna.git
    cd jna.git
    ant

Various issues are discussed below

invalid syntax in conditional

While running ant:

  [exec] Makefile:165: *** invalid syntax in conditional. Stop

Line 165 of native/Makefile is the ifdef $(MSVC) line below:

  ifdef $(MSVC)
  USE_MSVC=true
  endif

I had export MSVC=1, so a workaround was:

  ifneq ($(MSVC), "")
  USE_MSVC=true
  endif

I think the issue here is that MSVC is set to a value that has spaces in it?

Cygwin with MSVC: configure: error: C compiler cannot create executables

When building the from the variadic extensions git repo under Cygwin with MSVC:

[exec] checking for x86_64-w64-mingw32-gcc... /cygdrive/c/Users/cxh/src/jna/jna-cxbrooks/native/libffi/../cc.sh -m64
[exec] configure: error: in `/cygdrive/c/Users/cxh/src/jna/jna-cxbrooks/build/native-win32-x86-64/libffi':checking whether the C compiler works... no
[exec]
[exec] configure: error: C compiler cannot create executables
[exec] See `config.log' for more details
[exec] Makefile:418: recipe for target '../build/native-win32-x86-64/libffi/.libs/libffi.lib' failed
[exec] make: *** [../build/native-win32-x86-64/libffi/.libs/libffi.lib] Error 77

Looking at jna-cxbrooks/build/native-win32-x86-64/libffi/config.log:

configure:3673: /cygdrive/c/Users/cxh/src/jna/jna-cxbrooks/native/libffi/../cc.sh -m64 -std=gnu99 -DHAVE_PROTECTION -DPSAPI_VERSION=1 -DFFI_BUILDING -DUNICODE -D_UNICODE conftest.c >&5
Unsupported argument '-std=gnu99

The solution is to edit jna-cxbrooks/native/Makefile and change:

  FFI_ENV=CC="$(CC)" CFLAGS="$(COPT) $(CDEBUG) -std=gnu99" CPPFLAGS="$(CDEFINES)"

to:

  FFI_ENV=CC="$(CC)" CFLAGS="$(COPT) $(CDEBUG)" CPPFLAGS="$(CDEFINES)"

and rerun ant

Note that the above issue does 'not occur in the jna head as of February, 2015. This problem is probably in the 4.1 jna branch.

Cygwin with MSVC: Unsupported argument '-std=gnu99'

When building the from the variadic extensions git repo under Cygwin with MSVC:

[exec] libtool: link: ( cd ".libs" && rm -f "libffi.la" && ln -s "../libffi.la" "libffi.la" )
[exec] make[3]: Leaving directory '/cygdrive/c/Users/cxh/src/jna/jna-cxbrooks/build/native-win32-x86-64/libffi'
[exec] make[2]: Leaving directory '/cygdrive/c/Users/cxh/src/jna/jna-cxbrooks/build/native-win32-x86-64/libffi'
[exec] make[1]: Leaving directory '/cygdrive/c/Users/cxh/src/jna/jna-cxbrooks/build/native-win32-x86-64/libffi'
[exec] /cygdrive/c/Users/cxh/src/jna/jna-cxbrooks/native/libffi/../cc.sh -m64 -W -std=gnu99 -Wall -Wno-unused -Wno-parentheses -DHAVE_PROTECTION -DPSAPI_VERSION=1 -DFFI_BUILDING -DUNICODE -D_UNICODE -I"C:\Program Files\Java\jdk1.8.0_31\jre/../include" -I"C:\Program Files\Java\jdk1.8.0_31\jre/../include/win32" -I"C:\Users\cxh\src\jna\jna-cxbrooks\build\native-win32-x86-64" -I../build/native-win32-x86-64/libffi/include -DJNA_JNI_VERSION='"4.0.0"' -DCHECKSUM='"3f99b7ecf15cd6a6fc62cc9420598381"' -c dispatch.c -o ../build/native-win32-x86-64/dispatch.o
[exec] Unsupported argument '-std=gnu99'
[exec] Makefile:370: recipe for target '../build/native-win32-x86-64/dispatch.o' failed
[exec] make: *** [../build/native-win32-x86-64/dispatch.o] Error 1

The solution is to edit jna-cxbrooks/native/Makefile and change:

  PCFLAGS=-W -std=gnu99 -Wall -Wno-unused -Wno-parentheses

to:

  PCFLAGS=-W  -Wall -Wno-unused -Wno-parentheses

Note that the above issue does 'not occur in the jna head as of February, 2015. This problem is probably in the 4.1 jna branch.

Cygwin with MSVC: unresolved external symbol ffi_closure_va_sint8

When building the from the variadic extensions git repo under Cygwin with MSVC:

[exec] link is /cygdrive/c/Program Files (x86)/Microsoft Visual Studio 11.0/VC/BIN/amd64/link
[exec] C:/Program Files (x86)/Microsoft Visual Studio 11.0/VC/LIB/amd64;C:/Program Files (x86)/Microsoft Visual Studio 11.0/VC/ATLMFC/LIB/amd64;C:/Program Files (x86)/Windows Kits/8.0/lib/win8/um/x64;
[exec] "link" /nologo /opt:REF /incremental:no /subsystem:console /nodefaultlib:msvcrtd /out:"C:/Users/cxh/src/jna/jna-cxbrooks/build/native-win32-x86-64/jnidispatch.dll" /pdb:C:/Users/cxh/src/jna/jna-cxbrooks/build/native-win32-x86-64/jnidispatch.pdb /implib:C:/Users/cxh/src/jna/jna-cxbrooks/build/native-win32-x86-64/jnidispatch.lib /DLL C:/Users/cxh/src/jna/jna-cxbrooks/build/native-win32-x86-64/dispatch.o C:/Users/cxh/src/jna/jna-cxbrooks/build/native-win32-x86-64/callback.o C:/Users/cxh/src/jna/jna-cxbrooks/build/native-win32-x86-64/rsrc.o C:/Users/cxh/src/jna/jna-cxbrooks/build/native-win32-x86-64/dll-callback.o C:/Users/cxh/src/jna/jna-cxbrooks/build/native-win32-x86-64/libffi/.libs/libffi.lib psapi.lib (LIB=C:/Program Files (x86)/Microsoft Visual Studio 11.0/VC/LIB/amd64;C:/Program Files (x86)/Microsoft Visual Studio 11.0/VC/ATLMFC/LIB/amd64;C:/Program Files (x86)/Windows Kits/8.0/lib/win8/um/x64;)
[exec] Creating library C:/Users/cxh/src/jna/jna-cxbrooks/build/native-win32-x86-64/jnidispatch.lib and object C:/Users/cxh/src/jna/jna-cxbrooks/build/native-win32-x86-64/jnidispatch.exp
[exec] dispatch.o : error LNK2019: unresolved external symbol ffi_closure_va_sint8 referenced in function Java_com_sun_jna_Native_ffi_1closure_1va_1sint8
[exec] dispatch.o : error LNK2019: unresolved external symbol ffi_closure_va_sint16 referenced in function Java_com_sun_jna_Native_ffi_1closure_1va_1sint16
[exec] dispatch.o : error LNK2019: unresolved external symbol ffi_closure_va_sint32 referenced in function Java_com_sun_jna_Native_ffi_1closure_1va_1sint32
[exec] dispatch.o : error LNK2019: unresolved external symbol ffi_closure_va_sint64 referenced in function Java_com_sun_jna_Native_ffi_1closure_1va_1sint64
[exec] dispatch.o : error LNK2019: unresolved external symbol ffi_closure_va_uint8 referenced in function Java_com_sun_jna_Native_ffi_1closure_1va_1uint8

Note that the above issue does 'not occur in the jna head as of February, 2015. This problem is probably with the variadic patch.

Analysis:

The missing symbols are defined in jna-cxbrooks/native/libffi/src/closures_va.c. Running nm on the .obj file indicates that they are not present. Looking at closure_va.c, we see

#if FFI_CLOSURES
# if __STDC_VERSION__ >= 199901L

/* Note: int8_t, uint8_t, int16_t and uint16_t are promoted to int in '...'
*/
int8_t
ffi_closure_va_sint8(ffi_cif *cif) {
return ffi_closure_va_sint32(cif);
}

The issue here is that _STDC_VERSION is probably not defined for MSVC, so we change:

  #  if __STDC_VERSION__ >= 199901L

To:

  #  if __STDC_VERSION__ >= 199901L || defined(_MSC_VER)

This causes:

[exec] cl /nologo /EHac /W3 /wd4127 /wd4820 /wd4706 /wd4100 /wd4255 /wd4668 -DHAVE_CONFIG_H /I"." /I"C:/Users/cxh/src/jna/jna-cxbrooks/native/libffi" /I"." /I"C:/Users/cxh/src/jna/jna-cxbrooks/native/libffi/include" /I"include" /I"C:/Users/cxh/src/jna/jna-cxbrooks/native/libffi/src" -DHAVE_PROTECTION -DPSAPI_VERSION='1' -DFFI_BUILDING -DUNICODE -D_UNICODE /c "C:/Users/cxh/src/jna/jna-cxbrooks/native/libffi/src/closures_va.c" /Fosrc/closures_va.obj "/Fdsrc/closures_va" "/Fpsrc/closures_va" "/Fasrc/closures_va"
[exec] closures_va.c
[exec] C:/Users/cxh/src/jna/jna-cxbrooks/native/libffi/src/closures_va.c(36) : error C2061: syntax error : identifier 'ffi_closure_va_sint8'
[exec] C:/Users/cxh/src/jna/jna-cxbrooks/native/libffi/src/closures_va.c(36) : error C2059: syntax error : ';'
[exec] C:/Users/cxh/src/jna/jna-cxbrooks/native/libffi/src/closures_va.c(36) : error C2059: syntax error : 'type'
[exec] C:/Users/cxh/src/jna/jna-cxbrooks/native/libffi/src/closures_va.c(41) : error C2061: syntax error : identifier 'ffi_closure_va_uint8'
[exec] C:/Users/cxh/src/jna/jna-cxbrooks/native/libffi/src/closures_va.c(41) : error C2059: syntax error : ';'
[exec] C:/Users/cxh/src/jna/jna-cxbrooks/native/libffi/src/closures_va.c(41) : error C2059: syntax error : 'type'
[exec] C:/Users/cxh/src/jna/jna-cxbrooks/native/libffi/src/closures_va.c(46) : error C2061: syntax error : identifier 'ffi_closure_va_sint16'

Cannot open ../build/native-win32-x86-64/testlib.dll

The problem here was that the .dll already existed. The solution was to run rm ./build/native-win32-x86-64/testlib.dll

Running ant clean did not fix this.

After this, build succeeded, though the tests failed, see Running JNA Tests under Windows

Running JNA Tests under Windows

Running the JNA Tests using Eclipse under Windows

Running the tests using Eclipse under Windows worked better.

  1. Create a project
    1. Right Click in the Package Explorer, select Import
    2. General -> Existing Projects into Workspace -> Next
    3. In the "Import Properties" Window, next to "Select root directory", click Browse. Browse to the source tree checked out with git. Click Finish.
  2. Set up run configuration
    1. In the "Test" tab, select "Run all tests in the selected project, package or source folder."
    2. In the "Arguments" tab, under "VM arguments", enter
      -Ddummy
      -Djna.library.path=C:\cygwin64\home\cxh\src\jna\jna.git\build\native-win32-x86-64
      -Djna.nosys=true
      -Djna.protected=true
      -Djna.builddir=C:\cygwin64\home\cxh\src\jna\jna.git\build
      (:source:)
      # In the "Classpath" tab, Click on "User Entries", then "Add Jars" and browse to the @@build@@ directory and add @@jna.jar@@. Also, find the @@lib/test@@ directory and add all those jars.
      # The WebStartTest test fails, so:
      ## edit that file
      ## Comment out the body
      ## Add (:source:)
      public void testNotWebStart() {
      System.out.println("WebStartTest commented out.");
      }
  3. Click on Run

testBatchCheckStructuredGetFieldOrder

Fails with

  java.lang.NoClassDefFoundError: com/google/common/base/Predicate

Solution: Add lib/test/guava-11.0.2.jar to the classpath for the Run configuration. In fact, add all the jars in that directory and avoid other problems.

testLoadFromUnicodePath errors from within Eclipse under Windows

When running all the tests with the JNA head from 24-Feb-2015, JNALoadTest.testLoadFromUnicodePath() fails:

java.lang.Error: JVM error: System.load() failed to load JNA native library from C:\Users\cxh\AppData\Local\Temp\3\testLoadFromUnicodePath-&#1092;&#1083;&#1089;&#1074;&#1091;\jna7408683420722595513.dll): java.lang.UnsatisfiedLinkError: C:\Users\cxh\AppData\Local\Temp\3\testLoadFromUnicodePath-?????\jna7408683420722595513.dll: Can't find dependent libraries
at com.sun.jna.JNALoadTest.testLoadFromUnicodePath(JNALoadTest.java:229)

I'm not sure about the above, I'll skip it for now.

DirectTest testGetOptionsFOrDirectMappingWithMemberInitializer() fails

In the JNA head from 24-Feb-2015, this test fails from within Eclipse, under Windows:

junit.framework.AssertionFailedError: Wrong type mapper for direct mapping class com.sun.jna.DirectTest$DirectMapping$DirectStructure expected:<com.sun.jna.DefaultTypeMapper@5f8edcc5> but was:<null>
at junit.framework.Assert.fail(Assert.java:57)
at junit.framework.Assert.failNotEquals(Assert.java:329)
at junit.framework.Assert.assertEquals(Assert.java:78)
at junit.framework.TestCase.assertEquals(TestCase.java:244)
at com.sun.jna.DirectTest.testGetOptionsForDirectMappingWithMemberInitializer(DirectTest.java:212)

DirectTest.testGetOptionsForDirectMappingWithStaticInitializer fails from within Eclipse under Windows

junit.framework.AssertionFailedError: Wrong type mapper for direct mapping class com.sun.jna.DirectTest$DirectMappingStatic$DirectStructure expected:<com.sun.jna.DefaultTypeMapper@1ebd319f> but was:<null>
at junit.framework.Assert.fail(Assert.java:57)
at junit.framework.Assert.failNotEquals(Assert.java:329)
at junit.framework.Assert.assertEquals(Assert.java:78)
at junit.framework.TestCase.assertEquals(TestCase.java:244)
at com.sun.jna.DirectTest.testGetOptionsForDirectMappingWithStaticInitializer(DirectTest.java:255)

Native library not found

While testing the varargs extensions, win32-x86-64/testlib-path.dll was not found

java.io.IOException: Native library (win32-x86-64/testlib-path.dll) not found in resource path ([file:/c:/Users/cxh/src/jna/jna.git/build/native-win32-x86-64])
at com.sun.jna.Native.extractFromResourcePath(Native.java:840)
at com.sun.jna.LibraryLoadTest.testExtractFromResourcePath(LibraryLoadTest.java:64)

The solution is to run ant test to build the test dlls.

Also, it turns out that the error was that I had the wrong -D values for the VM arugments - the values referred to a different directory.

Running JNA Tests using Cygwin under Windows

In the devel tree (no variadic extensions), the JNA Callback tests hang when I build from Cygwin using either gcc or MSVC. However, if I build from the Open VS2012 x64 Native Tools Command Prompt, then they don't hang. 24-Feb-2015: I could not replicate the previous statement, I was not able to build from the Open VS2012 x64 Native Tools Command Prompt. Building using Cygwin with MSVC and then running the tests from that tool also hung.

To replicate outside of ant, I ran ant -v and then pasted the output into a script file. Below is an example

export IGNORE='C:\Users\cxh\src\jna'
C:/Program\ Files/Java/jdk1.8.0_25/bin/java.exe \
-Ddummy \
-Djna.library.path=C:/Users/cxh/src/jna/build/native-win32-x86-64 \
-Djna.nosys=true \
-Djna.protected=true \
-Djna.builddir=C:/Users/cxh/src/jna/build \
-Djna.nativedir=C:/Users/cxh/src/jna/build/native-win32-x86-64 \
-classpath \
'C:\Users\cxh\src\jna\build\jna.jar;C:\Users\cxh\src\jna\build\test-classes;C:\Users\cxh\src\\
jna\build\jna-test.jar;C:\Users\cxh\src\jna\lib\clover.jar;C:\Users\cxh\src\jna\lib\junit.jar\
;C:\Users\cxh\src\jna\lib\test\dom4j-1.6.1.jar;C:\Users\cxh\src\jna\lib\test\guava-11.0.2.jar\
;C:\Users\cxh\src\jna\lib\test\javassist-3.12.1.GA.jar;C:\Users\cxh\src\jna\lib\test\reflecti\
ons-0.9.8.jar;C:\Users\cxh\src\jna\lib\test\slf4j-api-1.6.1.jar;C:\Users\cxh\src\jna\build\cl\
asses;C:\cygwin64\usr\local\apache-ant-1.9.4\lib\ant-launcher.jar;C:\cygwin64\usr\local\apach\
e-ant-1.9.4\lib\ant.jar;C:\cygwin64\usr\local\apache-ant-1.9.4\lib\ant-junit.jar;C:\cygwin64\\
usr\local\apache-ant-1.9.4\lib\ant-junit4.jar' \
com.sun.jna.CallbacksTest \
skipNonTests=false \
filtertrace=true \
haltOnError=false \
haltOnFailure=false \
showoutput=false \
outputtoformatters=true \
logfailedtests=true \
threadid=0 \
logtestlistenerevents=false \
formatter=org.apache.tools.ant.taskdefs.optional.junit.BriefJUnitResultFormatter \
formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,C:\Users\cxh\s\
rc\jna\build\junit-results\TEST-com.sun.jna.CallbacksTest.xml \
crashfile=C:/Users/cxh/src/jna/build/junitvmwatcher727685508021720459.properties \
propsfile=C:/Users/cxh/src/jna/build/junit4057250054536740714.properties

jvisualvm does not show the process?

JNA Tests under Windows Server 2008R2

On Joule, which is running Windows Server 2008R2, the variadic tests failed in the jna devel tree on 2014-12-14.

    [junit] Testcase: testDLLCallback(com.sun.jna.CallbacksTest):       Caused an ERROR
    [junit] No more DLL callback slots available
    [junit]     at com.sun.jna.Native.createNativeCallback(Native Method)
    [junit]     at com.sun.jna.CallbackReference.<init>(CallbackReference.java:232)
    [junit]     at com.sun.jna.CallbackReference.getFunctionPointer(CallbackReference.java:398)
    [junit]     at com.sun.jna.CallbackReference.getFunctionPointer(CallbackReference.java:380)
    [junit]     at com.sun.jna.Function.convertArgument(Function.java:534)
    [junit]     at com.sun.jna.Function.invoke(Function.java:297)
    [junit]     at com.sun.jna.Library$Handler.invoke(Library.java:212)
    [junit]     at com.sun.proxy.$Proxy0.callVoidCallback(Unknown Source)
    [junit]     at com.sun.jna.CallbacksTest.testDLLCallback(CallbacksTest.java:1257)
  • The above looks bad, need to look into it.
  • Note that I get the same above failure when I check out the JNA 4.0 branch without variadic extensions.
    [junit] Testsuite: com.sun.jna.JNALoadTest
    [junit] Tests run: 5, Failures: 0, Errors: 1, Time elapsed: 4.852 sec
    [junit]
    [junit] Testcase: testLoadFromUnicodePath(com.sun.jna.JNALoadTest): Caused an ERROR
    [junit] JVM error: System.load() failed to load JNA native library from C:\Users\cxh.EECS\testLoadFromUnicodePath-?????\jna1665291666603896836.dll): java.lang.UnsatisfiedLinkError: C:\Users\cxh.EECS\testLoadFromUnicodePath-?????\jna1665291666603896836.dll: Can't find dependent libraries
    [junit] java.lang.Error: JVM error: System.load() failed to load JNA native library from C:\Users\cxh.EECS\testLoadFromUnicodePath-?????\jna1665291666603896836.dll): java.lang.UnsatisfiedLinkError: C:\Users\cxh.EECS\testLoadFromUnicodePath-?????\jna1665291666603896836.dll: Can't find dependent libraries
    [junit]     at com.sun.jna.JNALoadTest.testLoadFromUnicodePath(JNALoadTest.java:229)
  • This might be common to all Windows installations.
  • Note that I get the same above failure when I check out the JNA 4.0 branch without variadic extensions.
    [junit] Testcase: testLoadJAWT(com.sun.jna.LibraryLoadTest):        Caused an ERROR
    [junit] The specified module could not be found.
    [junit]
    [junit] java.lang.UnsatisfiedLinkError: The specified module could not be found.
    [junit]
    [junit]     at com.sun.jna.Native.getWindowHandle0(Native Method)
    [junit]     at com.sun.jna.Native$AWT.getComponentID(Native.java:2010)
    [junit]     at com.sun.jna.Native$AWT.getWindowID(Native.java:1986)
    [junit]     at com.sun.jna.Native.getWindowPointer(Native.java:275)
    [junit]     at com.sun.jna.LibraryLoadTest$AWT.loadJAWT(LibraryLoadTest.java:286)
    [junit]     at com.sun.jna.LibraryLoadTest.testLoadJAWT(LibraryLoadTest.java:49)

The above is expected because I'm connected via ssh with no X11 setup. This should be verified by running on the machine.

   [junit] Testsuite: com.sun.jna.WebStartTest
    [junit] Tests run: 6, Failures: 0, Errors: 6, Time elapsed: 181.583 sec
    [junit]
    [junit] Testcase: testDetectError(com.sun.jna.WebStartTest):        Caused an ERROR
    [junit] JWS Timed out
    [junit] java.lang.Error: JWS Timed out
    [junit]     at com.sun.jna.WebStartTest.runTestUnderWebStart(WebStartTest.java:199)
    [junit]     at com.sun.jna.WebStartTest.runTestUnderWebStart(WebStartTest.java:240)
    [junit]     at com.sun.jna.WebStartTest.runBare(WebStartTest.java:373)

The above can probably be ignored.

BTW - Java 1.8 or so now requires setup for the Java Web Start local files to work. Under Windows, start up the Java Control Panel and add file:/ as an acceptable host.

Notes about building JNA-4.0 under Windows

To get build JNA-4.0 from sources under Windows Server 2012R2 64-bit, I installed Visual Studio. In the Windows Environment Variables control panel, I set

  • ANT_HOME
  • JAVA_HOME
  • PATH to include both ANT_HOME/bin and JAVA_HOME/bin
  1. Start up the Open VS2012x74 Native Tools Command, which will sent the environment to use the cl Visual Studio Compiler
  2. Download the jna tree:
    git clone https://github.com/twall/jna.git jna.git
    cd jna.git
    git checkout -b 4.0-test 4.0
  3. Build:

JNA Notes

Random notes and trains of thoughts...

JNA Struct By Reference

http://www.eshayne.com/jnaex/example03.html C:

typedef struct Example3Struct {
int val;
} Example3Struct;
...
void example3_sendStruct(const Example3Struct* sval)
{
// note: printfs called from C won't be flushed
// to stdout until the Java process completes
printf("(C) %d\n", sval->val);
}

Java:

public interface CLibrary extends Library {
public static class Example3Struct extends Structure {
public static class ByReference extends Example3Struct implements Structure.ByReference {}

public int val;
}
...
// unless otherwise specified, ByReference is assumed - but it can't hurt to be explicit
public void example3_sendStruct(Example3Struct.ByReference sval);
}
...
CLibrary clib = (CLibrary)Native.loadLibrary("testlib", CLibrary.class);
...
CLibrary.Example3Struct.ByReference e3ref = new CLibrary.Example3Struct.ByReference();
e3ref.val = 7;
clib.example3_sendStruct(e3ref);

JNA Invalid Memory access

When loading a 64-bit FMU created by Dymola, the following was observed:

  Caused by: java.lang.Error: Invalid memory access
    at com.sun.jna.Native.invokePointer(Native Method)
    at com.sun.jna.Function.invokePointer(Function.java:470)
    at com.sun.jna.Function.invoke(Function.java:404)
    at com.sun.jna.Function.invoke(Function.java:315)
    at com.sun.jna.Function.invoke(Function.java:268)
    at ptolemy.actor.lib.fmi.FMUImport.preinitialize(FMUImport.java:1861)

Line 1861 is:

                _fmiComponent = (Pointer) _fmiInstantiateFunction.invoke(
                        Pointer.class, new Object[] { getFullName(), fmiType,
                            _fmiModelDescription.guid,
                            _fmiModelDescription.fmuResourceLocation,
                            _callbacks, toBeVisibleFMI2, loggingOnFMI2 });

The function being called is

   /* Creation and destruction of FMU instances and setting debug status */
   typedef fmi2Component fmi2InstantiateTYPE (fmi2String, fmi2Type, fmi2String, fmi2String, const fmi2CallbackFunctions*, fmi2Boolean, fmi2Boolean);

with these typedefs and structs:

   typedef void*           fmi2Component;               /* Pointer to FMU instance       */
   typedef void*           fmi2ComponentEnvironment;    /* Pointer to FMU environment    */
   typedef void*           fmi2FMUstate;                /* Pointer to internal FMU state */
   typedef unsigned int    fmi2ValueReference;
   typedef double          fmi2Real   ;

   typedef int             fmi2Integer;
   typedef int             fmi2Boolean;
   typedef char            fmi2Char;
   typedef const fmi2Char* fmi2String;
   typedef char            fmi2Byte;

  typedef enum {
    fmi2ModelExchange,
    fmi2CoSimulation
  } fmi2Type;

  typedef void      (*fmi2CallbackLogger)        (fmi2ComponentEnvironment, fmi2String, fmi2Status,   fmi2String, fmi2String, ...);
   typedef void*     (*fmi2CallbackAllocateMemory)(size_t, size_t);
  typedef void      (*fmi2CallbackFreeMemory)    (void*);
  typedef void      (*fmi2StepFinished)          (fmi2ComponentEnvironment, fmi2Status);

  typedef struct {
   const fmi2CallbackLogger         logger;
   const fmi2CallbackAllocateMemory allocateMemory;
   const fmi2CallbackFreeMemory     freeMemory;
   const fmi2StepFinished           stepFinished;
   const fmi2ComponentEnvironment   componentEnvironment;
  } fmi2CallbackFunctions;

Interestingly, running without the variadic extensions fails with both jna-4.0.0.jar and jna-4.1.0.jar:

  java -classpath "c:\Users\cxh\ptII\lib\jna-4.0.0.jar;c:\Users\cxh\ptII" ptolemy.vergil.VergilApplication -ptiny *.xml

Also, using the fmusdk fmus compiled with Microsoft Visual Studio also works:

  java -classpath "c:\Users\cxh\ptII\lib\jna-4.1.0-variadic.jar;c:\Users\cxh\ptII"      org.ptolemy.fmi.driver.FMUCoSimulation      c:/Users/cxh/src/fmi/fmusdk/fmu20/fmu/cs/x64/inc.fmu 11.0 1.0 true

Disassembly of the Dymola fmi2Instantiate method.

Running gdb on the fmusdk/bin/x64/fmu20sim_cs.exe

(gdb) break fmi2Instantiate
No symbol table is loaded. Use the "file" command.
Make breakpoint pending on future shared library load? (y or [n]) y

Breakpoint 2 (fmi2Instantiate) pending.
(gdb) r expDecayCurve.fmu
Starting program: /cygdrive/c/Users/cxh/src/fmi/fmusdk/bin/x64/fmu20sim_cs.exe/expDecayCurve.fmu
[New Thread 6568.0x1948]
warning: Application "\??\C:\Windows\system32\cmd.exe" found in cache

Breakpoint 2, 0x0000000180001447 in fmi2Instantiate ()
from /tmp/fmu/binaries/win64/expDecayCurve.dll
(gdb) where
#0 0x0000000180001447 in fmi2Instantiate ()
from /tmp/fmu/binaries/win64/expDecayCurve.dll
#1 0x00007ff6650a1134 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
...
(gdb) disassemble fmi2Instantiate
Dump of assembler code for function fmi2Instantiate:
0x0000000180001430 <+0>: mov %r9,0x20(%rsp)
0x0000000180001435 <+5>: mov %r8,0x18(%rsp)
0x000000018000143a <+10>: mov %edx,0x10(%rsp)
0x000000018000143e <+14>: mov %rcx,0x8(%rsp)
0x0000000180001443 <+19>: sub $0x58,%rsp
0x0000000180001447 <+23>: mov 0x90(%rsp),%eax
0x000000018000144e <+30>: mov %eax,0x30(%rsp)
0x0000000180001452 <+34>: mov 0x88(%rsp),%eax
0x0000000180001459 <+41>: mov %eax,0x28(%rsp)
0x000000018000145d <+45>: mov 0x80(%rsp),%rax
0x0000000180001465 <+53>: mov %rax,0x20(%rsp)
0x000000018000146a <+58>: mov 0x78(%rsp),%r9
0x000000018000146f <+63>: mov 0x70(%rsp),%r8
0x0000000180001474 <+68>: mov 0x68(%rsp),%edx
0x0000000180001478 <+72>: mov 0x60(%rsp),%rcx
0x000000018000147d <+77>: callq 0x18000b760 <setTimerCounterCB+30432>
0x0000000180001482 <+82>: mov %rax,0x40(%rsp)
0x0000000180001487 <+87>: mov 0x40(%rsp),%rax
0x000000018000148c <+92>: add $0x58,%rsp
0x0000000180001490 <+96>: retq
0x0000000180001491 <+97>: int3
0x0000000180001492 <+98>: int3
0x0000000180001493 <+99>: int3
0x0000000180001494 <+100>: int3
0x0000000180001495 <+101>: int3
0x0000000180001496 <+102>: int3
0x0000000180001497 <+103>: int3
0x0000000180001498 <+104>: int3
0x0000000180001499 <+105>: int3
0x000000018000149a <+106>: int3
0x000000018000149b <+107>: int3
0x000000018000149c <+108>: int3
0x000000018000149d <+109>: int3
0x000000018000149e <+110>: int3
0x000000018000149f <+111>: int3
End of assembler dump.
(gdb)

Running on a fmusdk 64-bit fmu compiled with MSVC:


(gdb) r inc.fmu
Starting program: /cygdrive/c/Users/cxh/src/fmi/fmusdk/bin/x64/fmu20sim_cs.exe inc.fmu
[New Thread 4840.0x1b90]
warning: Application "\??\C:\Windows\system32\cmd.exe" found in cache

Breakpoint 1, 0x00007ffbbca112f7 in inc!fmi2Instantiate ()
from /tmp/fmu/binaries/win64/inc.dll
(gdb) disassemble fmi2Instantiate
Dump of assembler code for function inc!fmi2Instantiate:
0x00007ffbbca112e0 <+0>: mov %r9,0x20(%rsp)
0x00007ffbbca112e5 <+5>: mov %r8,0x18(%rsp)
0x00007ffbbca112ea <+10>: mov %edx,0x10(%rsp)
0x00007ffbbca112ee <+14>: mov %rcx,0x8(%rsp)
0x00007ffbbca112f3 <+19>: sub $0x68,%rsp
=> 0x00007ffbbca112f7 <+23>: mov 0x90(%rsp),%rax
0x00007ffbbca112ff <+31>: cmpq $0x0,(%rax)
0x00007ffbbca11303 <+35>: jne 0x7ffbbca1130c <inc!fmi2Instantiate+44>
0x00007ffbbca11305 <+37>: xor %eax,%eax
0x00007ffbbca11307 <+39>: jmpq 0x7ffbbca117b7 <inc!fmi2Instantiate+1239>
0x00007ffbbca1130c <+44>: mov 0x90(%rsp),%rax
0x00007ffbbca11314 <+52>: cmpq $0x0,0x8(%rax)
0x00007ffbbca11319 <+57>: je 0x7ffbbca1132a <inc!fmi2Instantiate+74>
0x00007ffbbca1131b <+59>: mov 0x90(%rsp),%rax
0x00007ffbbca11323 <+67>: cmpq $0x0,0x10(%rax)

Interestingly, comparing the two versions, they are the same until the 5th line.

Dymola fmu that fails:
0x0000000180001443 <+19>: sub $0x58,%rsp

fmusdk fmu that works:
0x00007ffbbca112f3 <+19>: sub $0x68,%rsp

Why are they different? Probably because inc's fmi2Instantiate has a local (ModelInstance *comp) on the stack. I'm not sure why they are 16 bytes different. Could be alignment.

In the 64-bit inc.fmu, fmi2Instantiate is defined in fmuTemplate.c:

  // ---------------------------------------------------------------------------
  // FMI functions
  // ---------------------------------------------------------------------------
  fmi2Component fmi2Instantiate(fmi2String instanceName, fmi2Type fmuType, fmi2String fmuGUID,
                            fmi2String fmuResourceLocation, const fmi2CallbackFunctions *functions,
                            fmi2Boolean visible, fmi2Boolean loggingOn) {
    // ignoring arguments: fmuResourceLocation, visible
    ModelInstance *comp;
    if (!functions->logger) {
        return NULL;
    }

Resources:

  • Invalid memory access (Stack Overflow) - Problem is with characters. Uses JNI, not JNA.
  • java jna probleme Structure invalid access memory (Stack Overflow) Problem same as next resource
  • Char** in java JNA #313 (Github JNA Issues)
  • Java interoperation with a Native DLL using JNA (Viaboxx) - nice overview of JNA.
    • "Create Java objects from array of C-structs:
      • "We map the return type of the function as a com.sun.jna.Pointer in Java. With the knowledge about the C-struct (sequence and data type of member variables), the java program can read and convert the memory content to create adequate objects. The number of elements in the array is also known (variable “numberOfResults”, see above). It is very important, to compute the offset correctly to avoid JVM-crashes for invalid memory access!"

JNA Alignment

"getTypeMapper(java.lang.Class) and getStructureAlignment(java.lang.Class) are provided to avoid having to explicitly pass these parameters to Structures, which would require every Structure which requires custom mapping or alignment to define a constructor and pass parameters to the superclass. To avoid lots of boilerplate, the base Structure constructor figures out these properties based on its enclosing interface."
"Memory.align() does not allocate more memory, it just changes the base pointer and reduces the size of the allocated block."

fmiCallbackLogger

The fmiCallbackLogger() function is a callback in the fmiFunctions.h in the FMUSDK:

   typedef void  (*fmiCallbackLogger) (fmiComponent c, fmiString instanceName, fmiStatus status,
                                         fmiString category, fmiString message, ...);

fmiPlatformTypes.h defines fmiComponent etc:

   typedef void*        fmiComponent;
   typedef unsigned int fmiValueReference;
   typedef double       fmiReal   ;
   typedef int          fmiInteger;
   typedef char         fmiBoolean;
   typedef const char*  fmiString ;
  • The jnaerator provided me with code that works:

FMILibrary.java:

    public interface FMICallbackLogger extends Callback {
        void apply(Pointer fmiComponent, Pointer instanceName, int status, Pointer category, Pointer message/*, String ... parameters*/);
    };
}

FMUCoSimulation.java:

     public interface FMULibrary extends FMILibrary {

        public class FMULogger implements FMICallbackLogger {          
            public void apply(Pointer c, Pointer instanceName, int status, Pointer category, Pointer message/*, String ... parameters*/) {
                System.out.println("Java FMULogger, status: " + status);
                System.out.println("Java FMULogger, message: " + message.getString(0));
            }
        }

However, when we run, we get various segfaults when the logger is invoked and we have the varargs arguments.

It turns out that the segfault problem was because the code was not properly allocating memory and keeping handles to the allocated memory. Thus, the allocated memory was being gc'd. The code in question has callbacks for allocating and freeing memory. The fix is to keep a list of allocated memory and have the allocate callback add a reference to the Java list and have the free callback remove the reference.

The code below more accurately represents the C code. FMILibrary.java:

    public interface FMICallbackLogger extends Callback {
        void apply(Pointer fmiComponent, String instanceName, int status, String category, String message/*, String ... parameters*/);
    };
}

FMUCoSimulation.java:

     public interface FMULibrary extends FMILibrary {

        public class FMULogger implements FMICallbackLogger {          
            public void apply(Pointer c, String instanceName, int status, String category, String message/*, String ... parameters*.) {
                System.out.println("Java FMULogger, status: " + status);
                System.out.println("Java FMULogger, message: " + message);
            }
        }
  • Tried using Object ... parameters or Pointer ... parameters:

After modifying jna/src/com/sun/jna/Structure.java so that the exception thrown includes the cause and updating $PTII/lib/jna.jar, I get:

Exception in thread "main" java.lang.IllegalArgumentException: Structure field "logger" was declared as
interface org.ptolemy.fmi.FMILibrary$FMICallbackLogger, which is not supported within a Structure
at com.sun.jna.Structure.writeField(Structure.java:717)
at com.sun.jna.Structure.write(Structure.java:635)
at com.sun.jna.Structure.autoWrite(Structure.java:1603)
at com.sun.jna.Function.convertArgument(Function.java:467)
at com.sun.jna.Function.invoke(Function.java:258)
at com.sun.jna.Function.invoke(Function.java:235)
at org.ptolemy.fmi.FMUCoSimulation.simulate(FMUCoSimulation.java:224)
at org.ptolemy.fmi.FMUCoSimulation.main(FMUCoSimulation.java:170)
Caused by: java.lang.IllegalArgumentException: Callback argument class [Ljava.lang.Object; requires custom type conversion
at com.sun.jna.CallbackReference.<init>(CallbackReference.java:203)
at com.sun.jna.CallbackReference.getFunctionPointer(CallbackReference.java:375)
at com.sun.jna.CallbackReference.getFunctionPointer(CallbackReference.java:357)
at com.sun.jna.Pointer.setValue(Pointer.java:894)
at com.sun.jna.Structure.writeField(Structure.java:709)
... 7 more

Timothy Wall commented:

"See the "caused" by exception, which causes the Callback field write to fail. JNA supports Callback (function pointer) fields within a structure, but in your case, one of the callback arguments is Object, which is not allowed (there is a system property "jna.allow_objects" or something similar intended to bypass that, but it's not thoroughly tested in all situations where an Object might be used).
"In general, JNA doesn't allow you to pass Java object references to native code, since that raises all sorts of reference tracking/GC issues."

JNA Custom Type Conversion

Search for "requires custom type conversion" brings up:

This is incomplete

I was able to create a custom type conversion called FMITypeMapper.java. See jna/src/com/sun/jna/win32/W32APITypeMapper.java. To include the mapper, I added the following to FMILibrary.java. This needed to appear in the Library interface class.

public TypeMapper TYPE_MAPPER = FMITypeMapper.FMITYPEMAPPER;
Edit - History - Print - Recent Changes - Search
Page last modified on February 26, 2015, at 11:08 AM