我将Java嵌入到C++应用程序中。作为此过程的一部分,我需要向Java公开 native 函数,以及从C++调用Java函数。

我是否需要将要从Java调用的函数放入共享库中?还是可以以某种方式将它们编译到主机应用程序中?

到目前为止,这是我尝试过的方法,但是它给出了java.lang.UnsatisfiedLinkError

汇编

我正在使用以下操作系统在OS X 10.5上构建

g++ -Wall -I/System/Library/Frameworks/JavaVM.framework/Headers/ -framework JavaVM -g test.cpp

Java测试文件:TestObject.java
// To build this you need to do a `javac TestObject.java`
// To get the signatures do a `javap -d TestObject`
// To generate the .h file do a `javah TestObject`
public class TestObject
{
    public native TestObject get_property( String k );
}

C++测试文件:test.cpp
#include <jni.h>
#include <assert.h>


JNIEXPORT jobject JNICALL Java_TestObject_get_1property(JNIEnv * jni_env, jobject obj, jstring key)
{
  //Just a stub implementation for now.
  jclass klass = jni_env->GetObjectClass( obj );
  jmethodID constructor = jni_env->GetMethodID( klass, "<init>", "()V");
  jobject retval = jni_env->NewObject(klass, constructor );

  return retval;
}




int main()
{
  JavaVM* jvm;
  JavaVMInitArgs vm_args;
  JavaVMOption options[1];

  vm_args.version = JNI_VERSION_1_4;
  vm_args.nOptions = 1;
  options[0].optionString = "-Djava.class.path=.";
  vm_args.options = options;
  vm_args.ignoreUnrecognized = JNI_FALSE;

  JNIEnv * env;
  JNI_CreateJavaVM(&jvm, (void **)&env, &vm_args);

  jclass klass = (env)->FindClass("TestObject");
  assert( klass );

  jmethodID constructor = env->GetMethodID( klass, "<init>", "()V");
  assert( constructor );

  jobject obj = env->NewObject(klass, constructor );

  jmethodID test_method = (env)->GetMethodID( klass, "get_property", "(Ljava/lang/String;)LTestObject;" );
  assert( test_method );

  jvalue args[1];
  args[0].l = env->NewStringUTF("k");

  jobject rv = env->CallObjectMethodA(obj, test_method, args );

  jthrowable exc = env->ExceptionOccurred();
  if(exc)
  {
    env->ExceptionDescribe();
    env->ExceptionClear();
  }

  //TODO: do something with rv

}

最佳答案

通常,JVM希望在已通过System#loadSystem#loadLibrary加载的共享库中找到 native 方法定义,并且在大多数情况下,这是最方便的方法。但是,对于像您这样的情况,确实存在替代方法,在这种情况下,您希望将实现直接包含在可执行文件中。

如果调用 JNIEnv::RegisterNatives ,则可以向JVM传递与特定类中的 native 方法相对应的函数指针列表。当某些Java代码调用这些方法之一时,JVM将知道调用传递给RegisterNatives的函数指针,而不是通过动态加载的库进行搜索。

JNINativeMethod methods[] = {
    {
        "frobFabulously",
        "(Ljava/lang/Object;)V",
        reinterpret_cast<void*>(NativeFrobFabulouslyImpl)
    },
};

env->RegisterNatives(clazz, methods, sizeof(methods)/sizeof(JNINativeMethod));

关于java - 从C++应用程序从Java调用C++时,如何避免UnsatisfiedLinkError?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6893493/

10-11 19:31
查看更多