我想使用JNI从Java调用C函数。在C函数中,我想创建一个JVM并调用一些Java对象。当我尝试创建JVM时,JNI_CreateJavaVM返回-1。
所以,我想知道是否可以这样做。编译C代码以创建.so文件(在linux中),Java代码调用.so文件中的函数。
任何使用Java-> C-> Java的例子都很有用。
感谢。
答案 0 :(得分:2)
不,不幸的是,这是不可能的。每个进程只能有一个JVM,并且您已经处于JVM进程中。
答案 1 :(得分:2)
我无法看到Java中的重点 - > C - > Java。
如果可以从Java调用C,那么可以在C函数返回后从Java调用Java。
Excelsion xFunction是一个简单可靠的库,用于从Java调用C语言。它处理奇怪的JNI内容,为您提供更简单的界面。
答案 2 :(得分:2)
为什么需要创建第二个JVM?您无法创建第二个JVM,但可以从C代码访问Java类。请参阅Accessing Java Objects。
答案 3 :(得分:1)
我不明白为什么有些人认为这无用。实际上,Java - > C - >进入Android游戏编程时,Java场景很常见:
有必要使用SDK (Java)的原因是大多数Android API仅以Java提供! NDK (C / C++)仅提供了一个纤薄的Linux环境(将其视为“标准C库”+“标准C ++库”+“Linux系统库的缩减版”)。例如,如果要将应用程序与AdMob (Google Ads)或In-app Billing (Google Payment)集成,或者如果要访问设备的内置摄像头,则必须从游戏逻辑中调用Java方法(写的是C / C ++!)。
编写Java类。声明一个方法native
:
$ ls -F1
classes/
jni/
src/
$ nano src/com/example/jcj/Test.java
Test.java:
package com.example.jcj;
public class Test {
public static void main(String[] args) {
doSomethingInC();
}
public static native void doSomethingInC();
public static void doSomethingInJava() {
System.out.println("Done something in Java!");
}
static {
System.loadLibrary("hello_jcj");
}
}
调用“Java编译器”(javac
),然后调用“C头和存根文件生成器”(javah
):
$ javac -sourcepath src -d classes src/com/example/jcj/Test.java
$ javah -classpath classes -d jni com.example.jcj.Test
$ ls -F1 jni/
com_example_jcj_Test.h
实施C部分:
$ nano jni/com_example_jcj_Test.c
com_example_jcj_Test.c:
#include "com_example_jcj_Test.h"
#include <stdio.h>
/*
* Class: com_example_jcj_Test
* Method: doSomethingInC
* Signature: ()V
*/
JNIEXPORT void JNICALL
Java_com_example_jcj_Test_doSomethingInC(JNIEnv* env, jclass clazz)
{
printf("Done something in C!\n");
}
编译C源代码(Windows):
> REM TODO: Add this!
编译C源代码(Linux):
$ gcc -I{JAVA_HOME}/include
-shared \
-o libhello_jcj.so \
jni/com_example_jcj_Test.c
$ ls -F1
classes/
jni/
libhello_jcj.so*
src/
编译C源代码(Mac OS X):
$ gcc -I${JAVA_HOME}/include \
-shared \
-o libhello_jcj.jnilib \
jni/com_example_jcj_Test.c
$ ls -F1
classes/
jni/
libhello_jcj.jnilib*
src/
运行Java应用程序:
$ java -classpath classes com.example.jcj.Test
Done something in C!
由于您使用Java(而不是C / C ++)启动了程序,因此已经创建了一个JVM。您不需要在第二部分(C - > Java部分)中创建另一部分,您只需要重用已创建的部分。有两种方法可以做到:
JNIEnv*
)JavaVM*
JNI_OnLoad()
)
醇>
(答案尚未完成,我稍后会完成。如果您喜欢,请投票给我鼓励。谢谢!)
参考文献: