2011-09-24 9 views
16

से मैं उदाहरण निम्नलिखित C++ से जावा वर्चुअल मशीन को लागू करने की कोशिश कर रहा हूँ पाया here:आह्वान जावा सी ++

मूल रूप से मैं एक छोटा सा जावा प्रोग्राम है:

public class TestJNIInvoke 
{ 
    public static void main(String[] args) 
    { 
    System.out.println(args[0]); 
    } 
} 

तो मैं एक सी है ++ प्रोग्राम है जो मैं एक JVM बना सकते हैं और TestJNIInvoke वर्ग कॉल करना चाहते हैं:

#include <jni.h> 
#include <cstdlib> 
#define PATH_SEPARATOR ';' /* define it to be ':' on Solaris */ 
#define USER_CLASSPATH "." /* where Prog.class is */ 

using namespace std; 

int main() { 
    JNIEnv *env; 
    JavaVM *jvm; 
    jint res; 
    jclass cls; 
    jmethodID mid; 
    jstring jstr; 
    jclass stringClass; 
    jobjectArray args; 

#ifdef JNI_VERSION_1_2 
    JavaVMInitArgs vm_args; 
    JavaVMOption options[1]; 
    options[0].optionString = 
     "-Djava.class.path=" USER_CLASSPATH; 
    vm_args.version = 0x00010002; 
    vm_args.options = options; 
    vm_args.nOptions = 1; 
    vm_args.ignoreUnrecognized = JNI_TRUE; 
    /* Create the Java VM */ 
    res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args); 
#else 
    JDK1_1InitArgs vm_args; 
    char classpath[1024]; 
    vm_args.version = 0x00010001; 
    JNI_GetDefaultJavaVMInitArgs(&vm_args); 
    /* Append USER_CLASSPATH to the default system class path */ 
    sprintf(classpath, "%s%c%s", 
      vm_args.classpath, PATH_SEPARATOR, USER_CLASSPATH); 
    vm_args.classpath = classpath; 
    /* Create the Java VM */ 
    res = JNI_CreateJavaVM(&jvm, &env, &vm_args); 
#endif /* JNI_VERSION_1_2 */ 

    if (res < 0) { 
     fprintf(stderr, "Can't create Java VM\n"); 
     exit(1); 
    } 
    cls = (*env)->FindClass(env, "TestJNIInvoke"); 
    if (cls == NULL) { 
     goto destroy; 
    } 

    mid = (*env)->GetStaticMethodID(env, cls, "main", 
            "([Ljava/lang/String;)V"); 
    if (mid == NULL) { 
     goto destroy; 
    } 
    jstr = (*env)->NewStringUTF(env, " from CPP!"); 
    if (jstr == NULL) { 
     goto destroy; 
    } 
    stringClass = (*env)->FindClass(env, "java/lang/String"); 
    args = (*env)->NewObjectArray(env, 1, stringClass, jstr); 
    if (args == NULL) { 
     goto destroy; 
    } 
    (*env)->CallStaticVoidMethod(env, cls, mid, args); 

destroy: 
    if ((*env)->ExceptionOccurred(env)) { 
     (*env)->ExceptionDescribe(env); 
    } 
    (*jvm)->DestroyJavaVM(jvm); 
} 

लेकिन जब मैं सी ++ प्रोग्राम को संकलित करने की कोशिश मैं इस त्रुटि मिलती है:

c:\java\JNI> g++ -I"c:\Program Files\Java\jdk1.7.0\include"-I"c:\ProgramFiles\Java\jdk1.7.0\include\win32" -c TestJNIInvoke.cpp 


