2013-08-17 12 views
10

मुझे इनलाइन सी का उपयोग करके सी फ़ंक्शन में सरणी प्राप्त नहीं किया जा सकता है। मुझे कुछ मदद चाहिए, कृपया।पर्ल इनलाइन सी: एरेफ्रफ़ से सी फंक्शन

सबसे पहले, सिर्फ साबित करने के लिए मैं इनलाइन सी काम करने के लिए प्राप्त कर सकते हैं, मैं एक सी समारोह के लिए एक अदिश मान पास होगी:

#!/usr/bin/perl -I. 
# 
# try1.pl 
# 
use Inline C; 

my $c = 3.8; 
foo($c); 

__END__ 
__C__ 
void foo(double c) 
{ 
    printf("C = %f\n", c); 
} 

और इसे चलाने:

% ./try1.pl 
C = 3.800000 

अब करना एक ही बात है, लेकिन एक arrayref साथ:

#!/usr/bin/perl -I. 
# 
# try2.pl 
# 
use Inline C; 

my @abc = (1.9, 2.3, 3.8); 
foo(\@abc); 

__END__ 
__C__ 
void foo(double *abc) 
{ 
    printf("C = %f\n", abc[2]); 
} 

भागो यह:

012,
% ./try2.pl 
Undefined subroutine &main::foo called at ./try1.pl line 7. 

कोई विचार क्या मैं गलत कर रहा हूं? बहुत सराहना में मदद करें!

+0

मैं पर्ल के लिए नया हूं लेकिन रेखा 7 वह रेखा है जिसे आप सरणी को परिभाषित करते हैं, क्या आप सरणी को सही ढंग से परिभाषित कर रहे हैं। क्या आप सही तरीके से गुजर रहे हैं (/? के साथ) क्या इसे एपीआई में कुछ के माध्यम से एक सी सरणी में परिवर्तित करने की आवश्यकता है (यह नहीं कि यह एक्सडी कैसे काम कर रहा है)? –

उत्तर

4

गलत डेटा प्रकार।

use Inline 'C'; 

my @abc = (1.9, 2.3, 3.8); 
foo(\@abc); 

__END__ 
__C__ 
void foo(SV* abc) { 
    sv_dump(abc); 
} 
+0

आपके उत्तर के लिए धन्यवाद। और मैं एसवी * एबीसी के तीसरे तत्व को कैसे एक्सेस करूं? – AndyFroncioni

4

अपने Inline::C कोड में:

void foo(SV *reference) { 
    AV *array; 

    array = (AV *)SvRV(reference); 

    ... 
} 

फिर AV प्रकार के रूप में सरणी मान के साथ सौदा। Perl Inline::C Cookbook देखें।

+0

क्यों नहीं 'शून्य फू (एवी * सरणी) {... '? – mob

11

इनलाइन :: सी आपके सी फ़ंक्शन के प्रकार हस्ताक्षर के आधार पर SV के मान निकालने के लिए पर्याप्त स्मार्ट है। लेकिन यदि आप जटिल कार्यों को सी कार्यों में पास करना चाहते हैं तो आपको मान निकालने के लिए Perl API का उपयोग करना होगा। तो, यहां आपको इस समस्या के बारे में जानने की आवश्यकता है:

एक सरणी AV नामक सी struct का एक उदाहरण है। एक संदर्भ struct द्वारा RV नामक लागू किया गया है। ये सभी struct के आधार पर "उपप्रकार" (kinda) हैं SV कहा जाता है।

तो इस समारोह को काम करने के लिए हमें कुछ चीजें करने की आवश्यकता है।

  1. पैरामीटर प्रकार SV * पर बदलें (SV पर सूचक)।
  2. अगर इस विशेष SV एक संदर्भ के रूप अदिश
  3. के कुछ अन्य प्रकार के लिए विरोध किया आर.वी. चेक यकीन है कि यह एक सरणी में नहीं इशारा करते हुए और कुछ और ही है बनाने के लिए है की जाँच करने के API का उपयोग करें।
  4. RV को SV प्राप्त करने के लिए Dereference SV
  5. चूंकि हम जानते हैं कि SV एक सरणी है, इसे AV पर डालें और इसके साथ काम करना प्रारंभ करें।
  6. उस सरणी का तीसरा तत्व देखें, जो एक और SV है।
  7. चेक SV कि हम सरणी से मिला सी printf के लिए उपयुक्त एक संख्यात्मक मूल्य है
  8. SV से बाहर वास्तविक संख्यात्मक निकालें।

    use Inline C; 
    
    my @abc = (1.9, 2.3, 3.8); 
    foo(\@abc); 
    
    __END__ 
    __C__ 
    void foo(SV *abc) 
    { 
        AV *array;  /* this will hold our actual array */ 
        SV **value; /* this will hold the value we extract, note that it is a double pointer */ 
        double num; /* the actual underlying number in the SV */ 
    
        if (!SvROK(abc)) croak("param is not a reference"); 
        if (SvTYPE(SvRV(abc)) != SVt_PVAV) croak("param is not an array reference"); 
    
        /* if we got this far, then we have an array ref */ 
        /* now dereference it to get the AV */ 
        array = (AV *)SvRV(abc); 
    
        /* look up the 3rd element, which is yet another SV */ 
        value = av_fetch(array, 2, 0); 
    
        if (value == NULL) croak("Failed array lookup"); 
        if (!SvNOK(*value)) croak("Array element is not a number"); 
    
        /* extract the actual number from the SV */ 
        num = SvNV(*value); 
    
        printf("C = %f\n", num); 
    } 
    

    किंडा आप की सराहना करते हैं कितना काम पर्ल अंडर-हुड करता है बनाता है:

  9. प्रिंट संदेश

ताकि सब एक साथ डाल, हम कुछ इस तरह मिलता है। :)

अब, आपको उस उदाहरण के रूप में सुपर-स्पष्ट होने की आवश्यकता नहीं है। चीजों को इनलाइन करके आप कुछ अस्थायी चर से छुटकारा पा सकते हैं, उदा।

printf("C = %f\n", SvNV(*value)); 

num घोषित करने की आवश्यकता को खत्म कर देगा। लेकिन मैं यह स्पष्ट करना चाहता था कि सी

और नीचे @mob बिंदुओं के रूप में, आपको वास्तव में सभी काम करने की ज़रूरत नहीं है (हालांकि यह एक अच्छा विचार है कि यह कैसे काम करता है के साथ परिचित होना है।)

इनलाइन :: सी है कि यदि आप

void foo(AV *abc) { 
    ... 
} 

के रूप में अपने समारोह की घोषणा यह स्वचालित रूप से AV के लिए आप खोलने जाएगा और आप कर सकते हैं बहुत चालाक है सीधे av_fetch चरण पर जाएं।

यह सब आप के लिए चौंकाने लगता है, मैं अत्यधिक पर एक नज़र लेने की सिफारिश:

  1. Perlguts Illustrated पीडीएफ, तो
  2. perlguts मैनपेज, और फिर
  3. Inline::C Cookbook,
  4. परामर्श करते हुए
  5. perlapi मैनपेज।
+2

फ़ंक्शन 'शून्य फू (एवी * सरणी) {...' घोषित करने के लिए ठीक है और पर्ल/इनलाइन :: सी को पहले तीन चरणों को संभालने दें। – mob

+0

अच्छा बिंदु @mob; अपडेट किया गया। – friedo

+0

क्या एक पूरा जवाब @friedo है। धन्यवाद, भीड़, भीड़! – AndyFroncioni

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