Reading a Cube Voyager Matrix from Java using JNA
I've begun to really enjoy Java. It's hot, black exterior exposes a sweet bitterness that matches few other things in this world. Oh, wait, this is supposed to be about the other Java - the programming language!
The "Holy Grail" of API programming with Cube Voyager to me has been using the API in Java. I can program in C++ quite well, but I have a staff that can't. We're likely going to be going to a Java based modeling structure in the next few years, so it makes sense to write everything in Java and keep the model down to two languages - Cube Voyager and Java.
Setting up the Java Environment
There are three things to do to setup the Java environment to make this work. The first is to place the Cube DLL in the right location. The second is to get JNA and locate the libraries to where you need them. The final is to setup the Java execution environment.
First, copy the VoyagerFileAccess.dll file (and probably it's associated lib file) to C:\Windows. It should work. I'm using a Windows 7-64 bit machine, so if it doesn't work, try C:\Windows\System32 and C:\Windows\System.
Second, get JNA. This allows the Java compiler to connect to the DLL. The latest version can be downloaded from Github (go down to "Downloads" under the Readme.md... just scroll down 'till you see it, and get both platform.jar and jna.jar).
If you're on a 64-bit computer, the second thing to do is to set your jdk environment to use a 32-bit compiler. I use Eclipse as my IDE, so this is done through the project properties. One location is the Java Build Path - on the Libraries tab, make sure the JRE System Library is set to a 32-bit compiler. In the Java Build Path screenshot below, you can see that all the locations are in C:\Program Files (x86) - this is an easy (although not foolproof) way to show that this is a 32-bit compiler.
While you're setting up stuff in this window, make sure the jna.jar and platform.jar are linked here as well (click "Add External JARs..." and locate those two files).
Another place to check in Eclipse is the Java Compiler settings, which should have "Use Compliance from execution environment..." checked.
The thing that makes this work is this part of the programming. You can see in this that I create an interface t0 the Voyager DLL file by loading the DLL, and then setup some pointer objects to hold the memory pointer variable (the "state" variable in all of these) and set up the functions to read from the matrix.
The next part that makes this work is the actual programming. In the code below, the first thing I do is define vdll as an instance of the voyagerDLL interface. Then, I open a matrix file (yes, it is hard-coded, but this is an example!), get the number of matrices, zones, the names, and I start reading the matrix (in the for loops). I only print every 100th value, as printing each one makes this slow a bit. The actual reading is quite fast. Finally, I close the matrix and the program terminates.
The big issue I noticed is that if the matrix is not found, the Pointer variable returned by MatReaderOpen will be null, but nothing will be in the error value. I've tried redefining the error value to be a string in the interface, but it does the same thing. However, I don't recall if it did anything in C++. At any rate, there needs to be some error checking after the matrix is opened to ensure that it actually has opened, else the program will crash (and it doesn't do a normal crash).
The next thing I'm going to do is the path files.