一. C++的代码调用
如果我们想要从Java中调用C++方法,首先需要完成的工作是将C++代码转换为可执行二进制文件或动态链接库(DLL)。
C++代码示例:
#includeusing namespace std; extern "C" { int add(int a, int b) { return a + b; } } int main() { int a = 5, b = 3; cout << add(a, b) << endl; return 0; }
在C++代码中,我们必须使用 "extern" 关键字指定导出函数的名称和参数。 在这个例子中,我们导出了一个名为 "add" 的函数。
为了编译C++代码,我们需要使用以下命令:
g++ –std=c++11 –shared –fPIC add.cpp –o libadd.so
在编译过程中,我们使用了“-shared”和“-fPIC”选项,从而使编译器生成动态链接库“libadd.so”文件。此外,我们还需要使用“-std=c++11”指定C++版本。
在Java中我们使用以下代码调用C++代码:
public class CallCpp { static { System.loadLibrary("add"); } public static void main(String[] args) { int a = 5, b = 3; int result = add(a, b); System.out.println(result); } public static native int add(int a, int b); }
在Java中,我们需要使用“System.loadLibrary()”方法来加载C++生成的动态链接库,并且需要添加“native”关键字指定调用的方法是一个本地方法。以上示例中,我们已经成功的从Java中调用了C++代码。
二. 使用JNI调用C++
在上一篇中,我们已经演示了通过外部函数用Java直接调用C++方法的方法。事实上,Java也提供了JNI接口来使Java代码与C++代码进行交互,使用JNI,Java代码可以直接调用C++中的函数。
首先,我们需要生成一个名为“add”和两个参数作为整数的C++函数,如前一示例中的“add”函数一样。 然后,我们可以在Java中使用JNI调用C++方法。
C++代码:
#include#include using namespace std; extern "C" { JNIEXPORT jint JNICALL Java_CallCpp_add(JNIEnv *env, jobject jobj, jint a, jint b) { int result = a + b; return result; } } int main() { return 0; }
在这个代码中,我们通过JNI定义了一个名为“Java_CallCpp_add”的函数作为Java代码与C++代码之间的桥梁。代码中的“env”变量指向当前虚拟机实例,而“jobj”变量指向调用方法的对象。除此之外,其他参数与我们在上面示例中一样。 使用JNI,我们可以动态地加载C++库,并在Java程序中定义C++函数。
下面是一个Java示例:
public class CallCpp { static { System.loadLibrary("add"); } public static void main(String[] args) { int a = 5, b = 3; int result = add(a, b); System.out.println(result); } public static native int add(int a, int b); }
在这个Java代码中,我们使用“native”关键字来定义一个Java方法(上面已经描述过这个概念),该方法将调用C++方法。 接下来,我们可以编译并运行Java代码以查看结果。
三、使用JNA调用C++函数
JNA是Java的一种框架,它允许Java应用程序动态的从预编译共享库中调用C函数。
下面是一个直接使用JNA调用C++方法的Java示例:
import com.sun.jna.Library; import com.sun.jna.Native; import com.sun.jna.Platform; public class CallCpp { public interface AddLibrary extends Library { AddLibrary INSTANCE = (AddLibrary) Native.load((Platform.isWindows() ? "add" : "libadd"), AddLibrary.class); int add(int a, int b); } public static void main(String[] args) { int result = AddLibrary.INSTANCE.add(5, 3); System.out.println(result); } }
JNA摒弃使用JNI的方式,而是直接使用Java接口来调用C/C++函数。 我们创建了一个Java接口,并使用“Native.load()”方法动态加载C/C++的共享库。 在上面的代码中,我们已经成功的从Java中调用了C++代码。
四、C++中调用Java方法
在上面的示例中,我们演示了如何从Java中调用C++方法,现在我们来看一下如何在C++中调用Java方法。
首先,我们需要使用Java Native Interface(JNI)来实现从C++中调用Java方法。 下面是一个演示示例:
C++代码:
#include#include #include using namespace std; int main() { JavaVM *jvm; JNIEnv *env; JavaVMInitArgs vm_args; JavaVMOption options[1]; options[0].optionString = "-Djava.class.path=."; // 设置类路径,需要根据实际情况更改 vm_args.version = JNI_VERSION_1_6; vm_args.nOptions = 1; vm_args.options = options; vm_args.ignoreUnrecognized = false; jint rc = JNI_CreateJavaVM(&jvm, (void **) &env, &vm_args); if (rc != JNI_OK) { cerr << "Failed to create JVM" << endl; return 1; } jclass jcls = env->FindClass("CallJava"); if (jcls == nullptr) { cerr << "Failed to find CallJava class" << endl; return 1; } jmethodID mid = env->GetStaticMethodID(jcls, "print", "()V"); if (mid == nullptr) { cerr << "Failed to find static method print" << endl; return 1; } env->CallStaticVoidMethod(jcls, mid); jvm->DestroyJavaVM(); return 0; }
在这个示例代码的使用中,我们将使用JNI创建一个JVM并加载Java类“CallJava”,该类具有一个静态方法“print()”。 在C++代码中,我们可以使用JNI查找Java类,然后检索静态方法ID并调用静态Java方法。
下面是Java代码示例:
public class CallJava { public static void print() { System.out.println("Hello from Java!"); } public static void main(String[] args) { // do nothing } }
这个Java程序中,我们仅仅提供了一个“print()”静态方法,其中打印了一条简单的消息。 使用C++调用Java方法时,我们传递了一个名为“CallJava”的Java类的名称,因此需要确保Java类文件可用。
五、结论
Java和C++作为不同的编程语言,在不同的使用场景下都有各自的优势。通过调用C++方法,可以为Java应用程序提供更高的性能和更好的可扩展性。在本文中,我们介绍了Java如何调用C++函数以及C++如何调用Java方法的方法,并演示了每个简单的示例。通过这些方法,您可以更好地实现Java和C++之间的交互并提升应用程序的整体性能。