从Java调用C函数 [英] Call c function from Java

查看:109
本文介绍了从Java调用C函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何从Java调用C函数。
似乎C是基于编译

How to call c function from Java. Seems c is compiler based.

我想从Java调用C函数在Windows和
GCC功能弗朗的Java了。

I would like to call C function in Windows from Java, and GCC function fron Java too.

的内容?

推荐答案

在看一看<一个href=\"http://web.archive.org/web/20120419230023/http://java.sun.com/docs/books/jni/html/start.html\">Java本地接口:入门

2.1概述

[...]编写调用C函数打印一个简单的Java应用程序
  你好,世界!。该过程包括以下步骤:

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

创建一个类(HelloWorld.java)声明本机方法。使用
  的javac编译的HelloWorld源文件,导致类
  文件HelloWorld.class的。 javac编译器与JDK或Java提供
  2 SDK版本。使用 JAVAH -jni 来生成一个C头文件
  包含函数原型为本地方法( HelloWorld.h
  实现。该javah工具带有JDK或Java 2 SDK
  版本。写C实现的( HelloWorld.c )的本土
  方法。编译C实现到本机库,创建
   HELLO-World.dll libHello-World.so 。使用C编译器和连接器
  可在主机环境。使用运行HelloWorld程序
  Java运行时间preTER。无论是类文件(的HelloWorld.class
  和本机库( HelloWorld.dll libHelloWorld.so )将装载
  在运行时。本章的其余部分解释这些步骤
  详细信息。

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

2.2声明本机方法

您开始用Java编程写下面的程序
  语言。该程序定义一个类名为HelloWorld包含
  本地方法,打印。

You begin by writing the following program in the Java programming language. The program defines a class named HelloWorld that contains a native method, print.

 class HelloWorld {

 private native void print();

 public static void main(String[] args) {
     new HelloWorld().print();
 }

 static {
     System.loadLibrary("HelloWorld");
 }  }


  
  

HelloWorld类定义开始打印本地方法的声明。接着是一个主要方法,该方法
  实例的Hello-世界一流的,并调用打印本地方法
  此实例。类定义的最后部分是静态
  加载包含本地库初始化
  执行打印本地方法的。

The HelloWorld class definition begins with the declaration of the print native method. This is followed by a main method that instantiates the Hello-World class and invokes the print native method for this instance. The last part of the class definition is a static initializer that loads the native library containing the implementation of the print native method.

有一个本地方法的声明之间有两个区别
  如打印和在Java常规方法的声明
  编程语言。本地方法声明必须包含
  native修饰符。 native修饰符表明,该方法是
  在另一种语言实现的。此外,本机方法声明
  终止用分号,语句终止符号,
  因为在类的本地方法没有实现
  本身。我们将实现在一个单独的C文件打印方法。

There are two differences between the declaration of a native method such as print and the declaration of regular methods in the Java programming language. A native method declaration must contain the native modifier. The native modifier indicates that this method is implemented in another language. Also, the native method declaration is terminated with a semicolon, the statement terminator symbol, because there is no implementation for native methods in the class itself. We will implement the print method in a separate C file.

之前,本地库
  实现打印,必须被加载。在这种情况下,我们加载机
  图书馆在的HelloWorld 类的静态初始化。在Java
  虚拟机自动运行前的静态初始化
  调用在的HelloWorld 类的任何方法,从而确保
  被称为打印机方法之前,本地库被加载。

Before the native method print can be called, the native library that implements print must be loaded. In this case, we load the native library in the static initializer of the HelloWorld class. The Java virtual machine automatically runs the static initializer before invoking any methods in the HelloWorld class, thus ensuring that the native library is loaded before the print native method is called.

我们定义了一个main方法,以便能够运行的HelloWorld 类。
   HELLO-World.main 调用在相同的方式,本地方法打印
  它会调用一个普通的方法。

We define a main method to be able to run the HelloWorld class. Hello-World.main calls the native method print in the same manner as it would call a regular method.

的System.loadLibrary 需要一个库名,找到本机库,
  对应于该名称,并加载机库进
  应用。稍后我们将讨论的具体加载过程中
  书。现在只需记住,为了
  的System.loadLibrary(HelloWorld的)来取得成功,我们需要创建一个
  所谓本地库 HelloWorld.dll 在Win32或 libHelloWorld.so
  Solaris操作系统。

System.loadLibrary takes a library name, locates a native library that corresponds to that name, and loads the native library into the application. We will discuss the exact loading process later in the book. For now simply remember that in order 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编译HelloWorld类

2.3 Compile the HelloWorld Class

您已经定义了HelloWorld类后,保存在源$ C ​​$ C
  文件调用HelloWorld.java。然后,使用编译源文件
  自带的JDK或Java 2 SDK发布javac编译:

After you have defined the HelloWorld class, save the source code in a file called HelloWorld.java. Then compile the source file using the javac compiler that comes with the JDK or Java 2 SDK release:

 javac HelloWorld.java

此命令将生成一个的HelloWorld.class
  文件在当前目录。

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

2.4创建本地方法头文件

2.4 Create the Native Method Header File

下一步,我们将使用 JAVAH 工具来生成JNI风格的头文件
  该实施C.本地方法可以在运行时非常有用
   JAVAH 你好,世界类,如下所示:

Next we will use the javah tool to generate a JNI-style header file that is useful when implementing the native method in C. You can run javah on the Hello-World class as follows:

  javah -jni HelloWorld


  
  

头文件的名称是类名
  着有 .H 追加到它的结束。上面所示的命令
  生成一个名为 HelloWorld.h 。我们不会列出生成
  在这里以其整体头文件。的最重要的部分
  头文件的函数原型为 Java_HelloWorld_print ,其中
  是实现HelloWorld.print方法的C函数:

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

 JNIEXPORT void JNICALL   Java_HelloWorld_print (JNIEnv *, jobject);


  
  

忽略 JNIEXPORT JNICALL 宏现在。您可能已经注意到
  该本地方法的C实现接受两个参数
  即使本地方法的相应的申报受理
  没有参数​​。每一个本地方法的第一个参数
  实现是一个的JNIEnv 接口指针。第二个参数是一个
  参照的HelloWorld 对象本身(有点像这个
  在C ++中指针)。我们将讨论如何使用的JNIEnv 接口
  指针和 jobject 本书后面的论点,但这种简单的
  例如忽略这两个参数。

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

2.5编写本地方法实现

2.5 Write the Native Method Implementation

JAVAH 生成JNI风格的头文件可以帮助你编写C或
  C ++实现的本地方法。你写的函数
  必须按照生成的头文件中指定的-prototype。您
  可以实现在一个C文件 HelloWorld.c HELLO-World.print 方法
  如下:

The JNI-style header file generated by javah helps you to write C or C++ implementations for the native method. The function that you write must follow the -prototype specified in the generated header file. You can implement the Hello-World.print method in a C file 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;  } 

本机方法的实现很简单。它使用printf函数来显示字符串Hello World!然后返回。正如前面提到的,这两个参数,的JNIEnv 指针和参考的对象,将被忽略。

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

C程序包含三个头文件:

The C program includes three header files:

jni.h - 这个头文件提供的信息本地code需求
  调用JNI函数。当写本地方法,必须始终
  包括在C或C ++源文件,这个文件。
   stdio.h中 - 在code
  上面的代码段还包括 stdio.h中,因为它使用了的printf
  功能。
   HelloWorld.h - 你生成使用头文件
   JAVAH 。它包括C / C ++原型为 Java_HelloWorld_print
  功能。
  2.6编译C源代码,并创建一个本地库

jni.h -- This header file provides information the native code needs to call JNI functions. When writing native methods, you must always include this file in your C or C++ source files. stdio.h -- The code snippet above also includes stdio.h because it uses the printf function. HelloWorld.h -- The header file that you generated using javah. It includes the C/C++ prototype for the Java_HelloWorld_print function. 2.6 Compile the C Source and Create a Native Library

请记住,当你在创建的HelloWorld
   HelloWorld.java 文件,你提供一个线code那加载本地
  库到程序:

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

 System.loadLibrary("HelloWorld");   

现在所有必要的C $ C $Ç
  写的是你需要编译 HELLO-World.c ,并建立此本机
  库。

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

不同的操作系统支持不同的方式来构建本地
  库。在Solaris上,下面的命令建立一个共享库
  所谓libHello-World.so:

Different operating systems support different ways to build native libraries. On Solaris, the following command builds a shared library called libHello-World.so:

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


  
  

-G选项指示C编译器生成一个共享库,而不是一个普通的Solaris
  可执行文件。由于页面宽度在这本书的限制,
  我们打​​破在命令行中为两行。您需要键入命令
  在一个单一的线,或在一个脚本文件放置命令。在的Win32 中,
  下面的命令生成一个动态链接库(DLL) HelloWorld.dll
  使用Microsoft Visual C ++编译:

The -G option instructs the C compiler to generate a shared library instead of a regular Solaris executable file. Because of the limitation of page width in this book, we break the command line into two lines. You need to type the command in a single line, or place the command in a script file. On Win32, the following command builds a dynamic link library (DLL) HelloWorld.dll using the Microsoft Visual C++ compiler:

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

-MD 选项确保 HelloWorld.dll Win32的<链接/ code>多线程C库。
  在 -LD 选项指示C编译器生成一个DLL而不是
  定期Win32可执行程序。当然,在Solaris和Win32你
  需要把反映你自己设置的include路径
  机器。

The -MD option ensures that HelloWorld.dll is linked with the Win32 multithreaded C library. The -LD option instructs the C compiler to generate a DLL instead of a regular Win32 executable. Of course, on both Solaris and Win32 you need to put in the include paths that reflect the setup on your own machine.

2.7运行程序

在这一点上,你必须准备好运行程序的两个组成部分。
  类文件(的HelloWorld.class )调用本地方法,而
  本机库( HELLO-World.dll ),实现本机的方法。

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

由于该的HelloWorld 类包含自己的主要方法,你可以运行
  在Solaris或Win32的程序如下:

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

 java HelloWorld

您应该看到以下的输出:

You should see the following output:

   Hello World! 


  
  

设置你的本地库路径是非常重要的
  正确地为你的程序运行。本机库路径是一个列表
  目录在加载时Java虚拟机的搜索
  本机库。如果您没有本地库路径设置
  正确的话,那么你会看到类似以下内容的错误:

It is important to set your native library path correctly for your program to run. The native library path is a list of directories that the Java virtual machine searches when loading native libraries. If you do not have a native library path set up correctly, then you 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) 

