Invoking Native Code on OS X

I'm a developer at Autodesk interested in exposing a subset of our surface and solid modeling kernel to the Processing community: the ACIS kernel used in AutoCAD, CATIA, SolidWorks, NX Unigraphics, Revit, and parts of Alias and Maya. A java library has been written, but I'm running into trouble loading this library in Processing.

The specific error I'm getting is:

A library relies on native code that's not available. Or only works properly when the sketch is run as a 32-bit application

My library loads our internal dylib using JNI:

public class LibGForProcessing { static { System.loadLibrary("LibG"); } ... }

To be used in a Processing sketch as follows:

import autodesk.libg.*; LibGForProcessing l = new LibGForProcessing(this); void setup() { size(400, 400); Point p = Point.by_coordinates(0, 0, 0); } void draw() { background(0); }

I've verified that I can run the library on command line java (Java HotSpot(TM) 64-Bit Server VM) with the following script:

import autodesk.libg.*; class LibGJavaTest { static { System.loadLibrary("LibG"); } public static void main(String[] args) { LibG.start_asm_library(); Point p1 = Point.by_coordinates(0, 0, 0); Point p2 = Point.by_coordinates(10, 10, 0); Line line = Line.by_start_point_end_point(p1, p2); double d = line.length(); System.out.println("d is " + d); LibG.end_asm_library(); } }

A have a feeling that the problem lies with OS X not being able to find one of the dependencies of the library, of which there are many. Here's the otool output for the dylib I load with JNI:

bash-3.2$ otool -L libLibG.dylib libLibG.dylib: .//libLibG.dylib (compatibility version 0.0.0, current version 0.0.0) ./bin/libdsnetwork.dylib (compatibility version 0.0.0, current version 0.0.0) ./bin/libgcore.dylib (compatibility version 0.0.0, current version 0.0.0) /usr/local/lib/libboost_thread-mt.dylib (compatibility version 0.0.0, current version 0.0.0) /usr/local/lib/libboost_system-mt.dylib (compatibility version 0.0.0, current version 0.0.0) @rpath/libASMahl220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMbase220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMblnd220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMbool220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMcovr220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMcstr220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMct220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMdatax220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMdefm220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMeulr220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMfct220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMfrec220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMga220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMheal220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMimport220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMintr220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMkern220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMlaw220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMlop220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMlopt220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMmatrix220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMnpch220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMofst220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMoper220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMpid220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMrbase220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMrbi220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMrem220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMsbap220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMsbool220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMshl220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMskin220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMswp220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMtopt220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMtwk220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMufld220A.dylib (compatibility version 0.0.0, current version 2200.18.11) @rpath/libASMweld220A.dylib (compatibility version 0.0.0, current version 2200.18.11) /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.0.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)

I've created a bin directory inside of the lib directory of the library folder, containing both libdsnetwork.dylib and libgcore.dylib

Could anyone on the forum help with the following questions:

  • Is there any way to set the @rpath for this Processing library?
  • Where does JNI look for libraries when it's invoked inside of Processing? Does ./bin resolve to the lib folder of the library folder, or is it somewhere in the main Processing.app folder?
  • Is there any way to get a more detailed output from Processing to see which library it's failing to load? I've run Processing inside of dtruss and I can't see any calls to load a library.
Tagged:

Answers

  • I put together a Windows version of this library, hoping that Window's lack of @rpath, LD_LIBRARY_PATH, etc would fair better, and am getting the exact same error:

    A library relies on native code that's not available.
    Or only works properly when the sketch is run as a 32-bit  application.
    

    All the required DLLs are inside of the lib directory of the library, the same directory the library jar is located in.

    Could anyone with experience loading native code libraries into Processing give me advice?

  • Hi tiernep,

    I had a similar problem lately with System.loadLibrary(). If you check Library.java in the processing sources you will see that the .jni library needs to be in specific folders:

          if (file.isDirectory()) {
            if (name.equals("macosx")) return false;
            if (name.equals("macosx32")) return false;
            if (name.equals("macosx64")) return false;
            if (name.equals("windows")) return false;
            if (name.equals("windows32")) return false;
            if (name.equals("windows64")) return false;
            if (name.equals("linux")) return false;
            if (name.equals("linux32")) return false;
            if (name.equals("linux64")) return false;
            if (name.equals("android")) return false;
          }
          return true;
    

    you can also use the export.txt to define custom folder names but i guess it makes the most sense just to use the folder names anyway.

    The next step is to check for the run paths of the dependent .dylibs which you did with otool. What I ended up using is install_name_tool -id @loader_path

  • Post wasn't finished: If you use @loader_path you can define a path relative to wherever the jnilib is executed. This is all just tested under osx though.

  • Oh, and of course the jni-folder is relative to where you .jar is, so the library folder in your processing library. If this doesn't work it might have something to do with the other dependencies.

  • @wilm thanks for the hints. @tiernep, let us know if that fixes the problem on OSX. This article on the difference between @executable_path, @loader_path and @rpath could be useful.

    As for the error on windows, a trick I use in the video library is to preload all the DLLs, take a look at this code: https://github.com/processing/processing/blob/master/java/libraries/video/src/processing/video/LibraryLoader.java

Sign In or Register to comment.