JNI to call .NET dll - java

I am trying to create a Java Application that will call C# dll through an intermediate Visula C++ dll, its all well and good when I try to run the .class file from cmd prompt or Eclipse IDE but the problem is in order to do it I need to place the C# dll in the same directory as the Java.exe or else there occurs an exception the the native call, thus making to impossible to build the Java Project, any idea as to how this can be done

There are other ways, without COM. You might find one preferable or need one if you can't change the .NET component to support COM clients.
When a process that loads the CLR, the assembly search paths are determined by the location of the process's main Win32 module. Assembly search paths are different than Win32 DLL search paths. In this case, it starts with the location of java.exe. As a result, the search paths include the Global Assembly Cache (GAC), the folder of java.exe, and subfolders listed as assembly probing paths in java.exe.config (if it exists).
See How the Runtime Locates Assemblies.
This leads to a few options:
Install the assembly in the GAC. (On an end-user machines an installer should be used but on a developer machine, you can use gacutil.)
Put the assembly in the java.exe folder. Or, conversely, put a copy of Java in your application folder.
Create a subfolder with write permissions for the assembly. Create or update a java.exe.config and list the subfolder as a probing path.
Create your own java.exe in C or C++ using the Java Invocation API. It's documented alongside JNI. You can name it whatever you wish since, after all, it is your application. (This what many Java-based applications do, even if they don't use .NET. For example, eclipse and LibreOffice.) The documentation gives a complete example in C. For a typical MSVC build, jni.h needs to on the project's include path, jvm.lib needs to be on the project's library path, and jvm.dll needs to be in the Win32 DLL search path.
Other alternatives:
The VC DLL can load the assembly explicitly from a path before the assembly is needed. See Assembly::LoadFile.
Load the assembly on demand after it's not found by the standard search. See AppDomain::AssemblyResolve Event (but note it's description is wrong: failure has not occurred until and if your custom resolver(s) fails).

You can enable and register your managed (.NET) dll with COM Interop.
See this link: http://support.microsoft.com/kb/828736

Related

Where would one put a JNI module in Linux or OS X

The Java application has the JNI module to use.
Where should a user (or an installation script of this application) put the JNI module on Linux (Ubuntu) or on MacOS X so that this JNI module could be loaded without specifying the path to the module in code?
This is a link to a detailed explanation of shared objects and how they are searched for by the OS.
I wish Java people would stop using LD_LIBRARY_PATH and start using the existing directory structures and the ld.so.conf mechanism. Even the OpenJDK libraries are dumped in a place that's not on a standard path and they don't add an ld.so.conf file either ( just how hard is that ? ).
This approach avoids the need to set up your own LD_LIBRARY_PATH and launch via a shell script.
If a required shared object is to be installed, first test for somewhere like /usr/local/lib as an installation choice system wide, and if it exists and an existing file does not already use your file's name, then put your library there. A more systematic approach would be to check all the ld.so.conf files and see if any of the directories match something you know can be used. A shell script can do that at install time.
Put the compiled libraries (.so files on Linux or .dylib on MacOS) into a directory of your choice and include this directory in the library search path LD_LIBRARY_PATH used to start your JVM.

Java calling an external process - exe

I am building a java application, which at some point utilizes an external exe. At this point, I'm trying to simply add this exe as some sort of library, which I can use in process call, so user wouldn't have to install it..
This exe file is an command line tool which produces some output, which is further processsed by the application.
So my question is, how does one include exe file within a java application, instead of calling it as a system process. Also acceptable would be, if this exe would be for example in the final lib folder, where java app would fetch it and execute it.
I hope it is clear and thanks for any help.
Java interacts with other (native) code in a couple of ways:
to specifically coded libraries through Java Native Interface (JNI)
to external tools by forking a child process using Runtime.getRuntime().exec(...)
through network communications
In the first case, it is useful to include your JNI library with you Java program. It's thinkable to include it as a class resource in your JAR file, but that would be against the ideas of JAR files (holding classes and resources). More likely you should bundle the library (for all target platforms) with some sort of installation package (e.g. InstallAnywhere or others)
In the second case it's not useful to include the binary into your Java program (i.e. in the JAR file). Rather it most likely has (should have) its own installation procedure and your Java code should use an appropriate commandline (PATH) to find the executable.
I think the third case is not relevant.

Cross-platform Java with native libraries

