2011-01-30 12 views
12

के बीच int [] s भेज रहा है मेरे पास एंड्रॉइड में कुछ छवि प्रोसेसिंग जावा कोड है जो दो बड़े int arrays पर कार्य करता है। ज्यादातर समय, जावा पर्याप्त तेज़ है लेकिन मुझे कुछ ऑपरेशन तेज करने के लिए जेएनआई और एनडीके के माध्यम से सी का उपयोग करने की आवश्यकता है।जावा और सी

एकमात्र तरीका मुझे पता है कि मैं int arrays से डेटा को पास कर सकता हूं, एक नया बफर बनाने के लिए ByteBuffer.allocateDirect का उपयोग करना है, उस पर डेटा कॉपी करें और फिर सी कोड को बफर पर कार्य करें।

हालांकि, मैं जावा में इस बफर में डेटा को किसी भी तरह से नहीं जोड़ सकता जैसे कि बफर एक int [] या बाइट [] था। उदाहरण के लिए, बाइटबफर.एरे() को एक कॉल नव निर्मित बफर पर असफल हो जाएगा। क्या यह काम करने का कोई तरीका है?

मेरे पास सीमित स्मृति है और मुझे कितने सरणी/बफर की आवश्यकता है इसे कम करना चाहते हैं। उदाहरण के लिए, यह अच्छा होगा अगर मैं बफर बनाने के लिए IntBuffer.wrap (नया int [...]) का उपयोग कर सकता हूं और फिर जावा में सीधे बफर का समर्थन करने वाले सरणी में हेरफेर कर सकता हूं लेकिन मैं ऐसा नहीं कर सकता क्योंकि केवल एक चीज जो प्रतीत होती है जेएनआई के लिए यहां काम करें ByteBuffer.allocateDirect है।

क्या सी और जावा के बीच डेटा भेजने के लिए कोई और तरीका है? क्या मैं किसी भी तरह से सी पक्ष पर स्मृति आवंटित कर सकता हूं और क्या जावा सीधे डेटा भेज सकता है?

संपादित करें: एक बेंचमार्क की तुलना बफर उपयोग [] उपयोग int करने के लिए:

int size = 1000; 
IntBuffer allocateDirect = java.nio.ByteBuffer.allocateDirect(4 * size).asIntBuffer(); 
for (int i = 0; i < 100; ++i) 
{ 
    for (int x = 0; x < size; ++x) 
    { 
    int v = allocateDirect.get(x); 
    allocateDirect.put(x, v + 1); 
    } 
} 

int[] intArray = new int[size]; 
for (int i = 0; i < 100; ++i) 
{ 
    for (int x = 0; x < size; ++x) 
    { 
    int v = intArray[x]; 
    intArray[x] = v + 1; 
    } 
} 

एक Droid फ़ोन पर, बफर संस्करण लेता है ~ 10 सेकंड के समाप्त करने के लिए और सरणी संस्करण ~ 0.01 सेकंड लेता है।

+1

