2013-07-26 4 views
26

मैं एम्सस्क्रिप्ट/जावास्क्रिप्ट के साथ-साथ इस ओवरस्टैक समुदाय के लिए नया हूं। मैं क्षमा चाहता हूं, अग्रिम में, अगर मेरी स्थिति को पहले ही संबोधित किया जा चुका है।emscripten संकलित कोड में गुजरने/लौटने वाले सरणी पॉइंटर्स को कैसे संभालें?

विंडोज 7 वातावरण से, मैंने एक सरल सी प्रोग्राम संकलित करने के लिए एमसीसी का उपयोग किया है जो एक सरणी स्वीकार करता है और इसे संशोधित करता है (नीचे देखें)।

double* displayArray(double *doubleVector) { 

    for (int cnt = 0; cnt < 3; cnt++) 
     printf("doubleVector[%d] = %f\n", cnt, doubleVector[cnt]); 

    doubleVector[0] = 98; 
    doubleVector[1] = 99; 
    doubleVector[2] = 100; 

    for (int cnt1 = 0; cnt1 < 3; cnt1++) 
     printf("modified doubleVector[%d] = %f\n", cnt1, doubleVector[cnt1]); 

    return doubleVector; 
} 

int main() { 

    double d1, d2, d3; 
    double array1[3]; 
    double *array2; 

    array1[0] = 1.00000; 
    array1[1] = 2.000000; 
    array1[2] = 3.000000; 

    array2 = displayArray(array1); 

    for (int cntr =0; cntr < 3; cntr++) 
     printf("array1[%d] = %f\n", cntr, array1[cntr]); 

    for (int cnt = 0; cnt < 3; cnt++) 
     printf("array2[%d] = %f\n", cnt, array2[cnt]); 

    return 1; 
} 

EMCC के लिए -ओ विकल्पों का उपयोग करना, मैं एक .html फ़ाइल जो मैं एक ब्राउज़र (क्रोम) को लोड उत्पन्न।

python emcc displayArray7.c -o displayArray7.html -s EXPORTED_FUNCTIONS="['_main', '_displayArray' 

लोड होने पर, मुझे लगता है कि ब्राउज़र विंडो में उत्पन्न होने वाला आउटपुट अपेक्षित है (नीचे देखें)।

doubleVector[0] = 1.000000 
doubleVector[1] = 2.000000 
doubleVector[2] = 3.000000 
modified doubleVector[0] = 98.000000 
modified doubleVector[1] = 99.000000 
modified doubleVector[2] = 100.000000 
array1[0] = 98.000000 
array1[1] = 99.000000 
array1[2] = 100.000000 
array2[0] = 98.000000 
array2[1] = 99.000000 
array2[2] = 100.000000 

हालांकि, जब module.cwrap का उपयोग कर() के माध्यम से आदेश JavaScript कंसोल और सीधे समारोह आह्वान करने के लिए प्रयास करने से (के बाहर मुख्य()),

> displayArray=Module.cwrap('displayArray', '[number]', ['[number]']) 

> result = displayArray([1.0,2.0,3.0]) 
[1, 2, 3] 
> result 
[1, 2, 3] 

मैं देख रहा हूँ जेनरेट किए जाने के निम्नलिखित/ब्राउज़र में प्रदर्शित किया गया है जो मैं नहीं देख सकता हूं।

doubleVector[0] = 0.000000 
doubleVector[1] = 0.000000 
doubleVector[2] = 0.000000 
modified doubleVector[0] = 100.000000 
modified doubleVector[1] = 100.000000 
modified doubleVector[2] = 100.000000 

मैं निम्नलिखित प्रश्न हैं:

  1. मैं वाक्य रचना वापसी प्रकार और पैरामीटर Module.cwrap करने के लिए अपने कॉल में सही लिस्टिंग() के लिए सही है? मैंने int_sqrt() को ट्यूटोरियल के "कोड के साथ इंटरैक्टिंग" अनुभाग में int_sqrt() का सरल, सीधा-आगे उदाहरण चलाया है जो int_sqrt() दिनचर्या में गैर-पॉइंटर चर को गुजरने से संबंधित है।

  2. क्या ऐसा कुछ अलग हो रहा है जब सरणी और/या पॉइंटर्स emscripten- जेनरेट किए गए जावास्क्रिप्ट कोड (या से लौटाए गए) हो?

  3. फ़ंक्शन के ब्राउज़र में जेनरेट आउटपुट, displayArray(), मुख्य() से कॉल किए जाने पर काम करता है (अपेक्षित); लेकिन जावास्क्रिप्ट कंसोल के माध्यम से नहीं?

मैं ईएमएसस्क्रिप्ट/जावास्क्रिप्ट के लिए नया हूं इसलिए किसी भी जानकारी/सहायता की सराहना की जाएगी।

धन्यवाद,

एफसी

उत्तर

32

Module.cwrap की उम्मीद प्रारूप 'के लिए अनुमति नहीं है सरणी के समारोह में प्रदान किया जाने, लेकिन परिणाम पर जोर और असफल हो जायेगी अगर आप एक सरणी वापस जाने के लिए प्रयास

displayArrayA=Module.cwrap('displayArray','array',['array']) 
displayArrayA([1,2,3]) 
// Assertion failed: ccallFunc, fromC assert(type != 'array') 

इस का एक दूसरा प्रतिबंध, जो आने वाली सरणियों बाइट सरणियों होने की उम्मीद कर रहे हैं जिसका अर्थ है आप अहस्ताक्षरित 8 बिट संख्या में किसी भी भेजे डबल सरणियों कन्वर्ट करने के लिए की आवश्यकता होगी

