C function call from Java

How to call c function from Java. C seems to be compiler based.

I would like to call the C function on Windows with Java, and the GCC function is also available for Java.

Any link?

+47
java c
May 11 '11 at 11:11
source share
10 answers

Check out the Java Native Interface: Getting Started .

2.1 Overview

[...] write a simple Java application that calls the C function to print "Hello world!" The process consists of the following steps:

Create a class (HelloWorld.java) that declares a native method. using javac to compile the source HelloWorld file, leaving the class a HelloWorld.class file. The javac compiler comes with a JDK or Java 2 SDK release. Use javah -jni to create the C header file ( HelloWorld.h ) containing the function prototype for the native implementation method. The javah tool is provided with JDK or Java 2 SDK releases. Write an implementation of the C ( HelloWorld.c ) native method. Compile the C implementation into a native library by creating Hello-World.dll or libHello-World.so . Use the C compiler and linker available in the host environment. Launch the HelloWorld program using the java runtime interpreter. Both class files ( HelloWorld.class ) and loaded their own library ( HelloWorld.dll or libHelloWorld.so ) at runtime. The remainder of this chapter explains these steps in detail.

2.2 Declare a custom method

You start by writing the following program in the Java programming language. The program defines a class called HelloWorld, which contains its own method, printing.

 class HelloWorld { private native void print(); public static void main(String[] args) { new HelloWorld().print(); } static { System.loadLibrary("HelloWorld"); } } 

The definition of the HelloWorld class begins with the declaration of its own printing method. This is followed by the main method, which creates an instance of the Hello-World class and calls its own printing method for this instance. The last part of the class definition is a static initializer that loads its own library containing an implementation of its own printing method. A.

There are two differences between declaring a native method such as printing and declaring regular methods in the Java programming language. The native method declaration must contain its own modifier. The native modifier indicates that this method is implemented in another language. In addition, the declaration of the native method ends with a semicolon, the symbol of the operator terminator, because the class does not have an implementation for its own methods. We will use the printing method in a separate C file.

Before you can call printing the native method, there is a built-in library that implements printing. In this case, we load the libraries in the static initializer of the HelloWorld class. The Java virtual machine automatically starts the static initializer before invoking any methods in the HelloWorld class, thereby ensuring that the source library is loaded before the native printing method is called. A.

We define the main method to be able to run the HelloWorld class. Hello-World.main calls its own printing method in the same way as it will call a regular method.

System.loadLibrary takes the name of the library, finds its own library that matches that name, and loads its own library into the expression. We will discuss the exact loading process later in the book. For now, just remember that for System.loadLibrary("HelloWorld") to succeed, we need to create a native library called HelloWorld.dll on Win32, or libHelloWorld.so on Solaris.

2.3 Compile the HelloWorld class

After you define the HelloWorld class, save the source code in the HelloWorld.java file. Then compile the source file using javac, which comes with the JDK or Java 2 SDK version:

  javac HelloWorld.java 

This command will generate a HelloWorld.class file in the current directory.

2.4 Create a source code header file

Next, we will use the javah tool to create a JNI-style header file. This is useful when implementing our own method in C. You can run javah in the Hello-World class as follows:

  javah -jni HelloWorld 

The header file name is the class name with the addition of " .h " to the end. The command shown above generates a file called HelloWorld.h . We will not list the entire header file generated. The most important part of the header file is the function prototype for Java_HelloWorld_print , which is a C function that implements the HelloWorld.print method:

  JNIEXPORT void JNICALL Java_HelloWorld_print (JNIEnv *, jobject); 

Ignore JNIEXPORT and JNICALL . You may have noticed that the C implementation of the native method accepts two arguments, even if the corresponding declaration of the native method accepts no arguments. The first argument for each native implementation method is the JNIEnv interface JNIEnv . The second argument is a reference to the HelloWorld object itself (sort of like a " this " pointer in C ++). We will discuss how to use the JNIEnv pointer interface and jobject arguments in this book, but this simple example ignores both arguments.

2.5 Write down the original implementation method

The JNI-style header file generated by javah allows you to write C or C ++ for your own method. The function you write should follow the -prototype specified in the generated header file. You can implement the Hello-World.print in the C file of HelloWorld.c as follows:

 #include <jni.h> #include <stdio.h> #include "HelloWorld.h" JNIEXPORT void JNICALL Java_HelloWorld_print(JNIEnv *env, jobject obj) { printf("Hello World!\n"); return; } 

The implementation of this native method is simple. It uses the printf function to display the string "Hello World!" and then comes back. As mentioned earlier, both arguments, the JNIEnv pointer JNIEnv and the object reference are ignored.

Program C includes three header files:

jni.h - This header file provides the information needed for the internal code to invoke JNI functions. When writing your own methods, you should always include this file in the C or C ++ source files. stdio.h - The code snippet above also includes stdio.h , since it uses the printf function. HelloWorld.h is the header file you created with javah . It includes a C / C ++ prototype for the Java_HelloWorld_print function. 2.6. Compile the C source and create your own library.

Remember that when you created the HelloWorld class in HelloWorld.java , you included a line of code that loaded the native library into the program:

  System.loadLibrary("HelloWorld"); 

Now that all the necessary C code has been written, you need to compile Hello-World.c and build this native library.

Different operating systems support different ways to create your own library. On Solaris, the following command creates a shared library called libHello-World.so:

  cc -G -I/java/include -I/java/include/solaris HelloWorld.c -o libHelloWorld.so 