请确保本地库驻留在本地库路径的目录之一。
  如果你是在Solaris系统上运行时, LD_LIBRARY_PATH
  环境变量用来定义本地库路径。使
  确保它包括包含的目录的名称
   libHelloWorld.so 文件。如果 libHelloWorld.so 文件是在当前
  目录,你可以发出在标准以下两个命令
  外壳(SH)或KornShell(KSH)成立 LD_LIBRARY_PATH
  环境变量正确的:

Make sure that the native library resides in one of the directories in the native library path. If you are running on a Solaris system, the LD_LIBRARY_PATH environment variable is used to define the native library path. Make sure that it includes the name of the directory that contains the libHelloWorld.so file. If the libHelloWorld.so file is in the current directory, you can issue the following two commands in the standard shell (sh) or KornShell (ksh) to set up the LD_LIBRARY_PATH environment variable properly:

 LD_LIBRARY_PATH=.
 export LD_LIBRARY_PATH


  
  

等效命令
  的是C shell(csh或tcsh)如下:

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

 setenv LD_LIBRARY_PATH .

如果您是在Windows 95或运行
  在Windows NT机器,确保 HelloWorld.dll 在当前
  目录,或者在目录在PATH环境上市
  变量。

If you are running on a Windows 95 or Windows NT machine, make sure that HelloWorld.dll is in the current directory, or in a directory that is listed in the PATH environment variable.

在Java 2 SDK 1.2版本中,你也可以指定本机库
  在java命令行的系统属性的路径如下:

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

 java -Djava.library.path=. HelloWorld


  
  

-D 命令行选项
  设置一个Java平台的系统属性。设置的java.library.path
  属性为指示Java虚拟机搜索
  本机库在当前目录。

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

这篇关于从Java调用C函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