I am trying to implement a wrapper for native libraries that will be consumed via JNI in a Java application. I want to make installation of the program be as simple as "Unzip this file and run".
I've worked through most of the wrapper so far, getting it to unzip the native libraries from inside the platform-specific JAR file and setting the -Djava.native.lib variable at runtime. I've hit one last roadblock due to unsatisfied link errors.
On Windows, the DLLs that I'm calling link against msvcr100.dll. While the DLLs that I'm calling into are getting picked up by java.native.lib, msvcr100.dll isn't. I don't want to have to require the user to install the C++ runtime before using our app, so we are packaging the DLL file right along side the other DLLs.
As far as I understand, to get things to work we need to put the folder that contains msvcr100.dll on the PATH. I tried using reflection to change the environment inside the application to add the unpack directory to the PATH environmental variable. After this was unsuccessful, I recalled that I was only modifying a copy of the environment.
Is there some way that I can fix the unsatisfied link error without requiring any additional system setup (installing the runtime, hand modification of PATH, etc)? I would think it is possible since I've encountered other pieces of software (SWT, JOGL) that package native libraries that don't exhibit this issue.

Preparing JNA for use in Eclipse

Background:
I'm doing machine learning research, and want to use the FANN library to construct neural networks. The source code is written in C, but I need it wrapped so that I can use it with a lot of Java classes we've created.
Question:
The website provides a link to an already well received wrapper software called fannj. Its dependencies is the FANN library source code and JNA. I've never done wrapping before so JNA is brand new to me. The github homepage for the code mentions "you must set the jna.library.path system property to the path of the FANN Library". I'm currently in the process of trying to do this in Eclipse on Mac OS X. A friend of mine mentioned to me earlier that it means I have to pass the location of the FANN library as argument to the virtual machine, but he only showed me how to do this via the shell. I never actually ran this command from the shell, because I wasn't sure how it would conflict with whatever configurations I do in Eclipse later.
How do I set the jna.library.path in Eclipse? The JNA directory is huge, and I don't know where the actual executable is. My friend suggested I modify its run configuration through use of the argument tab, but like I said I don't actually know where the executable is. All I have is the large uncompressed jar file. How can I go about getting it set up in Eclipse?
You don't set in an IDE, just insert in some piece of code that is called BEFORE JNA is called, something like this:
System.setProperty("jna.library.path", "path you need");
Where System is java.lang.System. As for what path you need it must be the path that contains compiled dynamically linked FAAN library (a *dll).
Or just forget that alltogether and dump FAAN (*dlls, *so..) into Windows/system32 (or other appropriate folder on system you use) and these dll's will be on default search path.
Two allow Eclipse to use JNA, all you need to do is to put two jar files in Eclipse's Java Build Path, jna.jar and platform.jar. That's it.
To do this for an individual project, right click on the project in the Package Explorer, click Properties (at the bottom), click Java Build Path on the left, then the Add External Jar files. Browse to the directory with your JNA files and add those two files.

JNI-wrapped library seeks out wrong working directory -- how to circumvent?

I am using JNI to wrap a few native functions in a closed-source PDF library. It has an dependent fonts directory which must be in a subfolder of the calling application's directory. In my experience, it is standard to seek based on the current working directory. Thus, the problem.
When loading the JNI code into a Java application, the current working directory is correct. However, the calling application's directory is java.exe's bin directory. I have verified that putting the dependent fonts folder in C:\Program Files (x86)\Java\jre6\bin folder works as expected.
The library seems to be using a C++ GetCommandLine() call, or something similar to determine where the fonts directory should be. Obviously, this is an unacceptable solution.
I'd like to avoid calling an external EXE. But the only workarounds that I've come up with are:
Compile an EXE, place in Java project directory, and use Java's Runtime.exec() to execute. (this does work)
Make JNI code launch a separate process which does the same as above (gains nothing but more complexity)
Any ideas on how I can circumvent this problem? When Java applications are compiled as a runnable JAR, is the resultant command line still the JRE's C:\Program Files\...java.exe?
A Java executable maker can create an executable *.exe from your Java application without any native coding or compiling. You can put that executable, the jar files, the fonts and other application dependencies into a single install directory.
Exe4j is one of the executable makers that will support this, for Windows. It does not require any assumptions about the current working directory. This is important in the frequent case where you have no control over what the working directory is when the application is launched.

Categories

Resources