प्रतीक्षा, क्या [ 'ByteBuffer.asIntBuffer'] (http://developer.android.com/reference/java/nio/ByteBuffer.html#asIntBuffer%28%29) के साथ गलत क्या है? क्या आपको वास्तव में 'int [] 'होना चाहिए? – ephemient

+0

... और इसके अलावा, यदि आप चाहें तो इंटबफर पर .array() को कॉल कर सकते हैं। – mpontillo

+0

.array() जावा में सीधे आवंटित सरणी के लिए बाइटबफर और इंटबफर दोनों के लिए एक असमर्थित अपवाद फेंकता है। मैं वास्तव में एक int [] तक पहुंच चाहता हूं ताकि मैं जावा में कम गहन छवि प्रसंस्करण सामग्री कर सकूं। एक छवि को काले और सफेद में परिवर्तित करके जांचें कि कौन से पिक्सल चमक की दहलीज के ऊपर/नीचे हैं। इंटबफर का उपयोग करना प्रत्येक पिक्सेल के लिए मिलता है/डालता है एंड्रॉइड में बहुत धीमा होगा और साथ ही बेकार होगा। – rbcc

उत्तर

17

http://java.sun.com/docs/books/jni/html/objtypes.html से, का उपयोग JNI के Get/Release<TYPE>ArrayElements(...)

इस उदाहरण में, मैं एक सरणी पास करूंगा (तर्क के लिए, यह int array = new int[10] है और फिर इसे 0-9

से भरें
JNIEXPORT jint JNICALL 
Java_IntArray_doStuffArray(JNIEnv *env, jobject obj, jintArray arr) 
{ 

    // initializations, declarations, etc 
    jint *c_array; 
    jint i = 0; 

    // get a pointer to the array 
    c_array = (*env)->GetIntArrayElements(env, arr, NULL); 

    // do some exception checking 
    if (c_array == NULL) { 
     return -1; /* exception occurred */ 
    } 

    // do stuff to the array 
    for (i=0; i<10; i++) { 
     c_array[i] = i; 
    } 

    // release the memory so java can have it again 
    (*env)->ReleaseIntArrayElements(env, arr, c_array, 0); 

    // return something, or not.. it's up to you 
    return 0; 
} 

अध्ययन खंड 3.3, और विशेष रूप 3.3.2 - यह आप, जावा की स्मृति में सरणी के लिए सूचक इसे संशोधित करने के लिए इसे जारी, प्रभाव में आप मूल कोड में सरणी को संशोधित करने के लिए अनुमति की अनुमति देगा, और ।

मैं सिर्फ अपने ही परियोजना में इसका इस्तेमाल किया गया है (कम सरणियों के साथ) और आप सीधे आवंटित बफ़र्स उपयोग कर रहे हैं यह बहुत अच्छा :)

+0

धन्यवाद इस कोड को मुझे एफआईआर फिल्टर के लिए पुस्तकालय विधि siglib को – JPM

+2

गिनती पूर्णांक arrayLength = (* env) प्राप्त करने के लिए कनेक्ट मदद की -> GetArrayLength (env, आगमन); –

+0

जब मैं इसे आज़माता हूं, तो जावा doStuffArray (arr) देशी Java_IntArray_doStuffArray पूर्ण होने से पहले लौटाता है। जब तक मूल पक्ष पूरा नहीं हो जाता तब तक जावा पक्ष को अवरुद्ध करने के लिए मुझे क्या करने की ज़रूरत है? –

3

आप देशी परत से डेटा को डेटा भेजने के लिए कॉलबैक का उपयोग कर सकते हैं।

जावा परत में:

//Native method 
public native String getStrData(int size); 

//Callback method 
public void addData(char[] native_data, int size) { 

    ... 

} 

मूल निवासी परत में: मेरी देशी कार्यान्वयन में: मेरे देशी कक्षा में मैं निम्न विधियों है

JNIEXPORT jstring JNICALL Java_com_pkg_NativeClass_getStrData 
    (JNIEnv *env, jobject obj, jint size) { 
    ... 

    jclass native_class;   /* Callback: native class */ 
    jmethodID native_method_id; /* Callback: native method id */ 
    jcharArray row;    /* Callback: native data */ 

    ... 

    /* Start Callback: Native to Java */ 
    native_class = (*env)->GetObjectClass(env, obj); 
    native_method_id = (*env)->GetMethodID(env, native_class, "addData", "([CI)V"); 
    if (native_method_id == 0) { 
     return (jstring)ERR_NATIVE_METHODID; 
    } 
    row = (jcharArray)(*env)->NewCharArray(env, size); 
    /* jc has the data to be sent to Java */ 
    (*env)->SetCharArrayRegion(env, (jcharArray)row, (jsize)0, size, (jchar *)jc); 

    (*env)->CallVoidMethod(env, obj, native_method_id, row, size); 
    /* End Callback */ 

    ... 
} 
+0

क्या आप कृपया उल्लेख करें, 'जेसी' किस प्रकार का है? क्या यह 'char * jc' है? –

+0

@dma_k: मेरे मामले में 'जेसी' ज्ञात आकार की एक सरणी थी। – TheCottonSilk

+0

क्या आप एक संकेत दे सकते हैं, आप 'jc' के साथ कैसे काम करते हैं (उदा। वर्ण डेटा सेट करें)? मैं 'SetCharArrayRegion()' का उपयोग करने के उदाहरणों के लिए यहां और वहां देखता हूं, लेकिन 'jchar' की सरणी बनाने/प्रारंभ करने का एक पूर्ण उदाहरण नहीं मिल सकता है (उदाहरण के लिए, ASCII 1-बाइट स्ट्रिंग, 'char * ')। धन्यवाद –

5

काम करता है, आप सी से सीधे समर्थन सरणी का उपयोग कर सकते, का उपयोग करते हुए GetDirectBufferAddress फ़ंक्शन। यह क्षेत्र के क्षेत्रों की प्रतिलिपि बनाने की संभावना को रोकता है।

आप सामान्य सी सरणी के रूप में सीधे लौटे पते पर काम कर सकते हैं, और यह सीधे जावा डायरेक्ट-आवंटित बफर को संशोधित करेगा।

फिर, महाकाव्य राज्यों के रूप में, आप बफर को विभिन्न जावा प्राइमेटिव्स के सरणी को अनुकरण करने के तरीके से बफर तक पहुंचने के लिए ByteBuffer.asIntBuffer() और परिवार का उपयोग कर सकते हैं।

http://download.oracle.com/javase/1.4.2/docs/guide/jni/jni-14.html

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