atom feed4 messages in org.netbeans.openide.devRe: [openide-dev] Using JNI in a netb...
FromSent OnAttachments
Andreas StefikFeb 13, 2009 1:06 pm 
Wade ChandlerFeb 13, 2009 1:44 pm 
Wade ChandlerFeb 13, 2009 1:46 pm 
Andreas StefikFeb 13, 2009 1:55 pm 
Subject:Re: [openide-dev] Using JNI in a netbeans module Suite.
From:Wade Chandler (hwad@yahoo.com)
Date:Feb 13, 2009 1:44:58 pm
List:org.netbeans.openide.dev

See: http://wiki.netbeans.org/DevFaqNativeLibraries

Code using the working directory to load components like that isn't good usually
(Java, native, or otherwise)...not unless you can specifically control the
startup directory which is pretty hard. Better solutions involve locating a path
and then having that file relative to that path. For instance, you have the
native library in your NB module and put it under
yourprojectdir/release/modules/lib/

Then, this will be locatable easily enough using:

org.openide.modules.InstalledFileLocator locator = org.openide.modules.InstalledFileLocator.locate("modules/lib/SappyJNI.dll",
"your.code.name.base.for.your.module", false); or similar methods. Having the file there will place it on the library path
however, and you can use the cross platform library loading techniques. If you
need to use the same library from different places such as regular Java code and
NB module code you can have different code for each situation which sets up some
things for the library. Then it can use that information to set itself up...load
the library etc.

You can even have some default information and ways of working which can then be
overridden by different logic in different systems as well to make a default
scenario for plain JSE applications. In those type applications you can still
get relative paths to your Sappy Java classes using something like: URL relBase =
my.sappypackage.SappyClass.class.getResource("/my/sappypackage/SappyClass.class");

and then parse that to get either the .jar file if you have your classes in a
JAR file or folder if not in a JAR file (will be a direct file URL or it will be
a JAR url depending). Once you have that you can then build a relative path to
anything relative to that class file (folder) or its .jar file.

Wade

================== Wade Chandler, CCE Software Engineer and Developer, Certified Forensic Computer Examiner, NetBeans
Dream Team Member, and NetBeans Board Member http://www.certified-computer-examiner.com http://wiki.netbeans.org/wiki/view/NetBeansDreamTeam http://www.netbeans.org

________________________________ From: Andreas Stefik <stef@gmail.com> To: de@openide.netbeans.org Sent: Friday, February 13, 2009 4:07:10 PM Subject: [openide-dev] Using JNI in a netbeans module Suite.

Hey folks,

My team here at Central Washington University has been working on a netbeans
module suite for a custom compiler and debugger architecture. After months of
work, we finally have a basic version of our system more or less working in the
environment. However, our tools use SAPI connections to Microsoft's text to
speech engine (on windows). As far as I understand it, there are a couple ways
to get access to SAPI connections from Java in General, all involving some kind
of JNI access. There are third party tools like CloudGarden (which works "ok"
but is horribly supported and out of date), but we have rolled our own tool
called sappyJNI, which is a very simple JNI DLL that gives us considerable
control over our text-to-speech engine.

Our DLL works great when outside of the netbeans environment, but we are having
some difficulties getting it to work in our module suite. First, we want our
DLL, preferably, to be loaded via a relative path, so instead of dumping into
someplace under the PATH variable (which would require the students here have
admin access on some of our machines), we are using the typical methods, which
look something like this:

File sappyJNI = new File("sappy" + File.separatorChar + "SappyJNI.dll"); //System.loadLibrary("SappyJNI"); //this way is more cross platform, but we
aren't using it. System.load(sappyJNI.getAbsolutePath());

All of the native methods are in a module in our suite called "compiler" and the
methods are in org.sapi; We've been calling the SAPI code from within the same
module.

Now, when NetBeans loads a module suite, the value of this path appears to be
the top level directory for the suite, which means that it looks for our DLL in
<SomePath>SodBeans/sappy/sappy.dll. With this path, Netbeans appears to find the
DLL and, as far as we can tell, load it correctly. However, in addition to this
dll, sappy.dll actually has to call a second DLL (an interop assembly for SAPI
connections), but we do not call it directly from Java. This system works fine
outside of our module suite using typical Java code.

But once we go into our suite, something odd happens. Once NetBeans has loaded
the dll, our Java wrapper class allows to call native methods (e.g.,
speak(string st)), but when we make a call, no sound is output! We are a bit
perplexed. Any advice would be helpful.

Some questions:

1. Do we have to do anything special to get JNI to work in a module suite?

2. I've heard that in NetBeans that you have to do some additional work if your
DLL references another DLL. If this is really true, is it related to what might
be going wrong? Suggestions?

3. Any tips for how to handle this JNI issue when we deploy? Do we need to do
anything special for deployment, because of the JNI work (Assuming windows only,
for now)?

Thanks in advance folks, any ideas are welcome,

Andreas