TestJNIInvoke.cpp: In function 'int main()': 
TestJNIInvoke.cpp:20:31: warning: deprecated conversion from string constant to 
'char*' 
TestJNIInvoke.cpp:44:18: error: base operand of '->' has non-pointer type 'JNIEn 
v' 
TestJNIInvoke.cpp:49:18: error: base operand of '->' has non-pointer type 'JNIEn 
v' 
TestJNIInvoke.cpp:54:19: error: base operand of '->' has non-pointer type 'JNIEn 
v' 
TestJNIInvoke.cpp:58:26: error: base operand of '->' has non-pointer type 'JNIEn 
v' 
TestJNIInvoke.cpp:59:19: error: base operand of '->' has non-pointer type 'JNIEn 
v' 
TestJNIInvoke.cpp:63:12: error: base operand of '->' has non-pointer type 'JNIEn 
v' 
TestJNIInvoke.cpp:66:16: error: base operand of '->' has non-pointer type 'JNIEn 
v' 
TestJNIInvoke.cpp:67:16: error: base operand of '->' has non-pointer type 'JNIEn 
v' 
TestJNIInvoke.cpp:69:12: error: base operand of '->' has non-pointer type 'JavaVM' 

कोई विचार?

धन्यवाद

+0

आपको इस बारे में एक टिप्पणी शामिल करनी चाहिए कि आपके कोड के साथ क्या काम नहीं कर रहा है। क्या आपको कोई त्रुटि मिलती है या क्या यह अभी काम नहीं करती है? –

+0

मुझे सी ++ से जावा का आविष्कार करने के बारे में कुछ भी पता नहीं है, लेकिन आपने 'env' को पॉइंटर (' जेएनआईएनएनवी * एनवी') के रूप में घोषित किया है, इसलिए निश्चित रूप से जब आप '(* env) -> कुछ भी करते हैं तो यह शिकायत करेगा क्योंकि' * env' एक सूचक नहीं है। 'Env-> कुछ भी' का प्रयास करें। – dantswain

+0

या वैकल्पिक रूप से: तीर ('->') के बजाय बिंदु ('.') ऑपरेटर का उपयोग करें। JVM ऑब्जेक्ट के साथ भी यही समस्या होती है: '(* jvm)'। इसके अतिरिक्त कहीं एक स्ट्रिंग अक्षरशः * अंतर्निहित * 'char * 'पर कास्ट किया गया है, इसलिए आप इसके बजाय _explicit_ को डालना चाहते हैं। (यह चेतावनी से छुटकारा पा जाएगा)। – user268396

उत्तर

38

भले ही आप एक ही हेडर फ़ाइल शामिल करते हैं, जावा नेटिव इंटरफेस सी और सी ++ के लिए दो अलग-अलग इंटरफेस का उपयोग करता है।

सी ++ में, यह है:

jclass cls = env->FindClass("java/lang/String"); 
(सी के लिए) के बजाय

:

jclass cls = (*env)->FindClass(env, "java/lang/String"); 

तो सी समारोह कॉल है कि दो में env स्थानों की आवश्यकता है सी में एक सुविधाजनक सदस्य समारोह कॉल हो जाता है ++।

यह Java Native Interface 6.0 Specification के Native Method Arguments अनुभाग में उल्लिखित है।

+0

आपको बहुत बहुत धन्यवाद, मुझे नहीं पता था कि विभिन्न इंटरफेस थे। इससे मेरा जीवन बहुत आसान हो जाएगा। :) –

1

मेरा अनुमान होगा कि आप कमांड लाइन का उपयोग कर रहे दिए गए Win32 हेडर के खिलाफ संकलित करने के लिए प्रयास कर रहे हैं। क्या आपने इसके बजाय -I"c:\ProgramFiles\Java\jdk1.7.0\include\solaris की कोशिश की है (मान लीजिए कि यह स्रोत में उच्च टिप्पणी के आधार पर आपका मंच है)।

+0

यह हेडर का मुद्दा नहीं है, यह गलत वाक्यविन्यास का मुद्दा है। पॉइंटर (->) के माध्यम से ऑब्जेक्ट्स/ऑब्जेक्ट्स के तरीकों तक पहुंचने के लिए सिंटेक्स का उपयोग किया जाता है जहां पॉइंटर डीरफ्रेंसिंग (* एनवी) के माध्यम से मूल्य प्रदान किए जाते हैं। – user268396

+0

आह, क्षमा करें, सहमत हुए। मैंने स्क्रॉलबार को नहीं देखा और स्निपेट के शीर्ष पर केवल कोड को देखा जिसमें किसी भी समस्या कोड शामिल नहीं था। –

संबंधित मुद्दे