在JAVA中从框架调用C代码
我对java编程非常陌生,因此,如果这听起来像一个愚蠢的问题,我会提前道歉 我使用JNI通过创建Swing JFrame并显示它来调用C代码。代码相当简单,如果我将框架可见性设置为false(即调用“hello”方法),Java代码工作正常,而当我将框架可见性设置为true时,什么都不会发生(即不调用“hello”方法) Test.java在JAVA中从框架调用C代码,java,swing,java-native-interface,Java,Swing,Java Native Interface,我对java编程非常陌生,因此,如果这听起来像一个愚蠢的问题,我会提前道歉 我使用JNI通过创建Swing JFrame并显示它来调用C代码。代码相当简单,如果我将框架可见性设置为false(即调用“hello”方法),Java代码工作正常,而当我将框架可见性设置为true时,什么都不会发生(即不调用“hello”方法) Test.java public class Test extends JFrame { private JPanel contentPane; public
public class Test extends JFrame {
private JPanel contentPane;
public static Container root;
/**
* Launch the application.
*/
public static void main(String[] args) {
try {
Test frame = new Test();
new JNIServer().hello("world"); // where hello is native method
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
}
JNIServer.java
public class JNIServer{
public native void hello(String name);
static {
System.out.println("Inload library");
System.loadLibrary("JNI_Lib");
}
}
如前所述,您可以尝试使用单独的线程。我还会尝试添加一些println语句,以查明问题的原因
为了重现您的问题,我在Ubuntu 14.04 64位上测试了Java SE 1.8.0_66-b17(Java-version)和gcc(Ubuntu 4.8.4-2ubuntu1~14.04)4.8.4(gcc-version)
为了简化一些,我没有将String
参数传递给hello
方法/函数,暂时跳过该转换。以下是我用来测试的源文件:
// Test.java
import java.awt.Container;
import javax.swing.*;
public class Test extends JFrame {
private JPanel contentPane;
public static Container root;
/**
* Launch the application.
*/
public static void main(String[] args) {
try {
Test frame = new Test();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.callNativeFunction();
System.out.println("Test.main - before setting frame visible");
frame.setVisible(true);
System.out.println("Test.main - after setting frame visible");
} catch (Exception e) {
e.printStackTrace();
}
}
private void callNativeFunction() {
Thread nativeFunctionThread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Test.run - before calling hello.");
new JNIServer().hello(); // where hello is native method
System.out.println("Test.run - after calling hello.");
}
});
nativeFunctionThread.start();
}
}
// JNIServer.java
public class JNIServer {
public native void hello();
static {
System.out.println("Inload library");
System.loadLibrary("JNI_Lib");
}
}
// JNIServer.h (generated)
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class JNIServer */
#ifndef _Included_JNIServer
#define _Included_JNIServer
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: JNIServer
* Method: hello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_JNIServer_hello
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
// JNI_Lib.c
#include <jni.h>
#include <stdio.h>
JNIEXPORT void JNICALL Java_JNIServer_hello(JNIEnv * environment,
jobject java_object) {
printf("Hello from C!\n");
}
这是java-Djava.library.path=的输出。测试
命令:
Test.main - before setting frame visible
Test.run - before calling hello.
Inload library
Hello from C!
Test.run - after calling hello.
Test.main - after setting frame visible
备受期待的“来自C的你好!”被打印出来了。可以看到一个(非常小的)框架。(可以使用JFrame.setBounds
方法调整框架的大小和位置。)
编辑:使用Eclipse
虽然应该可以有一个组合的,但我建议从一个较小的步骤开始:使用两个单独的Eclipse项目(或者甚至更小:创建一个Java项目,该项目引用您的CLI C项目创建的库)。如果这是可行的,您可以在一个组合的Eclipse项目上工作
上面的CLI示例的java.library.path
指向包含libJNI_Lib.so文件的目录。对于Eclipse中的Java项目,您可以选择运行|运行配置。。。菜单,如有必要,在左侧面板中选择Java项目,在右侧面板中选择Arguments选项卡,并在VM参数中添加“-Djava.library.path=。”(不带引号)。例如,请参见“运行配置”对话框的屏幕截图:
这是您的完整计划吗?JNI_Lib看起来像什么?请注意,在实际的程序中,您应该更加注意线程,确保Swing代码在Swing事件线程上启动,并且本机代码在其自己的线程中运行。我没有发布C代码,否则就是这样。这不是一个完整的程序,也不是一个完整的问题。@Alex。。我没有发布C文件,因为我试图在其中打印一些消息,以确保我能够从中访问C代码java@Freek.. 本教程与我的问题无关。我重复我的问题:我想使用GUI从Java到JNI访问C代码。您使用哪个版本的Java JDK和哪个C编译器?你在什么操作系统上运行?我使用JDK1.8、gcc编译器和ubuntu作为操作系统。我也在linuxmint上试用过。关闭Swing应用程序的建议:调用
frame.setDefaultCloseOperation(JFrame.EXIT_on_CLOSE)代码>创建帧后。这将确保在关闭框架时关闭程序。谢谢您的建议。这对我很有帮助,因为当我合上相框时,“Hello from C”消息被打印出来了。但我的座右铭没有实现。我也尝试过你建议的代码,但仍然面临同样的问题。我没有得到和你一样的结果。“来自C的Hello没有同时打印”您能将您的输出添加到问题中吗?对我来说,“Hello from C!”消息是在框架可见之前(以及在我关闭框架之前)打印的。
Test.main - before setting frame visible
Test.run - before calling hello.
Inload library
Hello from C!
Test.run - after calling hello.
Test.main - after setting frame visible