012,
displayArrayA=Module.cwrap('displayArray','number',['array']) 
displayArrayA(new Uint8Array(new Float64Array([1,2,3]).buffer)) 

विधि इस तरह से अपने समारोह लागू करेगा कॉलिंग, अस्थायी रूप से Emscripten ढेर जो आपके लागू समारोह के निष्पादन के बाद रीसेट कर दिए जाएंगे संभावित व्यर्थ के रूप में यह stackspace मुक्त हो जाता है ऑफसेट लौटे सरणी बनाने के लिए अपने सरणियों को कॉपी।

यदि आप अपने फ़ंक्शन के परिणाम चाहते हैं, तो Emscriptens हीप सिस्टम के अंदर एक सरणी आवंटित और संरक्षित करने के लिए यह अधिक बेहतर है।

ईएमएसस्क्रिप्ट कोड केवल स्मृति को एक्सेस करने में सक्षम है जिसे Emscripten के हीप स्पेस के भीतर आवंटित किया गया है। आपके द्वारा फ़ंक्शन में पास करने का प्रयास करने वाले एरे को हेप के बाहर आवंटित किया जा रहा है कि Emscripten कोड चल रहा है, और इनकमिंग तर्कों में अपेक्षित कच्चे सूचक प्रकार से मेल नहीं खाता है।

ऐसे कई तरीके हैं जिनसे आप अपने कार्यों में डेटा पास करने के लिए किसी सरणी तक पहुंच प्राप्त कर सकते हैं। इन सभी को Emscripen की आवश्यकता है जो आपकी स्मृति के स्थान को emscripten मॉड्यूल के अंदर ज्ञान रखते हैं। हेप *, इसलिए प्रारंभिक चरण Emscripten "_malloc" फ़ंक्शन को कॉल करने के लिए किसी बिंदु पर है।

var offset = Module._malloc(24) 

यह आपको अपनी 3x 8-बाइट डबल सरणी के लिए आवश्यक Emscripten ढेर में आवश्यक 24 बाइट्स आवंटित करने के लिए अनुमति देते हैं, और एक संख्या Emscripten ढेर U8 TypedArray दर्शाने ऑफसेट अपने सरणी के लिए आरक्षित में ऑफसेट रिटर्न होगा। यह ऑफ़सेट आपका पॉइंटर है, और स्वचालित रूप से आपके cwrap displayArray फ़ंक्शन में पारित होने पर काम करेगा जब इसे कच्चे पॉइंटर ऑफ़सेट का उपयोग करने के लिए कॉन्फ़िगर किया गया हो।

  1. स्मृति सेट करें:

    displayArray=Module.cwrap('displayArray','number',['number']) 
    

    इस बिंदु पर, आप का उपयोग या सरणी की सामग्री को संशोधित करना चाहते हैं, जब तक कि malloc मान्य है, आप कम से कम निम्न विकल्प हैं एक अस्थायी रूप से लिपटे Float64 सरणी का उपयोग कर, कोई आसान तरीका के साथ उपयोग की निम्नलिखित 2 तरीकों को छोड़कर मूल्य की वसूली के लिए

    Module.HEAPF64.set(new Float64Array([1,2,3]), offset/8); 
    displayArray(offset); 
    
  2. Module.setValue स्वचालित करने के लिए 'डबल' संकेत का उपयोग करेगा आप जावास्क्रिप्ट की ओर अधिक बड़े पैमाने पर अपने सूचक उपयोग करना चाहते हैं ly HEAPF64 ऑफसेट, विभाजित संशोधित द्वारा 8.

    Module.setValue(offset, 1, 'double') 
    Module.setValue(offset+8, 2, 'double') 
    Module.setValue(offset+16, 3, 'double') 
    displayArray(offset) 
    var result = []; 
    result[0] = Module.getValue(offset,'double'); //98 
    result[1] = Module.getValue(offset+8,'double') //99 
    result[2] = Module.getValue(offset+16,'double') //100 
    
  3. , आप HEAPF64 प्रविष्टि मैन्युअल रूप से एक subarray TypedArray खींच सकते हैं। एक बार जब आप अपने फ़ंक्शन को निष्पादित कर लेते हैं तो यह आपको मूल्यों को आसानी से पढ़ने की अनुमति देता है। यह TypedArray Emscripten के बाकी के रूप में ही ढेर, इसलिए जावास्क्रिप्ट पक्ष पर प्रदर्शन सभी परिवर्तनों Emscripten पक्ष और उपाध्यक्ष प्रतिकूल पर परिलक्षित होगा द्वारा समर्थित है:

    var doublePtr = Module.HEAPF64.subarray(offset/8, offset/8 + 3); 
    doublePtr[0] = 1; 
    doublePtr[1] = 2; 
    doublePtr[2] = 3; 
    // Although we have access directly to the HEAPF64 of the pointer, 
    // we still refer to it by the pointer's byte offset when calling the function 
    displayArray(offset); 
    //doublePtr[] now contains the 98,99,100 values 
    
+2

बहुत उपयोगी जवाब। मुझे बाल खींचने के घंटों बचाता है। धन्यवाद। – scai

+0

वास्तव में बहुत उपयोगी है, लेकिन "आसपास के दूसरे तरीके" के बारे में क्या? आप सी कोड से सरणी को कैसे संशोधित कर सकते हैं और इसे जावास्क्रिप्ट में उपयोग कर सकते हैं? – gromit190

+0

मुझे एक 'मॉड्यूल.मॉलोक() 'लेकिन कोई' मॉड्यूल.फ्री()' नहीं है? क्या यह जेएस के जीसी द्वारा संभाला जाता है? – Nikkolasg

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