2009-06-14 15 views

回答

34

是的,你可以,但它有點複雜,並且以反射/非類型安全的方式工作(例子使用C++ api,它比C版本更清潔)。在這種情況下,它會在C代碼中創建Java VM的實例。如果你的母語稱作是首先被從Java叫那麼就沒有必要建立一個虛擬機實例

#include<jni.h> 
#include<stdio.h> 

int main(int argc, char** argv) { 

    JavaVM *vm; 
    JNIEnv *env; 
    JavaVMInitArgs vm_args; 
    vm_args.version = JNI_VERSION_1_2; 
    vm_args.nOptions = 0; 
    vm_args.ignoreUnrecognized = 1; 

    // Construct a VM 
    jint res = JNI_CreateJavaVM(&vm, (void **)&env, &vm_args); 

    // Construct a String 
    jstring jstr = env->NewStringUTF("Hello World"); 

    // First get the class that contains the method you need to call 
    jclass clazz = env->FindClass("java/lang/String"); 

    // Get the method that you want to call 
    jmethodID to_lower = env->GetMethodID(clazz, "toLowerCase", 
             "()Ljava/lang/String;"); 
    // Call the method on the object 
    jobject result = env->CallObjectMethod(jstr, to_lower); 

    // Get a C-style string 
    const char* str = env->GetStringUTFChars((jstring) result, NULL); 

    printf("%s\n", str); 

    // Clean up 
    env->ReleaseStringUTFChars(jstr, str); 

    // Shutdown the VM. 
    vm->DestroyJavaVM(); 
} 

編譯(在Ubuntu):

g++ -I/usr/lib/jvm/java-6-sun/include \ 
    -I/usr/lib/jvm/java-6-sun/include/linux \ 
    -L/usr/lib/jvm/java-6-sun/jre/lib/i386/server/ -ljvm jnitest.cc 

注意:從每個返回碼應該檢查這些方法以便實現正確的錯誤處理(爲了方便,我忽略了這一點)。例如。

str = env->GetStringUTFChars(jstr, NULL); 
if (str == NULL) { 
    return; /* out of memory */ 
} 
9

是的,但你必須通過JNI來做到這一點:http://java.sun.com/javase/6/docs/technotes/guides/jni/index.html

+0

我見過JNI用來從Java調用C++。不知道它以另一種方式工作。 – Kieveli 2009-06-14 13:35:04

+3

奇怪的是,我一直認爲它更常用於提供從Java訪問C++庫,但它有兩種方式。例如, – 2009-06-14 13:38:51

3

方法有很多種。 Here是一些想法。另外,商業Java-COM橋允許從C++到java的COM通信(如果您使用的是Windows)。你也應該看看CNI

2

是的,你可以調用從C Java函數++或C,但除非你使用像COM或CORBA(或其他第三方工具,我可能不知道的),你會必須在JNI的背景下做到這一點。

從本機代碼調用Java方法的整個過程在Sun的JNI指南pdf中的第4.2節中稱爲「調用方法」的第4章中描述,您可以在其中找到here

2

看一下invocation API。這使您可以從您的本機應用程序中加載和啓動JVM,然後從應用程序調用其中的方法。

簡言之(從鏈接文檔)

/* load and initialize a Java VM, return a JNI interface 
* pointer in env */ 
JNI_CreateJavaVM(&jvm, &env, &vm_args); 

/* invoke the Main.test method using the JNI */ 
jclass cls = env->FindClass("Main"); 
jmethodID mid = env->GetStaticMethodID(cls, "test", "(I)V"); 
env->CallStaticVoidMethod(cls, mid, 100); 
1

以下功能允許您創建虛擬機。

JNIEnv* create_vm(JavaVM ** jvm) 
{ 
    JNIEnv *env; 
    JavaVMInitArgs vm_args; 
    JavaVMOption options[2]; 

    options[0].optionString = "-Djava.class.path=."; 
    options[1].optionString = "-DXcheck:jni:pedantic"; 

    vm_args.version = JNI_VERSION_1_6; 
    vm_args.nOptions = 2; 
    vm_args.options = options; 
    vm_args.ignoreUnrecognized = JNI_TRUE; // remove unrecognized options 

    int ret = JNI_CreateJavaVM(jvm, (void**) &env, &vm_args); 
    if (ret < 0) printf("\n<<<<< Unable to Launch JVM >>>>>\n"); 
    return env; 
} 

編譯着名的Hello World程序。以下函數嘗試調用HelloWorld程序的主要方法。

int main(int argc, char* argv[]) 
{ 
    JNIEnv* env; 
    JavaVM* jvm; 

    env = create_vm(&jvm); 

    if (env == NULL) return 1; 

    jclass myClass = NULL; 
    jmethodID main = NULL; 


    myClass = env->FindClass("HelloWorld"); 


    if (myClass != NULL) 
     main = env->GetStaticMethodID(myClass, "main", "([Ljava/lang/String;)V"); 
    else 
     printf("Unable to find the requested class\n"); 


    if (main != NULL) 
    { 
     env->CallStaticVoidMethod(myClass, main, " "); 

    }else printf("main method not found") ; 


    jvm->DestroyJavaVM(); 
    return 0; 
} 

現在把create_vm函數和main函數放到一個cpp文件中,包含jni.h並編譯它。我在窗戶上使用了MinGW。

g++ -D_JNI_IMPLEMENTATION_ -I"C:\Program Files\Java\jdk1.6.0_32\include" -I"C:\Program Files\Java\jdk1.6.0_32\include\win32" hello.cpp -L"C:\Program Files\Java\jre6\bin\client" -ljvm -o hello.exe 

Exection 現在,如果你運行exe文件創建,你會得到一個錯誤。 jvm.dll not found。 將C:\Program Files\Java\jre6\bin\client放入您的PATH環境變量中。現在你可以運行這個exe文件 。

注意:不要取代jvm.dll文件。

0

編碼上面的例子後,你需要對你的項目做一些配置。

步驟來jvm.lib在Visual Studio中鏈接到您的項目:

  • 右鍵單擊項目 - >屬性。
  • 在屬性對話框中,在鏈接器 - >輸入 - >附加依賴關係區域添加jvm.lib。
  • 最後寫jvm.lib路徑(如 「C:\ Program Files文件\的Java \ jdk1.7.0_60 \ LIB」)下 連接器 - >常規 - > AdditionalLibraryDirectories

完成這些步驟之後,你的項目能鏈接到jvm並且運行良好。

相關問題