The -G option tells the C compiler to generate a shared library instead of the regular Solaris startup file. Due to page width limitations in this book, we split the command line into two lines. You need to enter the command on one line or put the command in a script file. On Win32 following command creates the HelloWorld.dll dynamic link library (DLL) using the Microsoft Visual C ++ compiler:

  cl -Ic:\java\include -Ic:\java\include\win32 -MD -LD HelloWorld.c -FeHelloWorld.dll 

The -MD parameter ensures that HelloWorld.dll is associated with the Win32 C multithreaded library. The -LD parameter tells the C compiler to generate the DLL instead of the regular Win32 executable. Of course, on Solaris and Win32 you need to include the included paths that reflect the configuration of the machine itself.

2.7 Run the program

At this point, you have two components ready to run the program. The class file ( HelloWorld.class ) calls its own method, and the native library ( Hello-World.dll ) implements its own method.

Since the HelloWorld class contains its own main method, you can run programs on Solaris or Win32 as follows:

  java HelloWorld 

You should see the following output:

  Hello World! 

It is important to set your path to the source library correctly for your program. The root path of the library is a list of directories that the Java virtual machine looks for when loading native libraries. If you do not have the path to the source library correctly, then you will see an error similar to the following:

  java.lang.UnsatisfiedLinkError: no HelloWorld in library path at java.lang.Runtime.loadLibrary(Runtime.java) at java.lang.System.loadLibrary(System.java) at HelloWorld.main(HelloWorld.java) 

Make sure that the native library is in one of the directories in the root path of the library. If you are running a Solaris system, the LD_LIBRARY_PATH environment variable is used to determine the path of your own library. To do this, make sure that it contains the name of the directory containing libHelloWorld.so . If the libHelloWorld.so file is in the current directory, you can issue the following two commands in the shell (sh) or KornShell (ksh) standard to configure the LD_LIBRARY_PATH environment variable:

  LD_LIBRARY_PATH=. export LD_LIBRARY_PATH 

The equivalent command in the C shell (csh or tcsh) is as follows:

  setenv LD_LIBRARY_PATH . 

If you are running Windows 95 or Windows NT, make sure that HelloWorld.dll is located in the current directory or in the directory specified in the PATH environment variable.

In Java 2 SDK 1.2, you can also specify your own library path on the java command line as a system property as follows:

  java -Djava.library.path=. HelloWorld 

The -D command line parameter sets the Java platform system property. Setting java.library.path The " . " Property instructs the Java virtual machine to search for native libraries in the current directory.

+50
May 11 '11 at 11:13
source share

Simply put, just load the appropriate library that contains the function definition, load the library that follows the JNI specification and wrap the target function from the first library, expose your own methods from your Java class, and you should be good to go.

I would recommend against raw JNI, as it contains a lot of template code, and you end up cursing yourself if you start wrapping up the large C library. Anyway, feel free to play JNI when you start, but use something like JNA when it comes to real work.

+10
May 11 '11 at 11:15
source share

You have options:

Java Explicit Interface
see https://en.wikipedia.org/wiki/Java_Native_Interface

quote:

JNI allows programmers to write their own methods for handling situations when an application cannot be completely written in the Java programming language, for example. when the standard Java class library does not support platform-specific functions or a program library

Explicit Java Access

see https://en.wikipedia.org/wiki/Java_Native_Access

quote:

Java Native Access is a community-developed library that provides Java programs with easy access to their native shared libraries without using the Java Native interface.

JNR-FFI

see: https://github.com/jnr/jnr-ffi

quote:

jnr-ffi is a java library for loading your own libraries without writing JNI code manually or using tools such as SWIG.

+3
Jan 15 '15 at 10:42
source share

In the exotic category, see NestedVM, which compiles C into Mips and launches the Mips VM inside the JVM.

http://nestedvm.ibex.org/

+2
Sep 03 '14 at 20:27
source share

If you use Windows and MinGW gcc, you may need an additional flag if you get UnsatisfiedLinkError for a specific method in lib:

 gcc -D_JNI_IMPLEMENTATION_ -Wl,--kill-at -I"%JAVA_HOME%"\include -I"%JAVA_HOME%"\include\win32 BestCode.c -shared -o BestCode.dll 
+1
Jun 09 '16 at 8:12
source share

JNI - Java Native Interface

To call the C function from Java, you need to use JNI

0
Mar 22 '13 at 20:16
source share

Checkout JNAerator. https://code.google.com/p/jnaerator/

You need to specify the source code and preprocessor definitions, etc.

0
Apr 24 '15 at 12:42
source share

To create a 64-bit compatible dll. Remove the -MD option from the instructions below

"cl -Ic: \ java \ include -Ic: \ java \ include \ win32 -MD -LD HelloWorld.c -FeHelloWorld.dll"

0
May 18 '15 at 6:51
source share

I have a solution to this problem. What you need is a code compilation using a 64-bit C ++ compiler to call a java function running on a 64-bit JRE. Along with this, we need to save the path of the created dll file to "Path" in the "Environment Variable" section.

0
Jul 20 '15 at 6:51
source share

First, make sure you upload your native library or DLL file to the class path by setting the path in the java.library.path property

Then use System.loadLibrary()

 Do not use .dll extension at the end. 
0
Sep 07 '17 at 2:19 on
source share



All Articles