GoGPT Best VPN GoSearch

OnWorks فافيكون

PDL::PPp - عبر الإنترنت في السحابة

قم بتشغيل PDL::PPp في موفر الاستضافة المجاني OnWorks عبر Ubuntu Online أو Fedora Online أو محاكي Windows عبر الإنترنت أو محاكي MAC OS عبر الإنترنت

هذا هو الأمر PDL::PPp الذي يمكن تشغيله في موفر الاستضافة المجاني OnWorks باستخدام إحدى محطات العمل المجانية المتعددة عبر الإنترنت مثل Ubuntu Online أو Fedora Online أو محاكي Windows عبر الإنترنت أو محاكي MAC OS عبر الإنترنت

برنامج:

اسم


PDL::PP - إنشاء إجراءات PDL من الأوصاف المختصرة

موجز


على سبيل المثال

pp_def(
"السوموفر"،
بارس => 'أ(ن); [س]ب();',
الكود => ف{
مزدوج تمب=0;
حلقة (ن) %{
تمة += $a();
%}
$b() = tmp;
},
);

pp_done();

وظائف


فيما يلي قائمة مرجعية سريعة بالوظائف التي يوفرها PDL::PP.

pp_add_boot
أضف رمزًا إلى قسم BOOT في ملف XS الذي تم إنشاؤه

pp_add_exported
إضافة وظائف إلى قائمة الوظائف المصدرة

pp_add_isa
إضافة إدخالات إلى قائمة @ISA

pp_addbegin
يضبط التعليمات البرمجية المراد إضافتها في الجزء العلوي من ملف إنشاء .pm

pp_addhdr
أضف التعليمات البرمجية ويتضمن القسم C لملف XS الذي تم إنشاؤه

pp_addpm
أضف التعليمات البرمجية إلى ملف .pm الذي تم إنشاؤه

pp_addxs
أضف رمز XS إضافي إلى ملف XS الذي تم إنشاؤه

pp_beginwrap
قم بإضافة غلاف كتلة BEGIN إلى التعليمات البرمجية لملف .pm الذي تم إنشاؤه

pp_bless
يضبط الحزمة التي يُضاف إليها رمز XS (الافتراضي هو PDL)

pp_boundscheck
التحكم في حالة نشاط التحقق من حدود PDL

pp_core_importList
حدد ما يتم استيراده من PDL::Core

pp_def
تحديد وظيفة PDL جديدة

pp_deprecate_module
أضف تحذيرات وقت التشغيل وPOD بشأن الوحدة النمطية التي تم إهمالها

pp_done
قم بوضع علامة على نهاية تعريفات PDL::PP في الملف

pp_export_nothing
امسح قائمة التصدير للوحدة التي تم إنشاؤها

pp_line_numbers
أضف معلومات رقم السطر لتبسيط تصحيح أخطاء رمز PDL::PP

pp_setversion
قم بتعيين الإصدار لملفات .pm و.xs

نظرة عامة


لماذا نحتاج PP؟ لعدة أسباب: أولاً، نريد أن نكون قادرين على إنشاء روتين فرعي
رمز لكل نوع من أنواع بيانات PDL (PDL_Byte، PDL_Short، إلخ). تلقائيا. ثانيًا،
عند الإشارة إلى شرائح صفائف PDL في لغة Perl (على سبيل المثال "$a->slice('0:10:2,:')" أو غيرها
أشياء مثل النقل) من الجيد أن تكون قادرًا على القيام بذلك بشفافية وأن تكون قادرًا
للقيام بهذا "في المكان" - أي، ليس من الضروري عمل نسخة ذاكرة من القسم. مقابض PP
كل العناصر الضرورية وحساب الإزاحة بالنسبة لك. هناك أيضًا مفاهيم
الترابط (الاستدعاء المتكرر لنفس الروتين لشرائح متعددة، راجع PDL::Indexing)
وتدفق البيانات (انظر PDL::Dataflow) الذي يسمح به استخدام PP.

وفي الكثير مما يلي سنفترض إلمام القارئ بمفاهيم
عمليات الترابط والفهرس الضمنية والصريحة داخل PDL. إذا لم تكن قد فعلت ذلك بعد
سمعت عن هذه المفاهيم أو لم تكن مرتاحًا لها، فقد حان الوقت للتحقق
PDL::الفهرسة.

كما يمكنك أن تدرك من اسمه PDL::PP هو معالج مسبق، أي أنه يقوم بتوسيع التعليمات البرمجية عبر
بدائل لإنشاء كود C حقيقي. من الناحية الفنية، الإخراج هو رمز XS (انظر perlxs) لكن
وهذا قريب جدًا من C.

إذن كيف تستخدم PP؟ حسنًا، بالنسبة للجزء الأكبر، فأنت فقط تكتب رمز C عاديًا باستثناء
إنشاءات PP خاصة والتي تأخذ الشكل:

شيء $(شيء آخر)

أو:

وظيفة PP٪ {

%}

إن بناء PP الأكثر أهمية هو النموذج "$array()". خذ بعين الاعتبار PP البسيط للغاية
دالة لجمع عناصر المتجه أحادي الأبعاد (في الواقع هذا مشابه جدًا للقيمة الفعلية
الكود المستخدم بواسطة 'sumover'):

pp_def('سوميت',
بارس => 'أ(ن); [س]ب();',
الكود => ف{
تمب مزدوج؛
تمب = 0;
حلقة (ن) %{
تمة += $a();
%}
$b() = tmp;
}
);

ماذا يحدث هنا؟ يعد السطر "Pars =>" مهمًا جدًا لـ PP - فهو يحدد كافة العناصر
الحجج وأبعادها. نحن نسمي هذا توقيع وظيفة PP (مقارنة
أيضا التفسيرات في PDL::Indexing). في هذه الحالة يأخذ الروتين وظيفة 1-D
الإدخال وإرجاع العددية 0-D كمخرجات. يتم استخدام بنية PP "$a()" للوصول
عناصر المصفوفة a(n) لك - يقوم PP بملء كافة رموز C المطلوبة.

ستلاحظ أننا نستخدم عامل الاقتباس المفرد "q{}". هذه ليست
حادثة. تريد عمومًا استخدام علامات الاقتباس المفردة للإشارة إلى أقسام PP Code الخاصة بك. بدل::PP
يستخدم "$var()" لتحليله، وإذا لم تستخدم علامات الاقتباس المفردة، فسيحاول Perl القيام بذلك
استيفاء "$var()". كما أن استخدام عامل الاقتباس المفرد "q" مع الأقواس المتعرجة يجعله كذلك
يبدو أنك تقوم بإنشاء كتلة تعليمات برمجية، وهو ما تقصده. (إن بيرل ذكي بما فيه الكفاية ليقوم بذلك
ابحث عن الأقواس المتعرجة المتداخلة ولا تغلق علامة الاقتباس حتى تجد الأقواس المتعرجة المتطابقة
دعامة، لذلك من الآمن أن يكون لديك كتل متداخلة.) في ظل ظروف أخرى، مثل عندما تكون
غالبًا ما يكون تجميع كتلة التعليمات البرمجية باستخدام تسلسلات السلسلة هو الأسهل في الاستخدام
اقتباسات مفردة حقيقية

Code => 'something'.$interpolatable.'somethingelse;'

في الحالة البسيطة هنا حيث يتم الوصول إلى جميع العناصر، يتم بناء PP "loop(n) %{ ...
%}" يستخدم للتكرار على كافة العناصر في البعد "n". لاحظ هذه الميزة لـ PP: ALL
يتم تحديد الأبعاد بالاسم.

يصبح هذا أكثر وضوحًا إذا تجنبنا PP عقدة() بناء وكتابة الحلقة بشكل صريح
باستخدام C التقليدية:

pp_def('سوميت',
بارس => 'أ(ن); [س]ب();',
الكود => ف{
كثافة العمليات أنا، n_size؛
تمب مزدوج؛
n_size = $SIZE(n);
تمب = 0;
ل(ط=0;ط
tmp += $a(n=>i);
}
$b() = tmp;
},
);

الذي يفعل نفس الشيء كما كان من قبل، ولكنه أطول. يمكنك رؤية الحصول على العنصر "i" من
a() نقول "$a(n=>i)" - نحن نحدد البعد بالاسم "n". في البعد الثنائي يمكننا أن نقول:

بارس=>'أ(م,ن);',

tmp += $a(m=>i,n=>j);


يستعير بناء الجملة "m=>i" من تجزئات Perl، والتي يتم استخدامها في الواقع في التنفيذ
من PP. يمكن للمرء أيضًا أن يقول "$a(n=>j,m=>i)" لأن الترتيب ليس مهمًا.

يمكنك أيضًا أن ترى في المثال أعلاه استخدام بنية PP أخرى - $SIZE(n) للحصول عليها
طول البعد "ن".

ومع ذلك، تجدر الإشارة إلى أنه لا ينبغي عليك كتابة حلقة C صريحة عندما تستطيع ذلك
لقد استخدمت بنية "حلقة" PP منذ أن يتحقق PDL::PP تلقائيًا من حدود الحلقة
أنت، استخدام "الحلقة" يجعل الكود أكثر إيجازًا، وما إلى ذلك. ولكن هناك بالتأكيد مواقف
حيث تحتاج إلى تحكم واضح في الحلقة والآن تعرف كيفية القيام بذلك؛).

لإعادة النظر في "لماذا PP؟" - الكود أعلاه ل سوميت () سيتم إنشاؤها لكل نوع من البيانات. هو - هي
ستعمل على شرائح من المصفوفات "في مكانها". سيتم ربطه تلقائيًا - على سبيل المثال إذا كان ثنائي الأبعاد
سيتم استدعاء المصفوفة بشكل متكرر لكل صف 1D (تحقق مرة أخرى من PDL::Indexing for
تفاصيل الخيوط). ومن ثم سيكون b() عبارة عن مصفوفة أحادية الأبعاد من مجموع كل صف. نستطيع
أطلق عليه $a->xchg(0,1) لجمع الأعمدة بدلاً من ذلك. وسيكون تتبع تدفق البيانات وما إلى ذلك
متاح.

يمكنك أن ترى أن PP يحفظ المبرمج من كتابة الكثير من أكواد C المتكررة بلا داع -
في رأينا، هذه إحدى أفضل ميزات PDL التي تجعل كتابة إجراءات فرعية جديدة للغة C
لPDL تمرين موجز بشكل مثير للدهشة. السبب الثاني هو القدرة على توسيع PP
تعريفات التعليمات البرمجية المختصرة الخاصة بك إلى كود C مختلف بناءً على احتياجات الكمبيوتر
الهندسة المعمارية المعنية. تخيل على سبيل المثال أنك محظوظ بامتلاك جهاز كمبيوتر فائق السرعة
يديك؛ في هذه الحالة تريد من PDL::PP بالتأكيد إنشاء تعليمات برمجية تستفيد منها
لميزات الحوسبة الموجهة/المتوازية لجهازك (هذا مشروع لـ
مستقبل). على أية حال، خلاصة القول هي أن التعليمات البرمجية التي لم تتغير يجب أن تستمر في التوسع إلى
يعمل رمز XS حتى لو تغيرت الأجزاء الداخلية لـ PDL.

أيضًا، نظرًا لأنك تقوم بإنشاء التعليمات البرمجية في برنامج Perl النصي الفعلي، فهناك الكثير من المرح
الأشياء التي يمكنك القيام بها. لنفترض أنك بحاجة إلى كتابة كل من sumit (كما هو مذكور أعلاه) وmultit.
مع القليل من الإبداع، يمكننا أن نفعل ذلك

ل({Name => 'sumit'، Init => '0'، Op => '+='}،
{الاسم => 'متعدد'، Init => '1'، Op => '*='}) {
pp_def($_->{Name},
بارس => 'أ(ن); [س]ب();',
الكود => '
تمب مزدوج؛
tmp = '.$_->{Init}.';
حلقة (ن) %{
tmp '.$_->{Op}.' $أ();
%}
$b() = tmp;
')؛
}

الذي يحدد كلتا الوظيفتين بسهولة. الآن، إذا كنت بحاجة لاحقًا إلى تغيير التوقيع أو
الأبعاد أو أي شيء آخر، ما عليك سوى تغيير مكان واحد في التعليمات البرمجية الخاصة بك. طبعا أكيد،
يحتوي محررك على خاصية "القص واللصق" و"البحث والاستبدال" ولكنه لا يزال أقل
مزعج وبالتأكيد أكثر صعوبة في نسيان مكان واحد فقط ولديه أخطاء غريبة
الزحف إلى الداخل. كما أن إضافة "orit" (بطريقة البت أو) لاحقًا يعد سطرًا واحدًا.

وتذكر أن قدرات Perl الكاملة معك حقًا - حيث يمكنك القراءة بسهولة شديدة
أي ملف إدخال وإجراء إجراءات روتينية من المعلومات الموجودة في هذا الملف. لحالات بسيطة مثل
ما ورد أعلاه، يفضل المؤلف (Tjl) حاليًا بناء جملة التجزئة مثل ما ورد أعلاه - إنه ليس كذلك
أحرف أكثر بكثير من بناء جملة المصفوفة المقابلة ولكن من الأسهل فهمها وفهمها
تغيير.

ويجب أن نذكر هنا أيضًا إمكانية إيصال المؤشر إلى بداية البيانات
الذاكرة - شرط أساسي لربط PDL ببعض المكتبات. يتم التعامل مع هذا مع
التوجيه "$P(var)"، انظر أدناه.

عند بدء العمل على وظيفة pp_def'ined جديدة، إذا قمت بخطأ ما، فسوف تقوم بذلك عادةً
ابحث عن كومة من أخطاء المترجم التي تشير إلى أرقام الأسطر في ملف XS الذي تم إنشاؤه. اذا أنت
إذا كنت تعرف كيفية قراءة ملفات XS (أو إذا كنت تريد أن تتعلم بالطريقة الصعبة)، فيمكنك فتح ملف
تم إنشاء ملف XS وابحث عن رقم السطر الذي يحتوي على الخطأ. ومع ذلك، مؤخرا
بالإضافة إلى PDL::PP يساعد في الإبلاغ عن رقم السطر الصحيح لأخطائك:
"pp_line_numbers". العمل مع مثال القمة الأصلي، إذا كان لديك خطأ إملائي
tmp في الكود الخاص بك، يمكنك تغيير كود (erroneos) إلى شيء مثل هذا و
سوف يوفر لك المترجم معلومات أكثر فائدة:

pp_def('سوميت',
بارس => 'أ(ن); [س]ب();',
الكود => pp_line_numbers(__LINE__, q{
تمب مزدوج؛
تمب = 0;
حلقة (ن) %{
تمة += $a();
%}
$b() = rmp;
})
);

بالنسبة للحالة المذكورة أعلاه، يخبرني المترجم الخاص بي:


test.pd:15: خطأ: 'rmp' غير معلن (أول استخدام في هذه الوظيفة)


في المثال النصي الخاص بي (المسمى test.pd)، فإن السطر 15 هو بالضبط السطر الذي قمت بإنشاء ملفي عليه
خطأ مطبعي: "rmp" بدلاً من "tmp".

لذلك، بعد هذه النظرة السريعة على النكهة العامة لبرمجة إجراءات PDL باستخدام
PDL::PP دعنا نلخص الظروف التي يجب عليك فيها استخدام هذا بالفعل
المعالج المسبق/المترجم المسبق. يجب عليك استخدام PDL::PP إذا كنت تريد ذلك

· واجهة PDL لبعض المكتبات الخارجية

· اكتب بعض الخوارزميات التي قد تكون بطيئة إذا تم ترميزها بلغة Perl (وهذا لا يحدث كثيرًا مثلك
يفكر؛ ألق نظرة على الخيوط وتدفق البيانات أولاً).

· أن تكون مطور PDL (وحتى ذلك الحين ليس إلزاميًا)

تحذير


بسبب بنيته، يمكن أن يكون PDL::PP مرنًا وسهل الاستخدام من ناحية،
لكنها معقدة للغاية في نفس الوقت. حاليًا، جزء من المشكلة هو هذا الخطأ
الرسائل ليست مفيدة للغاية، وإذا حدث خطأ ما، فمن الأفضل أن تعرف ما أنت عليه
تقوم به وتكون قادرًا على اختراق طريقك من خلال الأجزاء الداخلية (أو تكون قادرًا على اكتشاف ذلك من خلال
التجربة والخطأ ما هو الخطأ في وسيطاتك لـ "pp_def"). على الرغم من أن العمل يجري على
إنتاج تحذيرات أفضل، لا تخف من إرسال أسئلتك إلى القائمة البريدية إذا
واجهت مشكلة.

الوصف


الآن بعد أن أصبحت لديك فكرة عن كيفية استخدام "pp_def" لتحديد وظائف PDL الجديدة، فقد حان الوقت للقيام بذلك
شرح بناء الجملة العام لـ "pp_def". يأخذ "pp_def" اسم الملف كوسائط أولاً
الوظيفة التي تحددها ثم قائمة التجزئة التي يمكن أن تحتوي على مفاتيح مختلفة.

بناءً على هذه المفاتيح، يقوم PP بإنشاء كود XS وملف .pm. وظيفة "pp_done" (انظر
يتم استخدام المثال في SYNOPSIS) لإخبار PDL::PP أنه لا يوجد المزيد من التعريفات في
هذا الملف وحان الوقت لإنشاء .xs و
ملف .pm.

ونتيجة لذلك، قد يكون هناك عدة pp_def() المكالمات داخل ملف (بواسطة ملفات الاتفاقية
مع رمز PP لها الامتداد .pd أو .pp) ولكن بشكل عام واحد فقط pp_done().

هناك نوعان رئيسيان مختلفان لاستخدام pp_def()و"عملية البيانات" و"الشريحة".
النماذج الأولية للعملية.

يتم استخدام "عملية البيانات" لأخذ بعض البيانات وإفسادها وإخراج بعض البيانات الأخرى؛ هذا
يتضمن على سبيل المثال العملية '+' وعكس المصفوفة والجمع وما إلى ذلك وجميع الأمثلة
لقد تحدثنا عنها في هذه الوثيقة حتى الآن. الخيوط الضمنية والصريحة و
ويتم الاهتمام بإنشاء النتيجة تلقائيًا في تلك العمليات. يمكنك حتى
قم بإجراء تدفق البيانات باستخدام "sumit" و"sumover" وما إلى ذلك (لا تنزعج إذا لم تفهم
مفهوم تدفق البيانات في PDL جيد جدًا حتى الآن؛ لا يزال تجريبيًا إلى حد كبير).

"عملية الشريحة" هي نوع مختلف من العمليات: في عملية الشريحة، أنت لست كذلك
بتغيير أي بيانات، فإنك تحدد المراسلات بين عناصر مختلفة من عنصرين
Piddles (تتضمن الأمثلة تعريفات وظيفة معالجة/تقطيع الفهرس في الملف
شرائح وهذا جزء من توزيع PDL؛ ولكن حذار، هذا ليس المستوى التمهيدي
أشياء).

إذا تم تجميع PDL مع دعم القيم السيئة (على سبيل المثال "WITH_BADVAL => 1")، فسيتم إضافة
المفاتيح مطلوبة لـ "pp_def"، كما هو موضح أدناه.

إذا كنت مهتمًا فقط بالتواصل مع بعض المكتبات الخارجية (على سبيل المثال بعض
مكتبة الجبر الخطي/المصفوفة)، ستحتاج عادةً إلى "عملية البيانات" لذا سنبدأ
لمناقشة ذلك أولا.

البيانات عملية


A بسيط مثال
في عملية البيانات، يجب أن تعرف أبعاد البيانات التي تحتاجها. أولا، مثال
مع العددية:

pp_def("إضافة"،
بارس => 'أ(); ب()؛ [س]ج ()؛',
الكود => '$c() = $a() + $b();'
);

يبدو ذلك غريبًا بعض الشيء ولكن دعونا نحلله. السطر الأول سهل: نحن نحدد أ
روتين بالاسم "إضافة". السطر الثاني يعلن ببساطة عن معلماتنا و
الأقواس تعني أنها عددية. نحن نسمي السلسلة التي تحدد معلماتنا و
أبعادهم توقيع من تلك الوظيفة. لأهميته فيما يتعلق
تقوم معالجات الترابط والفهرس بفحص صفحة الدليل PDL::Indexing.

السطر الثالث هو العملية الفعلية. تحتاج إلى استخدام علامات الدولار والأقواس
للإشارة إلى المعلمات الخاصة بك (من المحتمل أن يتغير هذا في وقت ما في المستقبل، بمجرد أ
تم العثور على بناء جملة جيد).

هذه السطور هي كل ما هو ضروري لتحديد وظيفة PDL فعليًا (حسنًا،
في الواقع ليس كذلك؛ تحتاج أيضًا إلى كتابة Makefile.PL (انظر أدناه) وإنشاء ملف
الوحدة النمطية (شيء مثل "Perl Makefile.PL; make"); ولكن دعونا نتجاهل ذلك في الوقت الراهن).
حتى الآن يمكنك أن تفعل

استخدم MyModule؛
$a = بدل 2,3,4;
$ب = بدل 5؛

$c = إضافة($a,$b);
# أو
add($a,$b,($c=null)); # نموذج بديل، مفيد إذا كان $c
# مسبقا لشيء كبير، وليس مفيدا هنا.

وجعل الترابط يعمل بشكل صحيح (النتيجة هي $c == [7 8 9]).

إنّ الـ بارس القسم: القادم توقيع of a PP وظيفة
عند رؤية رمز المثال أعلاه، من المرجح أن تسأل: ما هذا الغريب "$c=null"
بناء الجملة في الاستدعاء الثاني لوظيفة "الإضافة" الجديدة؟ إذا ألقيت نظرة أخرى على
تعريف "add" ستلاحظ أن الوسيطة الثالثة "c" تم وضع علامة عليها مع
المؤهل "[o]" الذي يخبر PDL::PP أن هذه وسيطة إخراج. لذلك الدعوة أعلاه ل
الإضافة تعني "إنشاء $c جديد من البداية بالأبعاد الصحيحة" - "null" هو أمر خاص
رمز مميز لـ "piddle فارغ" (قد تتساءل لماذا لم نستخدم القيمة "undef" لوضع علامة على هذا
بدلاً من "فارغة" محددة لـ PDL؛ ونحن نفكر في ذلك حاليا ;).

[يجب توضيح ذلك في قسم آخر من الدليل أيضًا!!] السبب
وجود بناء الجملة هذا كبديل هو أنه إذا كان لديك تلاعبات ضخمة حقًا، فيمكنك القيام بذلك

$c = PDL->null;
ل(بعض حلقة طويلة) {
# منغ أ، ب
add($a,$b,$c);
# munge c، ضع شيئًا مرة أخرى في a،b
}

وتجنب تخصيص وإلغاء تخصيص $c في كل مرة. يتم تخصيصه مرة واحدة في الأول
إضافة () وبعد ذلك تبقى الذاكرة حتى يتم تدمير $c.

إذا قلت فقط

$c = إضافة($a,$b);

سيقوم الكود الذي تم إنشاؤه بواسطة PP تلقائيًا بملء "$c=null" وإرجاع النتيجة. لو
تريد معرفة المزيد حول أسباب دعم PDL::PP لهذا النمط حيث يتم الإخراج
يتم تقديم الوسائط كوسائط أخيرة للتحقق من صفحة الدليل PDL::Indexing.

"[o]" ليس المؤهل الوحيد الذي يمكن أن تحتويه وسيطة pdl في التوقيع. آخر
المؤهل المهم هو الخيار "[t]" الذي يضع علامة على pdl على أنه مؤقت. ماذا يفعل ذلك
يقصد؟ أخبرت PDL::PP أن هذا pdl يُستخدم فقط للحصول على نتائج مؤقتة أثناء العملية
الحساب ولست مهتمًا بقيمته بعد الحساب
مكتمل. ولكن لماذا يريد PDL::PP معرفة هذا الأمر في المقام الأول؟ السبب
يرتبط ارتباطًا وثيقًا بمفاهيم إنشاء PDL التلقائي (سمعت عن ذلك أعلاه) و
خيوط ضمنية. إذا كنت تستخدم الترابط الضمني، فستكون الأبعاد تلقائيًا
إن ملفات PDL التي تم إنشاؤها هي في الواقع أكبر من تلك المحددة في التوقيع. مع وضع علامة "[o]".
سيتم إنشاء pdls بحيث تحتوي على الأبعاد الإضافية التي يتطلبها الرقم
من أبعاد الموضوع الضمنية. ومع ذلك، عند إنشاء pdl مؤقت، سيتم ذلك دائمًا فقط
تكون كبيرة بما يكفي بحيث يمكنها الاحتفاظ بالنتيجة لتكرار واحد في حلقة خيط، أي
بالحجم الذي يتطلبه التوقيع. لذلك يتم إهدار ذاكرة أقل عند وضع علامة على pdl كـ
مؤقت. ثانيًا، يمكنك استخدام الإنشاء التلقائي للإخراج باستخدام ملفات PDL المؤقتة حتى عندما تكون كذلك
تستخدم خيوطًا صريحة محظورة بالنسبة إلى ملفات PDL للإخراج العادي التي تم وضع علامة عليها بـ "[o]"
(انظر PDL::الفهرسة).

فيما يلي مثال حيث نستخدم المؤهل [t]. نحدد الدالة "callf" ذلك
يستدعي روتين C "f" الذي يحتاج إلى مصفوفة مؤقتة بنفس حجم ونوع المصفوفة
"a" (آسف بشأن المرجع الأمامي لـ $P؛ إنه وصول للمؤشر، انظر أدناه):

pp_def('callf',
بارس => 'أ(ن); [ر] تمب(ن); [س] ب ()'،
Code => 'int ns = $SIZE(n);
f($P(a),$P(b),$P(tmp),ns);
'
);

حجة الأبعاد و القادم توقيع
الآن تحدثنا للتو عن أبعاد pdls والتوقيع. كيف ترتبط؟
لنفترض أننا نريد إضافة رقم قياسي + رقم الفهرس إلى المتجه:

pp_def('add2',
بارس => 'أ(ن); ب()؛ [س]ج(ن)؛',
الكود => 'حلقة (ن) %{
$c() = $a() + $b() + n;
%}'
);

هناك عدة نقاط يجب ملاحظتها هنا: أولاً، تحتوي الوسيطة "Pars" الآن على الامتداد n
الحجج لإظهار أن لدينا بعدا واحدا في a و c. ومن المهم أن نلاحظ
هذه الأبعاد هي كيانات فعلية يتم الوصول إليها بالاسم، لذلك يعلن ذلك a و c إلى
لديها نفسه الأبعاد الأولى. في معظم تعريفات PP، يكون حجم الأبعاد المسماة
يتم تعيينها من الأبعاد الخاصة بـ pdls غير المخرجة (تلك التي لا تحتوي على علامة "[o]") ولكن
في بعض الأحيان قد ترغب في تعيين حجم البعد المسمى بشكل صريح من خلال
المعلمة عدد صحيح. انظر أدناه في وصف قسم "OtherPars" كيفية عمل ذلك.

ثابت حجة الأبعاد in القادم توقيع
لنفترض أنك تريد إنشاء أداة إخراج تلقائيًا وأنت تعرف ذلك في كل مرة
استدعاء البعد الخاص به سيكون له نفس الحجم (على سبيل المثال 9) بغض النظر عن أبعاد
عبث الإدخال. في هذه الحالة يمكنك استخدام بناء الجملة التالي في قسم بارس لتحديد
حجم البعد:

' [س] ذ(ن=9); '

كما هو متوقع، سيتم إنشاء أبعاد إضافية تتطلبها الخيوط إذا لزم الأمر. اذا أنت
تحتاج إلى تعيين بُعد مسمى وفقًا لصيغة أكثر تعقيدًا (من الثابت)
يجب عليك استخدام مفتاح "RedoDimsCode" الموضح أدناه.

النوع التحويلات و القادم توقيع
يحدد التوقيع أيضًا نوع التحويلات التي سيتم تنفيذها عند PP
يتم استدعاء الوظيفة. فماذا يحدث عندما نستدعي أحد العناصر المحددة مسبقًا
وظائف مع PDLS من نوع مختلف، على سبيل المثال

add2($a,$b,($ret=null));

حيث $a من النوع "PDL_Float" و$b من النوع "PDL_Short"؟ بالتوقيع كما هو موضح بالصورة
تعريف "add2" أعلى نوع بيانات العملية (كما هو محدد في وقت التشغيل).
ذلك الخاص بـ pdl بالنوع "الأعلى" (التسلسل هو بايت < قصير < ushort < طويل < float
< مزدوج). في المثال add2، نوع بيانات العملية هو float ($a يحتوي على ذلك
نوع البيانات). يتم بعد ذلك تحويل جميع وسائط pdl إلى نوع البيانات هذا (ليس كذلك
تم تحويله إلى مكانه ولكن يتم إنشاء نسخة بالنوع الصحيح في حالة عدم وجود وسيطة pdl
نوع العملية). لا تساهم ملفات pdls الفارغة بنوع ما في تحديد ملف
نوع العملية. ومع ذلك، سيتم إنشاؤها باستخدام نوع بيانات العملية؛
هنا، على سبيل المثال، سيكون $ret من النوع float. يجب أن تكون على علم بهذه القواعد عندما
استدعاء وظائف PP باستخدام PDLs من أنواع مختلفة للحصول على مساحة تخزين إضافية و
متطلبات وقت التشغيل في الاعتبار.

تحويلات النوع هذه صحيحة لمعظم الوظائف التي تحددها عادةً باستخدام "pp_def".
ومع ذلك، هناك حالات معينة يتم فيها تعديل سلوك تحويل النوع بشكل طفيف
مرغوب. في هذه الحالات، يمكن استخدام مؤهلات إضافية في التوقيع لتحديد
الخصائص المطلوبة فيما يتعلق بتحويل النوع. يمكن دمج هذه التصفيات مع
تلك التي واجهناها بالفعل ( خلق تصفيات "[س]" و"[ر]"). دعنا نذهب
من خلال قائمة المؤهلات التي تغير سلوك تحويل النوع.

الأهم هو المؤهل "int" الذي يكون مفيدًا عند استخدام وسيطة pdl
يمثل المؤشرات في pdl آخر. دعونا نلقي نظرة على مثال من "PDL::Ufunc":

pp_def('maximum_ind',
بارس => 'أ(ن); كثافة العمليات [س] ب ()'،
Code => '$GENERIC() cur;
إنت كيريند.
حلقة (ن) %{
إذا (!n || $a() > cur) {cur = $a(); كوريند = ن؛}
%}
$b() = curind;',
);

تقوم الدالة "maximum_ind" بالبحث عن فهرس أكبر عنصر في المتجه. لو نظرت
عند التوقيع، لاحظت أنه تم الإعلان عن وسيطة الإخراج "b" باستخدام ملف
مؤهل "int" إضافي. هذا له العواقب التالية لتحويلات النوع:
بغض النظر عن نوع الإدخال pdl "a" فإن الإخراج pdl "b" سيكون من النوع "PDL_Long"
وهو أمر منطقي لأن "b" سيمثل فهرسًا في "a". علاوة على ذلك، إذا اتصلت بـ
دالة بمخرج pdl "b" موجود، لن يؤثر نوعها على نوع بيانات الملف
العملية (انظر أعلاه). وبالتالي، حتى لو كان "أ" من نوع أصغر من "ب" فلن يكون كذلك
تم تحويله ليطابق النوع "b" ولكنه يبقى دون تغيير، مما يوفر الذاكرة ودورات وحدة المعالجة المركزية
وهو الشيء الصحيح الذي يجب فعله عندما يمثل "b" المؤشرات. لاحظ أيضًا أنه يمكنك استخدام
المؤهل 'int' مع المؤهلات الأخرى (المؤهلات "[o]" و"[t]"). النظام هو
هام - مؤهلات النوع تسبق مؤهلات الإنشاء ("[o]" و"[t]").

يوضح المثال أعلاه أيضًا الاستخدام النموذجي للماكرو "$GENERIC()". إنه يتوسع
إلى النوع الحالي في ما يسمى بالحلقة العامة. ما هي الحلقة العامة؟ كما كنت بالفعل
سمعت أن وظيفة PP لها نوع بيانات وقت التشغيل كما هو محدد بواسطة نوع وسيطات pdl
لقد تم استدعاؤه مع. وبالتالي فإن رمز XS الذي تم إنشاؤه بواسطة PP لهذه الوظيفة يحتوي على ملف
قم بالتبديل مثل "switch (type) {case PDL_Byte: ... case PDL_Double: ...}" الذي يحدد الحالة
استنادًا إلى نوع بيانات وقت التشغيل للوظيفة (يُطلق عليها اسم "حلقة" لأنه يوجد
عبارة عن حلقة في كود PP تولد الحالات). على أية حال، يتم إدخال الرمز الخاص بك مرة واحدة
لكل نوع PDL في بيان التبديل هذا. يتم توسيع الماكرو "$GENERIC()" إلى ملف
النوع المعني في كل نسخة من التعليمات البرمجية التي تم تحليلها في عبارة "التبديل" هذه، على سبيل المثال، في
سيتم توسيع قسم "حالة PDL_Byte" "cur" إلى "PDL_Byte" وهكذا بالنسبة للحالة الأخرى
صياغات. أعتقد أنك تدرك أن هذا ماكرو مفيد للاحتفاظ بقيم pdls في بعضها
رمز.

هناك بضعة مؤهلات أخرى لها تأثيرات مشابهة لـ "int". من اجلك
الملاءمة هناك التصفيات "العائمة" و"المزدوجة" مع عواقب مماثلة
اكتب التحويلات كـ "int". لنفترض أن لديك جدا مجموعة كبيرة تريد
حساب مجموع الصفوف والأعمدة بما يعادل الدالة "sumover". ومع ذلك، مع
التعريف العادي لـ "sumover" قد تواجهك مشكلات عندما تكون بياناتك، على سبيل المثال
اكتب باختصار. مكالمة مثل

sumover($large_pdl,($sums = null));

سيؤدي إلى أن $sums من النوع القصير، وبالتالي يكون عرضة لتجاوز الأخطاء إذا
$large_pdl عبارة عن مصفوفة كبيرة جدًا. ومن ناحية أخرى يدعو

@dims = $large_pdl->dims; التحول @ dims؛
sumover($large_pdl,($sums = Zeroes(double,@dims)));

ليس بديلاً جيدًا أيضًا. الآن ليس لدينا مشاكل تجاوز السعة مع $sums ولكن في
تكلفة تحويل نوع $large_pdl إلى مضاعفة، وهو أمر سيئ إذا كان الأمر كذلك حقًا
بدل كبير. هذا هو المكان الذي يكون فيه "مزدوج" مفيدًا:

pp_def('سوموفيرد',
بارس => 'أ(ن); مزدوج [س] ب ()'،
Code => 'double tmp=0;
حلقة(ن) %{ tmp += a(); %}
$b() = تمب;',
);

هذا يجعلنا نتغلب على مشاكل تحويل النوع وتجاوز السعة. مرة أخرى، مماثلة ل
يؤدي المؤهل "int" "double" إلى أن يكون "b" دائمًا من النوع double بغض النظر عن النوع
من "أ" دون أن يؤدي إلى تحويل نوع "أ" كأثر جانبي.

أخيرًا، هناك مؤهلات "type+" حيث يكون النوع واحدًا من "int" أو "float". ماذا
هل يعني ذلك. دعونا نوضح مؤهل "int+" بالتعريف الفعلي لـ
مجموع:

pp_def("سوموفر"،
بارس => 'أ(ن); كثافة العمليات + [س] ب ()'،
الكود => '$GENERIC(b) tmp=0;
حلقة(ن) %{ tmp += a(); %}
$b() = تمب;',
);

كما رأينا بالفعل بالنسبة للمؤهلات "int" و"float" و"double"، تم وضع علامة pdl بـ
لا يؤثر المؤهل "type+" على نوع بيانات عملية pdl. معناها هو
"اجعل ملف PDL هذا على الأقل من النوع "type" أو أعلى، كما هو مطلوب بواسطة نوع ملف
العملية". في مثال المجموع، هذا يعني أنه عند استدعاء الدالة بحرف "a"
من النوع PDL_Short، سيكون pdl الناتج من النوع PDL_Long (تمامًا كما كان الحال مع
الحالة مع المؤهل "int"). يحاول هذا مرة أخرى تجنب مشاكل الفائض عند الاستخدام
أنواع البيانات الصغيرة (مثل الصور البايتية). ومع ذلك، عندما يكون نوع البيانات للعملية أعلى
من النوع المحدد في المؤهل "type+" "b" سيتم إنشاؤه بنوع البيانات
العملية، على سبيل المثال، عندما يكون "a" من النوع مزدوج، فإن "b" سيكون مزدوجًا أيضًا. إننا نأمل
أنت توافق على أن هذا سلوك معقول بالنسبة لـ "sumover". وينبغي أن يكون واضحا كيف
يعمل المؤهل "float+" عن طريق القياس. قد يصبح من الضروري أن تكون قادرًا على تحديد مجموعة
أنواع بديلة للمعلمات. ومع ذلك، فمن المحتمل ألا يتم تنفيذ ذلك
حتى يأتي شخص ما مع استخدام معقول لذلك.

لاحظ أنه يتعين علينا الآن تحديد الماكرو $GENERIC باسم pdl لاشتقاق ملف
اكتب من تلك الحجة. لماذا هذا؟ إذا اتبعت تفسيراتنا بعناية فسوف تفعل ذلك
لقد أدركت أنه في بعض الحالات سيكون لـ "b" نوع مختلف عن نوع
عملية. يؤدي استدعاء الماكرو '$GENERIC' باستخدام "b" كوسيطة إلى التأكد من أن النوع
سيكون دائمًا هو نفسه الموجود في "b" في ذلك الجزء من الحلقة العامة.

هذا هو كل ما يمكن قوله حول قسم "Pars" في استدعاء "pp_def". يجب
تذكر أن هذا القسم يحدد توقيع من وظيفة PP المحددة، يمكنك استخدامها
عدة خيارات لتأهيل وسيطات معينة كمخرجات ووسيطات مؤقتة وجميعها
يتم تعريف الأبعاد التي يمكنك الرجوع إليها لاحقًا في قسم "الرمز" بالاسم.

من المهم أن تفهم معنى التوقيع منذ إصدار PDL الأخير
الإصدارات يمكنك استخدامه لتحديد وظائف مترابطة من داخل بيرل، أي ما نسميه
بيرل مستوى خيوط. يرجى مراجعة PDL :: الفهرسة للحصول على التفاصيل.

إنّ الـ رمز قسم
يحتوي قسم "الرمز" على رمز XS الفعلي الذي سيكون في الجزء الأعمق من الملف
حلقة الخيط (إذا كنت لا تعرف ما هي حلقة الخيط فأنت لم تقرأها بعد
بدل::الفهرسة؛ افعل ذلك الآن ؛) بعد وجود أي وحدات ماكرو PP (مثل $GENERIC) ووظائف PP
موسعة (مثل وظيفة "الحلقة" التي سنشرحها بعد ذلك).

دعونا نكرر بسرعة مثال "sumover":

pp_def("سوموفر"،
بارس => 'أ(ن); كثافة العمليات + [س] ب ()'،
الكود => '$GENERIC(b) tmp=0;
حلقة(ن) %{ tmp += a(); %}
$b() = تمب;',
);

تشير بنية "الحلقة" في قسم "الرمز" أيضًا إلى اسم البعد، لذا لا تفعل ذلك
تحتاج إلى تحديد أي حدود: حجم الحلقة صحيح ويتم كل شيء من أجلك،
مرة أخرى.

بعد ذلك، هناك الحقيقة المدهشة المتمثلة في أن "$a()" و"$b()" يفعلان ذلك ليست تحتوي على الفهرس. هذا
ليس ضروريًا لأننا نكرر n وكلا المتغيرين يعرفان الأبعاد
لقد فعلوا ذلك حتى يعلموا تلقائيًا أنه يتم تكرارهم.

هذه الميزة مفيدة جدًا في العديد من الأماكن وتنتج تعليمات برمجية أقصر بكثير. ل
بالطبع، هناك أوقات تريد فيها التحايل على هذا؛ هنا وظيفة تجعل
مصفوفة متماثلة وهي بمثابة مثال لكيفية ترميز الحلقات الصريحة:

pp_def('symm',
بارس => 'أ(ن,ن); [س]ج(ن،ن)؛'،
الكود => 'حلقة (ن) %{
كثافة العمليات n2؛
ل(n2=n; n2<$SIZE(n); n2++) {
$c(n0 => n, n1 => n2) =
$c(n0 => n2, n1 => n) =
$a(n0 => n, n1 => n2);
}
%}
'
);

دعونا تشريح ما يحدث. أولاً، ما هي الوظيفة التي من المفترض أن تفعلها؟ منها
التوقيع ترى أنه يأخذ مصفوفة ثنائية الأبعاد بأعداد متساوية من الأعمدة والصفوف و
إخراج مصفوفة من نفس الحجم. من مصفوفة إدخال معينة $a فإنه يحسب متماثل
مصفوفة الإخراج $c (متماثلة بمعنى المصفوفة أن A^T = A حيث يعني ^T المصفوفة
تبديل، أو بلغة PDL $c == $c->xchg(0,1)). يفعل ذلك باستخدام القيم فقط
على وتحت قطري $a. في مصفوفة الإخراج $c جميع القيم الموجودة في وأسفل
القطرية هي نفس تلك الموجودة في $a بينما تلك الموجودة فوق القطر هي صورة معكوسة لـ
تلك الموجودة أسفل القطر (أعلاه وأدناه يتم تفسيرها هنا بالطريقة التي تطبع بها PDL
2D PDL). إذا كان هذا التفسير لا يزال يبدو غريبًا بعض الشيء، فما عليك سوى إنشاء ملف صغير
الذي تكتب فيه هذا التعريف، أنشئ امتداد PDL الجديد (راجع القسم الخاص بـ
Makefiles لرمز PP) وجربه مع بعض الأمثلة.

بعد أن شرحت ما يفترض أن تفعله الوظيفة، هناك بضع نقاط تستحق ذلك
مع ملاحظة من الناحية النحوية. أولاً، نحصل على حجم البعد المسمى
"n" مرة أخرى باستخدام الماكرو $SIZE. ثانيًا، هناك فجأة هذه "n0" و"n1" المضحكة
أسماء الفهرس في الكود على الرغم من أن التوقيع يحدد البعد "n" فقط. لماذا هذا؟ ال
يصبح السبب واضحًا عندما تلاحظ أن البعدين الأول والثاني لـ $a و$b
تمت تسميتهم بـ "n" في توقيع "symm". هذا يخبر PDL::PP أن الأول والثاني
أبعاد هذه الوسائط يجب أن يكون لها نفس الحجم. وإلا فإن الوظيفة التي تم إنشاؤها
سوف يثير خطأ وقت التشغيل. ومع ذلك، الآن في الوصول إلى $a و $c لا يمكن لـ PDL::PP معرفة ذلك
ما هو الفهرس "n" الذي يشير إليه فقط من اسم الفهرس. لذلك،
يتم ترقيم المؤشرات ذات الأسماء ذات الأبعاد المتساوية من اليسار إلى اليمين بدءًا من 0، على سبيل المثال in
يشير المثال أعلاه "n0" إلى البعد الأول لـ $a و$c، ويشير "n1" إلى البعد الثاني و
هكذا.

في جميع الأمثلة حتى الآن، استخدمنا فقط أعضاء "Pars" و"Code" في تجزئة ذلك
تم تمريره إلى "pp_def". هناك بالتأكيد مفاتيح أخرى يتعرف عليها PDL::PP و
وسنسمع عن بعضها في سياق هذه الوثيقة. البحث عن (غير شامل)
قائمة المفاتيح في الملحق أ. قائمة وحدات الماكرو ووظائف PP (لقد واجهنا فقط
بعض تلك الموجودة في الأمثلة أعلاه حتى الآن) والتي تم توسيعها في قيم وسيطة التجزئة
إلى "pp_def" تم تلخيصه في الملحق ب.

في هذه المرحلة، قد يكون من المناسب الإشارة إلى أن PDL::PP ليس ثابتًا تمامًا،
مجموعة من الإجراءات الروتينية المصممة جيدًا (كما يقول توماس: "توقف عن التفكير في PP كمجموعة من
إجراءات منحوتة في الحجر") بل مجموعة من الأشياء التي كتبها مؤلف PDL::PP
(توماس ج. لوكا) اعتبر أنه سيضطر إلى الكتابة كثيرًا في إجراءات تمديد PDL الخاصة به.
تحاول PP أن تكون قابلة للتوسيع بحيث يمكن في المستقبل، مع ظهور احتياجات جديدة، إنشاء كود مشترك جديد
يتم تجريدها مرة أخرى فيه. إذا كنت تريد معرفة المزيد عن سبب رغبتك في التغيير
PDL::PP وكيفية القيام بذلك تحقق من القسم الخاص بـ PDL::PP الداخلية.

معالجة سيئة القيم
إذا لم يكن لديك دعم ذو قيمة سيئة تم تجميعه في PDL، فيمكنك تجاهل هذا القسم وملف
المفاتيح ذات الصلة: "BadCode"، "HandleBad"، ... (حاول طباعة قيمة
$PDL::Bad::Status - إذا كانت تساوي 0، فانتقل مباشرةً).

هناك العديد من المفاتيح ووحدات الماكرو المستخدمة عند كتابة التعليمات البرمجية للتعامل مع القيم السيئة. الأول
الأول هو مفتاح "HandleBad":

المقود => 0
يؤدي هذا إلى وضع علامة على روتين pp كـ لا التعامل مع القيم السيئة إذا تم إرسال هذا الروتين العبث
مع مجموعة "badflag" الخاصة بهم، ثم تتم طباعة رسالة تحذير على STDOUT وpiddles
تتم معالجتها كما لو كانت القيمة المستخدمة لتمثيل القيم السيئة رقمًا صالحًا. ال
لا يتم نشر قيمة "badflag" إلى عناصر الإخراج.

أحد الأمثلة على استخدام ذلك هو إجراءات FFT، والتي لا تحتوي بشكل عام على طريقة
لتجاهل جزء من البيانات.

المقود => 1
يؤدي هذا إلى قيام PDL::PP بكتابة تعليمات برمجية إضافية تضمن استخدام قسم BadCode، و
أن يعمل الماكرو "$ISBAD()" (وإخوانه).

لم يتم إعطاء HandleBad
إذا تم تعيين "badflag" على أي من أدوات الإدخال، فسيتم تعيين علامات الإخراج الخاصة بها
تم تعيين "badflag" الخاص بهم، ولكن يتم تجاهل أي رمز BadCode تم توفيره.

يتم استخدام قيمة "HandleBad" لتحديد محتويات مفتاح "BadDoc"، إذا لم يكن كذلك
معطى.

للتعامل مع القيم السيئة، يجب كتابة التعليمات البرمجية بشكل مختلف إلى حد ما؛ على سبيل المثال،

$c() = $a() + $b();

يصبح شيئًا مثل

إذا ( $a() != BADVAL && $b() != BADVAL ) {
$c() = $a() + $b();
{} آخر
$c() = بادفال;
}

ومع ذلك، نريد الإصدار الثاني فقط في حالة وجود قيم سيئة في عناصر الإدخال
(وهذا الدعم ذو القيمة السيئة مطلوب!) - وإلا فإننا نريد الكود الأصلي بالفعل.
هذا هو المكان الذي يأتي فيه مفتاح "BadCode"؛ يمكنك استخدامه لتحديد التعليمات البرمجية التي سيتم تنفيذها إذا كانت سيئة
قد تكون القيم موجودة، ويستخدم PP كلاً منها وقسم "الكود" لإنشاء شيء ما
مثل:

إذا (القيم_السيئة_حاضرة) {
يتوهم_threadloop_stuff {
كود سيء
}
{} آخر
يتوهم_threadloop_stuff {
رمز
}
}

ويعني هذا الأسلوب أنه لا يوجد أي حمل فعلي عند عدم وجود قيم سيئة
(أي إرجاع روتين badflag 0).

يمكن أن يستخدم قسم BadCode نفس وحدات الماكرو وبنيات التكرار مثل قسم Code.
ومع ذلك، لن يكون هناك فائدة كبيرة بدون وحدات الماكرو الإضافية التالية:

$ISBAD(فار)
للتحقق مما إذا كانت قيمة اللغز سيئة، استخدم الماكرو $ISBAD:

if ( $ISBAD(a()) ) { printf("a() سيء\n"); }

يمكنك أيضًا الوصول إلى عناصر معينة من اللغز:

if ( $ISBAD(a(n=>l)) ) { printf("العنصر %d من a() سيء\n"، l); }

$ISGOOD(فار)
وهذا عكس الماكرو $ISBAD.

$SETBAD(فار)
لأنه عندما تريد تعيين عنصر من العناصر السيئة.

$ISBADVAR(c_var,pdl)
إذا قمت بتخزين قيمة Piddle "$a()" مؤقتًا في متغير c ("foo" على سبيل المثال)، ثم إلى
تحقق مما إذا كان سيئًا، استخدم "$ISBADVAR(foo,a)".

$ISGOODVAR(c_var,pdl)
كما هو مذكور أعلاه، ولكن هذه المرة يتم التحقق من أن القيمة المخزنة مؤقتًا ليست سيئة.

$SETBADVAR(c_var,pdl)
لنسخ القيمة السيئة لpiddle إلى متغير ac، استخدم "$SETBADVAR(foo,a)".

لكى يفعل: اذكر "$PPISBAD()" وما إلى ذلك من وحدات الماكرو.

باستخدام وحدات الماكرو هذه، يمكن تحديد الكود أعلاه على النحو التالي:

الكود => '$c() = $a() + $b();',
كود سيء => '
إذا ( $ISBAD(a()) || $ISBAD(b())) {
$SETBAD(c());
{} آخر
$c() = $a() + $b();
}',

نظرًا لأن هذا هو Perl، TMTOWTDI، فيمكنك أيضًا كتابة:

كود سيء => '
إذا ( $ISGOOD(a()) && $ISGOOD(b())) {
$c() = $a() + $b();
{} آخر
$SETBAD(c());
}',

إذا كنت تريد الوصول إلى قيمة العلامة السيئة لأمر معين، فيمكنك استخدام الملف
وحدات الماكرو "$PDLSTATExxxx()":

$PDLSTATEISBAD(pdl)
$PDLSTATEISGOOD(pdl)
$PDLSTATESETBAD(pdl)
$PDLSTATESETGOOD(pdl)

لكى يفعل: اذكر خياري "FindBadStatusCode" و"CopyBadStatusCode" في "pp_def" أيضًا
كمفتاح "BadDoc".

التواصل لك الخاصة/المكتبة وظائف استخدام PP
الآن، ضع في اعتبارك ما يلي: لديك وظيفة C الخاصة بك (والتي قد تكون في الواقع جزءًا من
بعض المكتبات التي تريد ربطها بـ PDL) والتي تأخذ مؤشرين كوسائط
ناقلات مزدوجة:

void myfunc(int n,double *v1,double *v2);

الطريقة الصحيحة لتعريف وظيفة PDL هي

pp_def('myfunc',
بارس => 'أ(ن); [س] ب (ن)؛'،
الأنواع العامة => ['D']،
الرمز => 'myfunc($SIZE(n),$P(a),$P(b));'
);

"$ف("من قبل")" يقوم بناء الجملة بإرجاع مؤشر إلى العنصر الأول والعناصر الأخرى
يضمن الكذب بعد ذلك.

لاحظ أنه من الممكن هنا ارتكاب العديد من الأخطاء. أولاً، يجب استخدام $SIZE(n).
بدلا من "ن". ثانيًا، يجب ألا تضع أي حلقات في هذا الكود. ثالثا، هنا نواجه
مفتاح تجزئة جديد تم التعرف عليه بواسطة PDL::PP : إعلان "GenericTypes" يخبر PDL::PP بـ
قم فقط بإنشاء TYPELOOP من قائمة الأنواع المحددة. في هذه الحالة "مزدوج". هذا
له ميزتان. أولاً، يتم تقليل حجم الكود المترجم بشكل كبير، وثانيًا إذا
يتم تمرير الوسائط غير المزدوجة إلى "myfunc ()" وسيقوم PDL بتحويلها تلقائيًا إلى
مضاعفة قبل المرور إلى روتين C الخارجي وتحويلها مرة أخرى بعد ذلك.

يمكن للمرء أيضًا استخدام "Pars" لتأهيل أنواع الوسائط الفردية. وهكذا يمكن للمرء أيضا
اكتب هذا على النحو التالي:

pp_def('myfunc',
بارس => 'مزدوج أ(ن)؛ مزدوج [س] ب (ن)؛'،
الرمز => 'myfunc($SIZE(n),$P(a),$P(b));'
);

مواصفات النوع في "Pars" تعفي الوسيطة من الاختلاف في حلقة الكتابة -
بل يتم تحويله تلقائيًا أيضًا ومن النوع المحدد. هذا واضح
مفيد في مثال أكثر عمومية، على سبيل المثال:

void myfunc(int n,float *v1,long *v2);

pp_def('myfunc',
بارس => 'تعويم أ (ن)؛ طويلة [س] ب (ن)؛'،
الأنواع العامة => ['F']،
الرمز => 'myfunc($SIZE(n),$P(a),$P(b));'
);

لاحظ أننا لا نزال نستخدم "GenericTypes" لتقليل حجم حلقة الكتابة، ومن الواضح أن PP يمكنه ذلك
من حيث المبدأ، اكتشف هذا وقم بذلك تلقائيًا على الرغم من أن الكود لم يحقق ذلك بعد
مستوى من التطور!

أخيرًا، لاحظ أنه عندما يتم تحويل الأنواع تلقائيًا، يجب على المرء استخدام المؤهل "[o]" لـ
سيتم تحسين متغيرات الإخراج أو التغييرات الصعبة بواسطة PP!

إذا كنت تتعامل مع مكتبة كبيرة، فيمكنك أتمتة الواجهة بشكل أكبر. يمكن لبيرل
مساعدتك مرة أخرى (!) في القيام بذلك. في العديد من المكتبات لديك اصطلاحات اتصال معينة.
هذا يمكن استغلاله. باختصار، يمكنك كتابة محلل صغير (وهو في الحقيقة ليس كذلك
صعب في Perl) الذي يقوم بعد ذلك بإنشاء استدعاءات لـ "pp_def" من الأوصاف التي تم تحليلها لـ
الوظائف الموجودة في تلك المكتبة. على سبيل المثال، يرجى التحقق من سلاتيك واجهة في
شجرة "Lib" لتوزيع PDL. إذا كنت تريد التحقق (أثناء التصحيح) مما يدعو إلى
وظائف PP التي أنشأها كود Perl الخاص بك هي حزمة مساعدة صغيرة تكون مفيدة
يستبدل وظائف PP بوظائف ذات أسماء متطابقة تقوم بتفريغ وسيطاتها إلى stdout.

فقط قل

بيرل -MPDL::PP::تفريغ myfile.pd

لرؤية المكالمات إلى "pp_def" والأصدقاء. جربه مع ops.pd و slatec.pd. إذا كنت
إذا كنت مهتمًا (أو ترغب في تحسينه)، فالمصدر موجود في Basic/Gen/PP/Dump.pm

أخرى وحدات الماكرو و وظائف in القادم رمز قسم
وحدات الماكرو: واجهنا حتى الآن وحدات الماكرو $SIZE و$GENERIC و$P. الآن نحن ذاهبون إلى
قم بشرح وحدات الماكرو الأخرى التي تم توسيعها في قسم "الكود" في PDL::PP بسرعة
مع أمثلة على استخدامها.

$T يتم استخدام الماكرو $T لمفاتيح الكتابة. هذا مفيد جدًا عندما يتعين عليك استخدامه
وظائف خارجية مختلفة (مثل المكتبة) اعتمادًا على نوع الوسائط المدخلة.
بناء الجملة العام هو

$Ttypeletters(type_alternatives)

حيث "الحروف المطبوعة" هي تبديل لمجموعة فرعية من الحروف "BSULFD" الموجودة
بالنسبة لـ Byte وShort وUshort وما إلى ذلك و"type_alternatives" هي التوسعات عند الكتابة
لعملية PP تساوي تلك المشار إليها بالحرف المعني. دعونا
وضح هذا الوصف غير المفهوم بمثال. على افتراض أن لديك اثنين من C
وظائف مع النماذج الأولية

void float_func(float *in, float *out);
void double_func(double *in, double *out);

والتي تفعل نفس الشيء بشكل أساسي ولكن أحدهما يقبل التعويم والمؤشرات المزدوجة الأخرى.
يمكنك ربطها بـ PDL عن طريق تحديد وظيفة عامة "foofunc" (والتي سوف
استدعاء الوظيفة الصحيحة اعتمادًا على نوع التحويل):

pp_def('foofunc',
بارس => ' أ(ن); [س] ب()؛',
Code => ' $TFD(float_func,double_func) ($P(a),$P(b));'
GenericTypes => [qw(FD)],
);

يرجى ملاحظة أنه لا يمكنك القول

Code => ' $TFD(float,double)_func ($P(a),$P(b));'

نظرًا لأن الماكرو $T يتوسع بمسافات زائدة، بشكل مشابه لوحدات ماكرو المعالج الأولي لـ C.
النموذج الأطول قليلاً الموضح أعلاه صحيح. إذا كنت تريد حقا الاختصار، عليك
يمكن بالطبع أن تفعل

'$TBSULFD('.(الانضمام إلى ',',الخريطة {"long_identifier_name_$_"}
qw/byt صالة قصيرة غير موقعة flotte dubble/).');'

$PP
يتم استخدام الماكرو $PP لما يسمى مادي مؤشر الوصول. مادي يشير إلى
بعض التحسينات الداخلية لـ PDL (بالنسبة لأولئك الذين هم على دراية بنواة PDL، نحن
الحديث عن تحسينات فافين). هذا الماكرو مخصص للاستخدام الداخلي وأنت أيضًا
لا ينبغي أن تحتاج إلى استخدامه في أي من التعليمات البرمجية العادية الخاصة بك.

$COMP (وقسم "OtherPars")
يتم استخدام الماكرو COMP $ للوصول إلى القيم غير الخاصة بـ pdl في قسم التعليمات البرمجية. اسمها
المستمدة من تنفيذ التحولات في PDL. المتغيرات التي يمكنك الرجوع إليها
لاستخدام $COMP هم أعضاء في البنية "المترجمة" التي تمثل PDL
التحول المعني ولكنه لا يحتوي حتى الآن على أي معلومات حول الأبعاد
(لمزيد من التفاصيل راجع PDL::Internals). ومع ذلك، يمكنك التعامل مع $COMP كملف
الصندوق الأسود دون معرفة أي شيء عن تنفيذ التحولات في PDL.
إذن متى ستستخدم هذا الماكرو؟ استخدامه الرئيسي هو الوصول إلى قيم الوسائط التي
تم التصريح عنها في قسم "OtherPars" من تعريف "pp_def". ولكن بعد ذلك لم تفعل ذلك
سمعت عن مفتاح "OtherPars" حتى الآن؟! ولنأخذ مثالاً آخر يوضح ذلك
الاستخدام النموذجي لكلتا الميزات الجديدة:

pp_def('pnmout',
بارس => 'a(م)'،
OtherPars => "شار* فد"،
الأنواع العامة => [qw(BUSL)],
Code => 'PerlIO *fp;
IO *IO;

io = GvIO(gv_fetchpv($COMP(fd),FALSE,SVt_PVIO));
إذا (!io || !(fp = IoIFP(io)))
Croak("لا يمكن معرفة FP");

إذا (PerlIO_write(fp,$P(a),len) != len)
Croak("حدث خطأ أثناء كتابة ملف pnm");
')؛

تُستخدم هذه الوظيفة لكتابة البيانات من ملف pdl إلى ملف. تم تمرير واصف الملف
كسلسلة في هذه الوظيفة. لا تنتقل هذه المعلمة إلى قسم "Pars".
نظرًا لأنه لا يمكن معاملته بشكل مفيد مثل pdl بل في الاسم المناسب
قسم "OtherPars". المعلمات الموجودة في قسم "OtherPars" تتبع تلك الموجودة في "Pars"
القسم عند استدعاء الوظيفة، أي

افتح الملف،">out.dat" أو يموت "تعذر فتح out.dat"؛
pnmout($pdl,'FILE');

عندما تريد الوصول إلى هذه المعلمة داخل قسم التعليمات البرمجية، عليك إخبار PP بها
باستخدام الماكرو $COMP، أي تكتب "$COMP(fd)" كما في المثال. خلاف ذلك ص
لا أعرف أن "fd" الذي تشير إليه هو نفسه المحدد في ملف
قسم "OtherPars".

الاستخدام الآخر لقسم "OtherPars" هو تعيين بُعد مسمى في التوقيع.
دعونا نحصل على مثال لكيفية القيام بذلك:

pp_def('setdim',
بارس => '[س] أ(ن)'،
OtherPars => 'int ns => n'،
Code => 'loop(n) %{ $a() = n; %}',
);

يشير هذا إلى أنه سيتم تهيئة البعد المسمى "n" من قيمة أخرى
المعلمة "ns" وهو من النوع الصحيح (أعتقد أنك أدركت أننا نستخدم
"CType من => بناء الجملة المسمى_dim"). يمكنك الآن استدعاء هذه الوظيفة بالطريقة المعتادة:

setdim(($a=null),5);
طباعة $أ؛
[ 0 1 2 3 4 ]

من المسلم به أن هذه الوظيفة ليست مفيدة جدًا ولكنها توضح كيفية عملها. اذا أنت
قم باستدعاء الوظيفة باستخدام pdl موجود ولا تحتاج إلى تحديد وظيفة
حجم "n" نظرًا لأن PDL::PP يمكنه اكتشافه من أبعاد pdl غير الفارغة. في
في هذه الحالة، تقوم فقط بإعطاء معلمة البعد كـ "-1":

$a = اصمت($b);
setdim($a,-1);

يجب أن تفعل ذلك.

وظيفة PP الوحيدة التي استخدمناها في الأمثلة حتى الآن هي "loop". بالإضافة إلى ذلك،
توجد حاليًا وظيفتان أخريان تم التعرف عليهما في قسم "الرمز":

Threadloop
كما سمعنا أعلاه، فإن توقيع وظيفة PP المحددة يحدد أبعاد الجميع
وسيطات pdl المتضمنة في a بدائي عملية. ومع ذلك، غالبًا ما تتصل بـ
الوظائف التي حددتها باستخدام PP باستخدام pdls التي لها أبعاد أكثر من تلك
المحدد في التوقيع في هذه الحالة يتم تنفيذ العملية البدائية على الجميع
شرائح فرعية ذات أبعاد مناسبة فيما يسمى ب خيط حلقة (انظر أيضا
نظرة عامة أعلاه وPDL::Indexing). على افتراض أن لديك فكرة عن هذا المفهوم لك
من المحتمل أن نقدر أن العملية المحددة في قسم التعليمات البرمجية يجب أن تكون
الأمثل لأن هذه هي أضيق حلقة داخل حلقة الخيط. ومع ذلك، إذا قمت بإعادة النظر
في المثال الذي حددنا فيه وظيفة "pnmout"، ستدرك بسرعة أن المظهر
لا يكون واصف الملف "IO" في حلقة الخيط الداخلي فعالاً للغاية عند الكتابة
pdl مع العديد من الصفوف. قد يكون الأسلوب الأفضل هو البحث عن واصف "IO" مرة واحدة
خارج حلقة الخيط واستخدم قيمته ثم داخل حلقة الخيط الأضيق. هذا هو
بالضبط حيث تكون وظيفة "threadloop" مفيدة. هنا تعريف محسن
من "pnmout" الذي يستخدم هذه الوظيفة:

pp_def('pnmout',
بارس => 'a(م)'،
OtherPars => "شار* فد"،
الأنواع العامة => [qw(BUSL)],
Code => 'PerlIO *fp;
IO *IO;
int len؛

io = GvIO(gv_fetchpv($COMP(fd),FALSE,SVt_PVIO));
إذا (!io || !(fp = IoIFP(io)))
Croak("لا يمكن معرفة FP");

لين = $SIZE(م) * حجم($GENERIC());

حلقة الخيط %{
إذا (PerlIO_write(fp,$P(a),len) != len)
Croak("حدث خطأ أثناء كتابة ملف pnm");
%}
')؛

هذا يعمل على النحو التالي. عادةً ما يتم وضع رمز C الذي تكتبه داخل قسم "الرمز".
داخل حلقة الخيط (أي يقوم PP بإنشاء كود XS المناسب حوله).
ومع ذلك، عند استخدام وظيفة "threadloop" بشكل صريح، يتعرف PDL::PP على هذا و
لا يغلف الكود الخاص بك بحلقة ترابط إضافية. هذا له التأثير الذي يرمز لك
يتم تنفيذ الكتابة خارج حلقة الخيط مرة واحدة فقط لكل تحويل ورمز فقط
مع وضع الزوج "%{ ... %}" المحيط داخل أضيق حلقة خيط. هذا
يكون أيضًا مفيدًا عندما تريد تنفيذ قرار (أو أي كود آخر، خصوصًا
رمز مكثف لوحدة المعالجة المركزية) مرة واحدة فقط لكل موضوع، على سبيل المثال

pp_addhdr('
#تعريف الخام 0
#تعريف ASCII 1
')؛
pp_def('do_raworascii',
بارس => 'أ(); ب()؛ [س]ج ()'،
OtherPars => 'وضع int'،
الكود => 'التبديل ($COMP(وضع)) {
حالة الخام:
حلقة الخيط %{
/* افعل الأشياء الخام */
%}
كسر؛
حالة ASCII:
حلقة الخيط %{
/* القيام بأشياء ASCII */
%}
كسر؛
الافتراضي:
Croak("وضع غير معروف");
}'
);

أنواع
تعمل وظيفة الأنواع بشكل مشابه للماكرو $T. ومع ذلك، مع وظيفة "الأنواع".
يتم تنفيذ التعليمات البرمجية الموجودة في الكتلة التالية (المفصولة بـ "%{" و"%}" كالمعتاد) للجميع
تلك الحالات التي يكون فيها نوع بيانات العملية أي وقت of الأنواع التي يمثلها
الحروف في الوسيطة "للكتابة"، على سبيل المثال

الكود =>'...

الأنواع (BSUL) %{
/* تنفيذ عملية نوع عدد صحيح */
%}
الأنواع (FD) %{
/* تنفيذ عملية النقطة العائمة */
%}
... "

إنّ الـ RedoDimsCode القسم
مفتاح "RedoDimsCode" هو مفتاح اختياري يُستخدم لحساب أبعاد العبث في
وقت التشغيل في حالة عدم وجود القواعد القياسية لحساب الأبعاد من التوقيع
كافٍ. يتم تفسير محتويات إدخال "RedoDimsCode" بنفس الطريقة
يتم تفسير قسم الكود-- أي، يتم توسيع وحدات ماكرو PP والنتيجة هي
يتم تفسيره على أنه رمز C. الغرض من الكود هو ضبط حجم بعض الأبعاد التي
تظهر في التوقيع سيتم إعداد تخصيص التخزين وthreadloops وما إلى ذلك
إذا كان البعد المحسوب قد ظهر في التوقيع. في التعليمات البرمجية الخاصة بك، عليك أولا حساب
الحجم المطلوب للبعد المسمى في التوقيع حسب احتياجاتك وبعد ذلك
قم بتعيين هذه القيمة لها عبر $مقاس() دقيق.

على سبيل المثال، النظر في الوضع التالي. أنت تتعامل مع مكتبة خارجية
الروتين الذي يتطلب تمرير مصفوفة مؤقتة لمساحة العمل كوسيطة. اثنين
صفائف بيانات الإدخال التي تم تمريرها هي p(م) و س (ن). مصفوفة بيانات الإخراج هي y(n). ال
يتطلب الروتين مصفوفة مساحة عمل بطول n+m*m، وترغب في التخزين
يتم إنشاؤه تلقائيًا تمامًا كما هو الحال مع أي رمز صغير تم وضع علامة عليه بـ [t] أو [o]. ماذا
كنت ترغب في أن أقول شيئا من هذا القبيل

pp_def ("myexternalfunc"،
بارس => " p(م)؛ س(ن); [س] ذ؛ [ر] العمل(ن+م*م); "، ...

ولكن هذا لن ينجح، لأن PP لا يمكنه تفسير التعبيرات الحسابية في
إمضاء. بدلا من ذلك تكتب

pp_def ("myexternalfunc"،
بارس => " p(م)؛ س(ن); [س] ذ؛ [ر] العمل(ن); "،
ريدوديمس كود => "
int im = $PDL(p)->dims[0];
int in = $PDL(x)->dims[0];
int min = in + im * im;
int inw = $PDL(work)->dims[0];
$SIZE(wn) = inw >= دقيقة؟ inw : دقيقة؛ "،
الكود => "
Externalfunc($P(p),$P(x),$SIZE(م)،$SIZE(ن)،$P(العمل));
"؛)

يعمل هذا الرمز كما يلي: يتم توسيع الماكرو $PDL(p) إلى مؤشر إلى بنية pdl لـ
اللغز ص. لا تريد مؤشرًا للبيانات (على سبيل المثال $P) في هذه الحالة، لأنك
تريد الوصول إلى أساليب اللغز على المستوى C. تحصل على البعد الأول
كل من الألغاز وتخزينها في أعداد صحيحة. ثم تقوم بحساب الحد الأدنى للطول
يمكن أن تكون مجموعة العمل. إذا أرسل المستخدم "عملًا" مع مساحة تخزين كافية، فاتركه
وحيد. إذا أرسل المستخدم، على سبيل المثال، pdl فارغًا، أو لم يرسل pdl على الإطلاق، فسيكون حجم wn
صفر وقمت بإعادة تعيينه إلى الحد الأدنى للقيمة. قبل الكود الموجود في قسم الكود هو
سيقوم PP المنفذ بإنشاء التخزين المناسب لـ "العمل" إذا لم يكن موجودًا. لاحظ أنك
أخذ فقط البعد الأول لـ "p" و"x" لأن المستخدم ربما أرسل تلاعبًا به
أبعاد خيوط إضافية. بالطبع، "العمل" المؤقت (لاحظ العلامة [t])
لا ينبغي أن تعطى أي أبعاد موضوع على أي حال.

يمكنك أيضًا استخدام "RedoDimsCode" لتعيين أبعاد القطعة التي تحمل علامة [o]. في هذا
في حالة قيامك بتعيين أبعاد البعد المسمى في التوقيع باستخدام $مقاس() كما في
المثال السابق. ومع ذلك، نظرًا لأنه تم وضع علامة على اللغز بـ [o] بدلاً من [t]،
سيتم إضافة أبعاد الخيط إذا لزم الأمر كما لو كان حجم البعد
تحسب من التوقيع وفقا للقواعد المعتادة. هنا مثال من
بدل::الرياضيات

pp_def ("متعددة الجذور"،
بارس => 'كر(ن); سي (ن)؛ [س]rr(م)؛ [س]ri(م)؛'،
RedoDimsCode => 'int sn = $PDL(cr)->dims[0]; $SIZE(م) = sn-1;',

إن ألعاب الإدخال هي الأجزاء الحقيقية والتخيلية للمعاملات المعقدة لـ a
متعدد الحدود. إن التلاعبات الناتجة هي أجزاء حقيقية وخيالية من الجذور. هناك "ن"
جذور لكثيرة الحدود من الرتبة "n" ومثل هذه كثيرة الحدود لها معاملات "n+1" (
zeoreth من خلال "ن" ال). في هذا المثال، سوف يعمل الترابط بشكل صحيح. وهذا هو،
البعد الأول من بيدل الإخراج مع تعديل أبعاده، ولكن خيوط أخرى
سيتم تعيين الأبعاد تمامًا كما لو لم يكن هناك "RedoDimsCode".

خريطة الكتابة معالجة in القادم "أُخر بارس" قسم
غالبًا ما يكون قسم "OtherPars" الذي تمت مناقشته أعلاه بالغ الأهمية عندما تقوم بذلك
واجهة المكتبات الخارجية مع PDL. ولكن في كثير من الحالات المكتبات الخارجية سواء
استخدام أنواع مشتقة أو مؤشرات من أنواع مختلفة.

الطريقة القياسية للتعامل مع هذا في Perl هي استخدام ملف "typemap". تمت مناقشة هذا في
بعض التفاصيل في perlxs في وثائق Perl القياسية. في PP الوظيفة للغاية
مشابه، حتى تتمكن من إنشاء ملف "typemap" في الدليل الذي يوجد به ملف PP الخاص بك
وعندما يتم بناؤه، تتم قراءته تلقائيًا لمعرفة الترجمة المناسبة
بين النوع C والنوع المدمج في Perl.

ومع ذلك، هناك بعض الاختلافات المهمة عن المعالجة العامة للأنواع
في XS. الأول، وربما الأكثر أهمية، هو أنه في الوقت الحالي توجد مؤشرات للأنواع
غير مسموح به في قسم "OtherPars". للتغلب على هذا القيد يجب عليك استخدام
النوع "IV" (شكرًا لجود تايلور لإشارته إلى أن هذا ضروري لقابلية النقل).

ربما يكون من الأفضل توضيح ذلك من خلال مقتطفات من التعليمات البرمجية:

على سبيل المثال، تحتوي الدالة "gsl_spline_init" على إعلان C التالي:

إنت gsl_spline_init(gsl_spline * خدد,
const double xa[], const double ya[], size_t size);

من الواضح أن المصفوفتين "xa" و"ya" مرشحتان لتمريرهما على شكل عبث و
وسيطة "الحجم" هي مجرد طول هذه العبثات بحيث يمكن التعامل معها بواسطة
الماكرو "$SIZE()" في PP. المشكلة هي المؤشر إلى النوع "gsl_spline". الطبيعي
سيكون الحل هو كتابة إعلان "OtherPars" للنموذج

OtherPars => 'gsl_spline *spl'

واكتب ملف "typemap" قصيرًا يتعامل مع هذا النوع. هذا لا يعمل في الوقت الحاضر
لكن! إذن ما عليك فعله هو التغلب على المشكلة قليلاً (وفي بعض النواحي
وهذا أسهل أيضًا!):

الحل هو إعلان "الخط الفاصل" في قسم "OtherPars" باستخدام "قيمة عدد صحيح"،
"الرابع". يؤدي هذا إلى إخفاء طبيعة المتغير من PP وتحتاج بعد ذلك إلى (حسنًا لتجنب ذلك).
تحذيرات المترجم على الأقل!) قم بإجراء تحويل نوع عند استخدام المتغير في التعليمات البرمجية الخاصة بك.
وبالتالي يجب أن يأخذ "OtherPars" النموذج:

OtherPars => 'IV spl'

وعندما تستخدمه في الكود الذي ستكتبه

INT2PTR(gsl_spline *، $COMP(spl))

حيث تم استخدام ماكرو Perl API "INT2PTR" للتعامل مع تحويل المؤشر لتجنبه
تحذيرات ومشاكل المترجم للأجهزة ذات الإصدار المختلط 32 بت و64 بت من لغة بيرل
التكوينات. تجميع هذا معًا كما فعل أندريس جوردان (مع التعديل
باستخدام "IV" بواسطة Judd Taylor) في "gsl_interp.pd" في مصدر التوزيع الذي تحصل عليه:

pp_def('init_meat',
بارس => 'مزدوج x(n); مزدوج ص (ن)؛'،
OtherPars => 'IV spl'،
الكود =>'
gsl_spline_init,( INT2PTR(gsl_spline *, $COMP(spl)), $P(x),$P(y),$SIZE(n)));'
);

حيث قمت بإزالة استدعاء مجمع الماكرو، ولكن هذا من شأنه أن يحجب المناقشة.

الفرق البسيط الآخر مقارنة بمعالجة typemap القياسية في Perl هو ذلك
لا يمكن للمستخدم تحديد مواقع typemap غير القياسية أو أسماء ملفات typemap باستخدام
خيار "TYPEMAPS" في MakeMaker... وبالتالي يمكنك فقط استخدام ملف يسمى "typemap" و/أو
خدعة "الرابع" أعلاه.

أخرى مفيد PP مفاتيح in البيانات عملية التعاريف
لقد سمعت بالفعل عن مفتاح "OtherPars". حاليا، لا يوجد العديد من المفاتيح الأخرى
لعملية البيانات التي ستكون مفيدة في برمجة PP العادية (مهما كانت). في
في الواقع، سيكون من المثير للاهتمام أن نسمع عن حالة تعتقد أنك تحتاج فيها إلى أكثر من ماذا
يتم توفيرها في الوقت الراهن. من فضلك تحدث في إحدى القوائم البريدية لـ PDL. كثير اخر
المفاتيح التي تم التعرف عليها بواسطة "pp_def" مفيدة حقًا لما نسميه فقط شريحة عمليات (انظر
أعلاه أيضاً).

الشيء الوحيد الذي يتم التخطيط له بقوة هو العدد المتغير من الوسائط، والذي سيكون a
صعبة قليلا.

قائمة غير كاملة بالمفاتيح المتاحة:

في المكان
يؤدي تعيين هذا المفتاح إلى وضع علامة على أن الروتين يعمل في مكانه - أي الإدخال والإخراج
البيدلز هي نفسها. مثال على ذلك هو "$a->inplace->sqrt()" (أو "sqrt(inplace($a))").

مكان => 1
يُستخدم عندما يكون الروتين دالة أحادية، مثل "sqrt".

مكان => ['أ']
إذا كان هناك أكثر من خدعة إدخال واحدة، فحدد اسم القطعة التي يمكن أن تكون
تم تغييره في مكانه باستخدام مرجع صفيف.

مكان => ['أ'،'ب']
إذا كان هناك أكثر من وحدة إخراج، فحدد اسم وحدة الإدخال و
piddle الإخراج في مرجع صفيف مكون من عنصرين. ربما ليس هناك حاجة لهذا، ولكن اليسار
في للاكتمال.

في حالة استخدام قيم سيئة، يجب توخي الحذر لضمان انتشار هذه القيم
badflag عندما يتم استخدام inplace؛ النظر في هذا المقتطف من أساسي / سيئ / bad.pd:

pp_def('replacebad',HandleBad => 1,
بارس => 'أ(); [س]ب();',
OtherPars => 'جديد مزدوج'،
إنبلايس => 1،
CopyBadStatusCode =>
'/* نشر العلامة السيئة إذا كانت موجودة وقد تغيرت */
إذا (أ == ب && $ISPDLSTATEBAD(a))
PDL->propogate_badflag( b, 0 );

/* تأكد دائمًا من أن الإخراج "جيد" */
$SETPDLSTATEGOOD(ب);
',


نظرًا لأن هذا الروتين يزيل كافة القيم السيئة، فإن جهاز الإخراج يحمل علامة سيئة
مسح. إذا تم تشغيله في مكانه (لذلك "a == b")، فيجب علينا إخبار جميع أبناء "a"
أنه تم مسح العلامة السيئة (لتوفير الوقت نتأكد من أننا نتصل
"PDL->propogate_badgflag" فقط إذا كان مُدخل الإدخال يحتوي على مجموعة علامات سيئة).

ملاحظة: إحدى الأفكار هي أن وثائق الروتين يمكن أن تكون تلقائية
تم وضع علامة عليه للإشارة إلى أنه يمكن تنفيذه في مكانه، أي شيء مشابه لكيفية تنفيذه
يقوم "HandleBad" بتعيين "BadDoc" إذا لم يتم توفيره (فهذا ليس حلاً مثاليًا).

أخرى PDL :: ص وظائف إلى تقنية مختصرا صفقة تعريف
لقد قمنا حتى الآن بوصف الدالتين "pp_def" و"pp_done". PDL::PP يصدر عددًا قليلًا
وظائف أخرى لمساعدتك في كتابة تعريفات موجزة لحزمة ملحق PDL.

pp_addhdr

في كثير من الأحيان عندما تقوم بواجهة وظائف المكتبة كما في المثال أعلاه، يجب عليك تضمينها
تتضمن لغة C الإضافية ملفات. نظرًا لأن ملف XS يتم إنشاؤه بواسطة PP، فنحن بحاجة إلى بعض الوسائل للقيام بذلك
اجعل PP يقوم بإدراج توجيهات التضمين المناسبة في المكان المناسب في XS الذي تم إنشاؤه
ملف. ولهذه الغاية توجد وظيفة "pp_addhdr". هذه هي أيضًا الوظيفة التي يجب استخدامها
عندما تريد تحديد بعض وظائف C للاستخدام الداخلي بواسطة بعض وظائف XS
(وهي في الغالب وظائف محددة بواسطة "pp_def"). من خلال تضمين هذه الوظائف هنا لك
تأكد من قيام PDL::PP بإدراج الكود الخاص بك قبل النقطة التي توجد بها وحدة XS الفعلية
يبدأ القسم وبالتالي سيتم تركه دون تغيير بواسطة xsubpp (راجع. perlxs و com.perlxstut
صفحات الرجل).

ستكون المكالمة النموذجية

pp_addhdr('
#يشمل /* نحتاج إلى تعريفات XXXX */
#include "libprotos.h" /* نماذج أولية لوظائف المكتبة */
#include "mylocaldecs.h" /* السجلات المحلية */

الفراغ الثابت do_the real_work (PDL_Byte * in، PDL_Byte * out، int n)
{
/* إجراء بعض العمليات الحسابية باستخدام البيانات */
}
')؛

وهذا يضمن أن جميع الثوابت والنماذج الأولية التي تحتاجها سيتم تضمينها بشكل صحيح
أنه يمكنك استخدام الوظائف الداخلية المحددة هنا في "pp_def"، على سبيل المثال:

pp_def ("بارفو"،
بارس => ' أ(ن); [س] ب(ن)'،
الأنواع العامة => ['B']،
Code => ' int ns = $SIZE(n);
do_the_real_work($P(a),$P(b),ns);
',
);

pp_addpm

في كثير من الحالات، يكون رمز PP الفعلي (بمعنى وسيطات استدعاءات "pp_def") جزءًا فقط من
الحزمة التي تقوم بتنفيذها حاليًا. غالبًا ما يكون هناك كود Perl إضافي وXS
الرمز الذي كنت ستكتبه عادةً في ملفات PM وXS والتي أصبحت الآن تلقائيًا
الناتجة عن PP. فكيف يمكن إدخال هذه الأشياء في تلك الملفات التي تم إنشاؤها ديناميكيًا؟
لحسن الحظ، هناك وظيفتان، يطلق عليهما عمومًا "pp_addXXX" لمساعدتك
في القيام بذلك.

لنفترض أن لديك كود Perl إضافيًا يجب أن يدخل في الملف الذي تم إنشاؤه pm-ملف. هذا
يمكن تحقيقه بسهولة باستخدام الأمر "pp_addpm":

pp_addpm(<<'EOD');

= head1 NAME

PDL::Lib::Mylib - واجهة PDL لمكتبة Mylib

=head1 الوصف

تطبق هذه الحزمة واجهة لحزمة Mylib كاملة
دعم الخيوط والفهرسة (انظر L ).

= قص

استخدم ببلوت؛

=head2 use_myfunc
تطبق هذه الوظيفة عملية myfunc على كافة
عناصر إدخال PDL بغض النظر عن الأبعاد
وإرجاع مجموع النتيجة
= قص

الاستخدام الفرعي_myfunc {
بلدي $pdl = التحول؛

myfunc($pdl->clump(-1),($res=null));

إرجاع $res->sum;
}

التخلص من الذخائر المتفجرة

pp_add_exported

ربما تكون قد حصلت على هذه الفكرة. في بعض الحالات، قد ترغب أيضًا في تصدير بياناتك الإضافية
المهام. لتجنب الوقوع في مشكلة مع PP الذي يعبث أيضًا بـEXPORT
المصفوفة التي تخبر PP فقط بإضافة وظائفك إلى قائمة الوظائف المصدرة:

pp_add_exported('use_myfunc gethynx');

pp_add_isa

يعمل الأمر "pp_add_isa" مثل وظيفة "pp_add_exported". الحجج ل
تتم إضافة "pp_add_isa" إلى قائمة @ISA، على سبيل المثال

pp_add_isa('بعض::أخرى::Class');

pp_bless

إذا كان سيتم استخدام إجراءات pp_def كطرق كائن، فاستخدم "pp_bless" لتحديد
الحزمة (أي الفئة) التي لديك pp_defسيتم إضافة طرق إد. على سبيل المثال،
"pp_bless('PDL::MyClass')". الافتراضي هو "PDL" إذا تم حذفه.

pp_addxs

في بعض الأحيان تريد إضافة رمز XS إضافي خاص بك (وهذا لا يرتبط عمومًا بـ
أي مشكلات في الترابط/الفهرسة ولكنها توفر بعض الوظائف الأخرى التي تريد الوصول إليها
من جانب Perl) إلى ملف XS الذي تم إنشاؤه، على سبيل المثال

pp_addxs('','

# تحديد endianness من الجهاز

مادبا
إسبيجينديان()
CODE:
أنا قصيرة غير موقعة؛
PDL_Byte *b;

ط = 42؛ ب = (PDL_Byte*) (باطل*) &i;

إذا (*ب == 42)
ريفال = 0؛
وإلا إذا (*(ب+1) == 42)
ريفال = 1؛
آخر
croak("مستحيل - الآلة ليست كبيرة ولا صغيرة!!\n");
انتاج:
ريتفال
')؛

يجب استخدام "pp_add_exported" و"pp_addxs" بحذر على وجه الخصوص. يستخدم PP
PDL::Exporter، وبالتالي فإن السماح لـ PP بتصدير وظيفتك يعني أنه سيتم إضافتها إلى ملف
القائمة القياسية للوظيفة التي يتم تصديرها افتراضيًا (القائمة المحددة بواسطة علامة التصدير
``:الوظيفة''). إذا كنت تستخدم "pp_addxs"، فيجب ألا تحاول القيام بأي شيء يتضمن الترابط
أو الفهرسة مباشرة. يعد PP أفضل بكثير في إنشاء الكود المناسب من ملف
تعريفات.

pp_add_boot

أخيرًا، قد ترغب في إضافة بعض التعليمات البرمجية إلى قسم BOOT في ملف XS (إذا لم تقم بذلك
تعرف ما هو الاختيار perlxs). يتم ذلك بسهولة باستخدام الأمر "pp_add_boot":

pp_add_boot(<
descrip = mylib_initialize(KEEP_OPEN);

إذا (وصف == NULL)
Croak("لا يمكن تهيئة المكتبة");

GlobalStruc->descrip = descrip;
GlobalStruc->maxfiles = 200;
EOB

pp_export_nothing

افتراضيًا، يقوم PP.pm بوضع كافة العناصر الفرعية المحددة باستخدام الدالة pp_def في الإخراج .pm
قائمة تصدير الملف. يمكن أن يؤدي هذا إلى حدوث مشكلات إذا كنت تقوم بإنشاء كائن فئة فرعية حيث
لا تريد تصدير أي طرق. (أي سيتم استدعاء الأساليب فقط باستخدام
$object->بناء جملة الطريقة).

لهذه الحالات يمكنك الاتصال pp_export_nothing() لمسح قائمة التصدير. مثال (في
نهاية الملف .pd):

pp_export_nothing();
pp_done();

pp_core_importList

بشكل افتراضي، يضع PP.pm "استخدام Core;" سطر في ملف الإخراج .pm. هذا يستورد Core
الأسماء المصدرة إلى مساحة الاسم الحالية، مما قد يؤدي إلى حدوث مشكلات إذا تجاوزت
ركوب إحدى طرق Core في الملف الحالي. ينتهي بك الأمر بتلقي رسائل مثل
"تحذير: تمت إعادة تعريف المجموع الفرعي في الملف subclass.pm" عند تشغيل البرنامج.

في هذه الحالات، يمكن استخدام pp_core_importList لتغيير ما يتم الاستيراد منه
الأساسية. مساء. على سبيل المثال:

pp_core_importList('()')

وهذا من شأنه أن يؤدي إلى

استخدم النواة ()؛

يتم إنشاؤها في ملف الإخراج .pm. قد يؤدي هذا إلى عدم استيراد أي أسماء منها
الأساسية. مساء. وبالمثل، الدعوة

pp_core_importList('qw/ barf /')

من شأنه أن يؤدي إلى

استخدم كور qw/ barf/;

يتم إنشاؤها في ملف الإخراج .pm. قد يؤدي هذا إلى استيراد "barf" فقط
من Core.pm.

pp_setversion

أنا متأكد تمامًا من أن هذا يسمح لك بتعيين ملفات .pm و.xs في وقت واحد.
الإصدارات، وبالتالي تجنب انحراف الإصدار غير الضروري بين الاثنين. لاستخدام هذا، ببساطة لديك
السطر التالي في مرحلة ما في ملف .pd الخاص بك:

pp_setversion('0.0.3');

ومع ذلك، لا تستخدم هذا إذا كنت تستخدم Module::Build::PDL. راجع وثائق هذه الوحدة لـ
تفاصيل.

pp_deprecate_module

إذا تم اعتبار وحدة معينة قديمة، فيمكن استخدام هذه الوظيفة لوضع علامة عليها
إهمال. وهذا له تأثير إصدار تحذير عندما يحاول المستخدم "استخدام" الملف
وحدة. يحمل POD الذي تم إنشاؤه لهذه الوحدة أيضًا إشعارًا بالإيقاف. ال
يمكن تمرير وحدة الاستبدال كوسيطة مثل هذا:

pp_deprecate_module( infavor => "PDL::NewNonDeprecatedModule" );

لاحظ أن الوظيفة تؤثر فقط تحذير وقت التشغيل وPOD.

القيام ب لك PP وظيفة "خاص"


لنفترض أن لديك وظيفة في الوحدة النمطية الخاصة بك تسمى PDL::foo تستخدم PP
وظيفة "bar_pp" للقيام برفع الأحمال الثقيلة. لكنك لا تريد الإعلان عن ذلك "bar_pp"
موجود. للقيام بذلك، يجب عليك نقل وظيفة PP الخاصة بك إلى أعلى ملف الوحدة النمطية الخاص بك، ثم
دعوة

pp_export_nothing()

لمسح قائمة "التصدير". للتأكد من عدم وجود وثائق (حتى مستندات PP الافتراضية).
ولدت، مجموعة

مستند => undef

ولمنع إضافة الوظيفة إلى جدول الرموز، قم بتعيينها

بمفونك => ''

في إعلان pp_def الخاص بك (راجع Image2D.pd للحصول على مثال). هذا سيجعل بشكل فعال
وظيفة PP الخاصة بك "خاصة". ومع ذلك فإنه دائما يمكن الوصول إليه عبر PDL::bar_pp بسبب لغة Perl
تصميم الوحدة. لكن جعلها خاصة سيؤدي إلى ابتعاد المستخدم كثيرًا عما هو عليه
طريقة استخدامه، حتى يتحمل العواقب!

شريحة عملية


يتم توفير قسم تشغيل الشريحة في هذا الدليل باستخدام تدفق البيانات والتقييم البطيء:
عندما تحتاج إليه، اطلب من Tjl أن يكتبه. التسليم خلال أسبوع من تاريخ استلام البريد الإلكتروني
محتمل بنسبة 95% والتسليم خلال أسبوعين محتمل بنسبة 99%.

وعلى أية حال، تتطلب عمليات الشريحة معرفة أكثر حميمية بالعناصر الداخلية لـ PDL
من عمليات البيانات. علاوة على ذلك، فإن تعقيد القضايا المعنية هو
أعلى بكثير من تلك الموجودة في متوسط ​​تشغيل البيانات. إذا كنت تريد أن تقنع
نفسك من هذه الحقيقة نلقي نظرة على أساسي/شرائح/شرائح.pd الملف في PDL
توزيع :-). ومع ذلك، فإن الوظائف التي تم إنشاؤها باستخدام عمليات الشريحة موجودة في
قلب معالجة الفهرس وقدرات تدفق البيانات لـ PDL.

أيضًا، هناك الكثير من المشكلات القذرة المتعلقة بالألعاب الافتراضية والأشياء التي يجب علينا فعلها
تخطي تماما هنا.

شرائح و سيئة القيم
يجب أن تكون عمليات الشريحة قادرة على التعامل مع القيم السيئة (إذا تم تجميع الدعم في PDL).
أسهل شيء يمكنك القيام به هو النظر أساسي/شرائح/شرائح.pd لنرى كيف يعمل هذا.

إلى جانب "BadCode"، يوجد أيضًا مفتاحا "BadBackCode" و"BadRedoDimsCode" لـ
"pp_def". ومع ذلك، ينبغي لأي "EquivCPOffsCode". ليست بحاجة إلى تغيير، لأن أي تغييرات هي
تم استيعابها في تعريف الماكرو "$EQUIVCPOFFS()" (أي يتم التعامل معه
تلقائيًا عن طريق PDL::PP>.

A قليل ملاحظات on جاري الكتابة a تشريح نمط...
تصف الفقرات القليلة التالية كتابة روتين تشريح جديد ("النطاق")؛ أي
الأخطاء هي CED. (--26 أغسطس 2002)

معالجة of "تحذير" و "يتقيأ" in PP رمز


لطباعة رسائل التحذير أو الإجهاض/الموت، يمكنك استدعاء "warn" أو "barf" من PP
شفرة. ومع ذلك، يجب أن تدرك أنه تم إعادة تعريف هذه الاستدعاءات باستخدام لغة C
وحدات ماكرو المعالج المسبق إلى "PDL->barf" و"PDL->تحذير". تم وضع هذه التعريفات من أجل
يمنعك من الاتصال عن غير قصد بـ "تحذير" أو "barf" الخاص بـ Perl مباشرةً، مما قد يتسبب في حدوث ذلك
أخطاء segfaults أثناء pthreading (أي خيوط المعالجة المتعددة).

ستقوم إصدارات "barf" و"warn" الخاصة بـ PDL بوضع رسائل التحذير أو الحظر في قائمة الانتظار حتى بعد ذلك
اكتمل pthreading، ثم قم باستدعاء إصدارات Perl من هذه الإجراءات.

راجع PDL::ParallelCPU لمزيد من المعلومات حول pthreading.

مفيدة الروتين


هيكل PDL "الأساسي"، المحدد في الأساسية / الأساسية / pdlcore.h.PL، يحتوي على مؤشرات إلى أ
عدد من الإجراءات التي قد تكون مفيدة لك. غالبية هذه الإجراءات الروتينية تتعامل معها
التلاعب بالألعاب، لكن بعضها أكثر عمومية:

PDL->qsort_B( PDL_Byte *xx, int a, int b )
قم بفرز المصفوفة "xx" بين الفهرسين "a" و"b". هناك أيضًا إصدارات لـ
أنواع بيانات PDL الأخرى، مع postfix "_S" و"_U" و"_L" و"_F" و"_D". أي وحدة تستخدم
يجب أن يضمن هذا تحميل "PDL::Ufunc".

PDL->qsort_ind_B( PDL_Byte *xx, int *ix, int a, int b )
أما بالنسبة لـ "PDL->qsort_B"، لكن هذه المرة قم بفرز المؤشرات بدلاً من البيانات.

الروتين "med2d" في ليب/Image2D/image2d.pd يوضح كيفية استخدام مثل هذه الإجراءات.

يصنع لأي PP FILES


إذا كنت ستقوم بإنشاء حزمة من ملف PP الخاص بك (امتدادات الملفات النموذجية هي
".pd" أو ".pp" للملفات التي تحتوي على كود PP) فمن الأسهل والأكثر أمانًا المغادرة
إنشاء الأوامر المناسبة لملف Makefile. في ما يلي سوف نوضح
التنسيق النموذجي لـ Perl Makefile لإنشاء الحزمة الخاصة بك وتثبيتها تلقائيًا منها
وصف في ملف PP. معظم القواعد لإنشاء ملفات xs وpm وغيرها من الملفات المطلوبة
من ملف PP تم تعريفها مسبقًا في حزمة PDL::Core::Dev. علينا فقط أن
أخبر MakeMaker باستخدامه.

في معظم الحالات، يمكنك تحديد ملف Makefile الخاص بك مثل

# Makefile.PL لحزمة محددة بواسطة كود PP.

استخدم PDL::Core::Dev; # التقاط المرافق التطويرية
استخدام ExtUtils :: MakeMaker ؛

$package = ["mylib.pd",Mylib,PDL::Lib::Mylib];
%hash = pdlpp_stdargs($package);
$hash{OBJECT} .= ' extra_Ccode$(OBJ_EXT) ';
$hash{clean}->{FILES} .= ' todelete_Ccode$(OBJ_EXT) ';
$hash{'VERSION_FROM'} = 'mylib.pd';
WriteMakefile(%hash);

sub MY::postamble { pdlpp_postamble($package); }

هنا، القائمة في $package هي: أولاً: اسم ملف مصدر PP، ثم البادئة لـ
الملفات المنتجة وأخيرا اسم الحزمة بالكامل. يمكنك تعديل التجزئة في أي شيء
بالطريقة التي تريدها ولكن سيكون من المعقول البقاء ضمن بعض الحدود بحيث تكون الحزمة الخاصة بك
سيستمر العمل مع الإصدارات الأحدث من PDL.

إذا كنت لا تريد استخدام الوسائط المعبأة مسبقًا، فإليك وسيطة عامة Makefile.PL ذلك ما تستطيع
التكيف مع احتياجاتك الخاصة:

# Makefile.PL لحزمة محددة بواسطة كود PP.

استخدم PDL::Core::Dev; # التقاط المرافق التطويرية
استخدام ExtUtils :: MakeMaker ؛

اكتب مايفيل (
'NAME' => 'PDL::Lib::Mylib',
'VERSION_FROM' => 'mylib.pd',
'TYPEMAPS' => [&PDL_TYPEMAP()]،
'OBJECT' => 'mylib$(OBJ_EXT) extra_Ccode$(OBJ_EXT)',
'PM' => { 'Mylib.pm' => '$(INST_LIBDIR)/Mylib.pm'},
'INC' => &PDL_INCLUDE(), # أضف تضمين dirs كما هو مطلوب بواسطة lib الخاص بك
'LIBS' => [''], # أضف توجيهات الارتباط حسب الضرورة
'نظيف' => {'ملفات' =>
'Mylib.pm Mylib.xs Mylib$(OBJ_EXT)
extra_Ccode$(OBJ_EXT)'},
);

# إضافة قاعدة genpp؛ سيؤدي هذا إلى استدعاء PDL::PP في ملف PP الخاص بنا
# الوسيطة هي مرجع مصفوفة حيث يحتوي المصفوفة على ثلاثة عناصر سلسلة:
# arg1: اسم الملف المصدر الذي يحتوي على كود PP
# arg2: الاسم الأساسي لملفات xs وpm التي سيتم إنشاؤها
# arg3: اسم الحزمة التي سيتم إنشاؤها
sub MY::postamble { pdlpp_postamble(["mylib.pd",Mylib,PDL::Lib::Mylib]); }

لجعل الحياة أسهل، يحدد PDL::Core::Dev الدالة "pdlpp_stdargs" التي ترجع
تجزئة ذات قيم افتراضية يمكن تمريرها (إما مباشرة أو بعد المناسبة
التعديل) لاستدعاء WriteMakefile. حاليًا، يقوم "pdlpp_stdargs" بإرجاع علامة التجزئة حيث
يتم تعبئة المفاتيح على النحو التالي:

(
'NAME' => $mod،
'TYPEMAPS' => [&PDL_TYPEMAP()]،
'OBJECT' => "$pref\$(OBJ_EXT)"،
PM => {"$pref.pm" => "\$(INST_LIBDIR)/$pref.pm"},
MAN3PODS => {"$src" => "\$(INST_MAN3DIR)/$mod.\$(MAN3EXT)"},
'INC' => &PDL_INCLUDE(),
'LIBS' => ['']،
'نظيف' => {'FILES' => "$pref.xs $pref.pm $pref\$(OBJ_EXT)"},
)

هنا، $src هو اسم الملف المصدر مع رمز PP، $pref البادئة التي تم إنشاؤها
ملفات .pm و.xs و$mod اسم وحدة الامتداد المراد إنشاؤها.

الداخلية


تتكون الأجزاء الداخلية للإصدار الحالي من جدول كبير يعطي القواعد
وبموجبها تترجم الأشياء والفرعيات التي تنفذ هذه القواعد.

لاحقًا، سيكون من الجيد جعل الجدول قابلاً للتعديل من قبل المستخدم بحيث يكون مختلفًا
يمكن تجربة الأشياء.

[تعليق ميتا: نأمل أن يكون هناك المزيد في المستقبل؛ حاليًا، سيكون أفضل رهان لك
لقراءة الكود المصدري :-( أو اسأل في القائمة (جرب الأخير أولاً) ]

الزائدة الدودية A: بعض مفاتيح معروف by PDL :: ص


ما لم يُنص على خلاف ذلك، تكون الوسائط عبارة عن سلاسل. المفاتيح التي تحمل علامة (سيئة) هي فقط
يُستخدم إذا تم تجميع دعم القيمة السيئة في PDL.

بارس
تحديد توقيع وظيفتك

OtherPars
الحجج التي ليست pdls. الافتراضي: لا شيء. هذه قائمة مفصولة بفاصلة منقوطة
الوسائط، على سبيل المثال، "OtherPars=>'int k; double value; char* fd'". راجع $COMP(x) وأيضًا
نفس الإدخال في الملحق ب.

رمز
الكود الفعلي الذي ينفذ الوظيفة؛ عدة وحدات ماكرو PP ووظائف PP
يتم التعرف عليها في قيمة السلسلة

هاندلباد (سيء)
إذا تم تعيينه على 1، فمن المفترض أن يدعم الروتين القيم السيئة والتعليمات البرمجية الموجودة في BadCode
يتم استخدام المفتاح في حالة وجود قيم سيئة؛ كما أنه يقوم بإعداد الأشياء بحيث يكون "$ISBAD()"
الخ ويمكن استخدام وحدات الماكرو. إذا تم التعيين على 0، فاجعل الروتين يطبع تحذيرًا في حالة وجوده
تم ضبط علامات الإدخال السيئة على أدوات الإدخال.

كود سيء (سيء)
قم بإعطاء الكود الذي سيتم استخدامه في حالة وجود قيم سيئة في أدوات الإدخال. تستخدم فقط
إذا كان "HandleBad => 1".

أنواع عامة
مرجع مصفوفة. قد يحتوي المصفوفة على أي مجموعة فرعية من السلاسل المكونة من حرف واحد `B'،
`S'، `U'، `L'، `Q'، `F' و `D'، والتي تحدد الأنواع التي ستقبلها عمليتك.
ومعنى كل نوع هو:

ب - البايت الموقع (أي الحرف الموقع)
S - علامة قصيرة (عدد صحيح ثنائي البايت)
U - قصير غير موقع
L - علامة طويلة (عدد صحيح رباعي البايت، int على أنظمة 32 بت)
Q - علامة طويلة طويلة (عدد صحيح بثمانية بايت)
ف – تعويم
د – مزدوج

وهذا مفيد جدًا (ومهم!) عند التعامل مع مكتبة خارجية. تقصير:
[qw/BSULQFD/]

في المكان
قم بتمييز الوظيفة بأنها قادرة على العمل في مكانها.

Inplace => 1 if Pars => 'a(); [س] ب ()؛'
Inplace => ['a'] if Pars => 'a(); ب()؛ [س]ج ()؛'
Inplace => ['a','b'] if Pars => 'a(); ب()؛ [س]ج ()؛ [س]د ()؛'

في حالة استخدام قيم سيئة، يجب توخي الحذر لضمان انتشار هذه القيم
badflag عندما يتم استخدام inplace؛ على سبيل المثال، راجع رمز "replacebad" في
أساسي / سيئ / bad.pd.

يستخدم Doc لتحديد سلسلة وثائق بتنسيق Pod. راجع PDL::Doc للحصول على معلومات حول
اتفاقيات توثيق PDL. ملحوظة: في الحالة الخاصة التي تكون فيها سلسلة PP 'Doc'
يتم استخدام سطر واحد ضمنيًا للإشارة السريعة والوثائق!

إذا تم حذف حقل Doc، فسيقوم PP بإنشاء وثائق افتراضية (بعد كل ما يعرفه
عن التوقيع).

إذا كنت تريد حقًا عدم توثيق الوظيفة بأي شكل من الأشكال في هذه المرحلة (على سبيل المثال.
لروتين داخلي، أو لأنك تفعل ذلك في مكان آخر من الكود) بشكل صريح
حدد "Doc=>undef".

بادوك (سيء)
يحتوي على النص الذي تم إرجاعه بواسطة الأمر "badinfo" (في "perldl") أو رمز التبديل "-b".
إلى البرنامج النصي شل "pdldoc". في كثير من الحالات، لن تحتاج إلى تحديد ذلك، منذ ذلك الحين
يمكن إنشاء المعلومات تلقائيًا بواسطة PDL::PP. لكن بما يتناسب مع الكمبيوتر
النص الذي تم إنشاؤه، هو متقلب إلى حد ما؛ قد يكون من الأفضل أن تفعل ذلك بنفسك!

NoPthread
علامة اختيارية للإشارة إلى وظيفة PDL ليست استخدم خيوط المعالج (أي
pthreads أو POSIX Threads) لتقسيم العمل عبر مراكز وحدة المعالجة المركزية المتعددة. هذا الخيار هو
يتم تعيينه عادةً على 1 إذا كانت وظيفة PDL الأساسية ليست آمنة لمؤشر الترابط. إذا كان هذا الخيار
غير موجود، فمن المفترض أن تكون الوظيفة آمنة لمؤشر الترابط. ينطبق هذا الخيار فقط
إذا تم تجميع PDL مع تمكين سلاسل POSIX.

رمز PM
تسمح لك وظائف PDL بتمرير الحقل الذي تريد حفظ الإخراج فيه. هذا
يعد مفيدًا لأنه يمكنك تخصيص أداة إخراج مرة واحدة وإعادة استخدامها عدة مرات؛ ال
سيكون البديل أن يقوم PDL بإنشاء ملف جديد في كل مرة، مما قد يؤدي إلى إضاعة الحساب
دورات أو، على الأرجح، ذاكرة الوصول العشوائي. هذه المرونة الإضافية تأتي على حساب المزيد
التعقيد: يجب على PDL::PP كتابة وظائف ذكية بما يكفي لحساب عدد
تم تمرير الوسائط إليها وإنشاء ألعاب جديدة بسرعة، ولكن فقط إذا كنت تريدها.

PDL::PP ذكي بما فيه الكفاية للقيام بذلك، ولكن هناك قيود على ترتيب الوسيطات و
الاعجاب. إذا كنت تريد وظيفة أكثر مرونة، فيمكنك كتابة جانب Perl الخاص بك
المجمع وتحديده في مفتاح PMCode. السلسلة التي تقدمها يجب (ينبغي)
حدد دالة Perl باسم يطابق ما أعطيته لـ pp_def في الأول
مكان. عندما ترغب في استدعاء الدالة التي تم إنشاؤها بواسطة PP في النهاية، فسوف تحتاج إلى ذلك
قم بتزويد جميع العبث بالترتيب الدقيق المحدد في التوقيع: تلاعبات الإخراج هي
ليست اختيارية، ولن تُرجع الدالة التي تم إنشاؤها بواسطة PP أي شيء. المبهم
الاسم الذي ستتصل به هو __int.

أعتقد أن هذه الوثائق تحتاج إلى مزيد من التوضيح، ولكن هذا يجب أن يتم.
:-(

PMFunc
عندما يقوم pp_def بإنشاء وظائف، فإنه يحددها عادةً في حزمة PDL. ثم،
في ملف .pm الذي ينشئه للوحدة النمطية الخاصة بك، فإنه عادةً ما يضيف سطرًا
يقوم بشكل أساسي بنسخ تلك الوظيفة إلى جدول رموز الحزمة الحالية باستخدام الكود
التي تبدو كالتالي:

*func_name = \&PDL::func_name;

إنها أذكى قليلاً من ذلك (فهي تعرف متى يتم تغليف هذا النوع من الأشياء في ملف
BEGIN block، على سبيل المثال، وإذا حددت شيئًا مختلفًا لـ pp_bless)، لكن
هذا هو جوهر الأمر. إذا كنت لا تهتم باستيراد الوظيفة إلى ملفك الحالي
جدول رموز الحزمة، يمكنك تحديده

بمفونك => '',

ليس لدى PMFunc أي آثار جانبية أخرى، لذا يمكنك استخدامه لإدراج كود Perl التعسفي
في الوحدة النمطية الخاصة بك إذا أردت. ومع ذلك، يجب عليك استخدام pp_addpm إذا كنت تريد إضافة لغة Perl
رمز إلى الوحدة النمطية الخاصة بك.

الزائدة الدودية B: PP وحدات الماكرو و وظائف


وحدات الماكرو
يتم استخدام وحدات الماكرو التي تحمل علامة (سيئ) فقط إذا تم تجميع دعم القيمة السيئة في PDL.

$variablename_from_sig()
الوصول إلى pdl (بالاسم) الذي تم تحديده في التوقيع

$COMP(x)
الوصول إلى قيمة في بنية البيانات الخاصة لهذا التحويل (تستخدم بشكل أساسي لـ
استخدم الوسيطة المحددة في قسم "OtherPars")

حجم $(ن)
تم استبداله في وقت التشغيل بالحجم الفعلي لـ a عين البعد (كما هو محدد في
توقيع)

$نوعي()
تم استبداله بالنوع C الذي يساوي نوع وقت التشغيل للعملية

$P(a) وصول المؤشر إلى PDL المسمى "a" في التوقيع. مفيد للتواصل مع C
وظائف

$PP(a) وصول المؤشر الفعلي إلى pdl "a"; أساسا للاستخدام الداخلي

$TXXX(بديل،بديل)
بدائل التوسعة وفقًا لنوع العملية في وقت التشغيل، حيث يمثل XXX بعضًا منها
السلسلة المطابقة لـ "/[BSULFD+]/".

$PDL(أ)
قم بإرجاع مؤشر إلى بنية بيانات pdl (pdl *) الخاصة بالـ piddle "a"

$ISBAD(a()) (سيء)
يُرجع صحيحًا إذا كانت القيمة المخزنة في "a()" تساوي القيمة السيئة لهذا العرض.
يتطلب تعيين "HandleBad" على 1.

$ISGOOD(a()) (سيء)
يُرجع صحيحًا إذا كانت القيمة المخزنة في "a()" لا تساوي القيمة السيئة لذلك
عبث. يتطلب تعيين "HandleBad" على 1.

$SETBAD(a()) (سيء)
يضبط "a()" لتساوي القيمة السيئة لهذا اللغز. يتطلب تعيين "HandleBad".
ل1.

وظائف
"حلقة (DIMS) %{ ... %}"
حلقة فوق الأبعاد المسماة؛ يتم إنشاء الحدود تلقائيًا بواسطة PP

"حلقة الترابط %{ ... %}"
أرفق التعليمات البرمجية التالية في حلقة الموضوع

"الأنواع (الأنواع) %{ ... %}"
قم بتنفيذ الكود التالي إذا كان نوع العملية هو أي من "TYPES"

الزائدة الدودية C: وظائف مستورد by PDL :: ص


يتم استيراد عدد من الوظائف عند "استخدام PDL::PP". وتشمل هذه الوظائف التي
التحكم في كود C أو XS الذي تم إنشاؤه، والوظائف التي تتحكم في كود Perl الذي تم إنشاؤه، و
الوظائف التي تتعامل مع الحزم وجداول الرموز التي يتم إنشاء التعليمات البرمجية فيها.

توليد C و XS رمز
الغرض الرئيسي من PDL::PP هو تسهيل قيامك بلف محرك الترابط حول ملفك
رمز C الخاص بك، ولكن يمكنك القيام ببعض الأشياء الأخرى أيضًا.

pp_def
يستخدم لالتفاف محرك الترابط حول كود C الخاص بك. تقريبا كل هذه الوثيقة
يناقش استخدام pp_def.

pp_done
يشير إلى أنك انتهيت من استخدام PDL::PP وأنه يجب إنشاء ملفات .xs و.pm الخاصة به
بناءً على وظائف pp_* الأخرى التي قمت باستدعائها. هذه الوظيفة لا تأخذ أي
الحجج.

pp_addxs
يتيح لك هذا إضافة رمز XS إلى ملف .xs الخاص بك. يعد هذا مفيدًا إذا كنت تريد إنشاء Perl-
الوظائف التي يمكن الوصول إليها والتي تستدعي كود C ولكن لا يمكنها أو لا ينبغي لها استدعاء الترابط
محرك. XS هي الوسيلة القياسية التي يمكنك من خلالها تغليف كود C الذي يمكن الوصول إليه بواسطة Perl. أنت تستطيع
تعلم المزيد في perlxs.

pp_add_boot
تضيف هذه الوظيفة أي سلسلة تمررها إلى قسم XS BOOT. قسم التمهيد
هو رمز C الذي يتم استدعاؤه بواسطة Perl عند تحميل الوحدة النمطية الخاصة بك ويكون مفيدًا لـ
التهيئة التلقائية. يمكنك معرفة المزيد حول XS وقسم BOOT على perlxs.

pp_addhdr
يضيف كود pure-C إلى ملف XS الخاص بك. يتم تنظيم ملفات XS بحيث يجب أن يكون كود C خالصًا
تأتي قبل مواصفات XS. هذا يسمح لك بتحديد رمز C هذا.

pp_boundscheck
يتحقق PDL عادةً من حدود عمليات الوصول الخاصة بك قبل القيام بها. يمكنك تحويل ذلك
تشغيل أو إيقاف تشغيله في وقت التشغيل عن طريق تعيين MyPackage::set_boundscheck. تتيح لك هذه الوظيفة
لإزالة مرونة وقت التشغيل و أبدا القيام بفحص الحدود. كما أنها ترجع
حالة التحقق من الحدود الحالية إذا تم استدعاؤها دون أي وسيطات.

ملحوظة: لم أجد أي شيء يتعلق بفحص الحدود في الوثائق الأخرى. الذي - التي
يحتاج إلى معالجة.

توليد بيرل رمز
تتيح لك العديد من الوظائف التي يتم استيرادها عند استخدام PDL::PP تعديل محتويات الملف
تم إنشاء ملف .pm. بالإضافة إلى pp_def و pp_done، دور هذه الوظائف هو
في المقام الأول لإضافة تعليمات برمجية إلى أجزاء مختلفة من ملف .pm الذي تم إنشاؤه.

pp_addpm
يضيف رمز Perl إلى ملف .pm الذي تم إنشاؤه. PDL::PP يتتبع في الواقع ثلاثة
أقسام مختلفة من التعليمات البرمجية التي تم إنشاؤها: الأعلى والأوسط والأسفل. يمكنك إضافة
رمز Perl إلى القسم الأوسط باستخدام نموذج الوسيطة الواحدة، حيث تكون الوسيطة هي
كود بيرل الذي تريد توفيره. في النموذج ثنائي الوسيطة، الوسيطة الأولى هي
تجزئة مجهولة بمفتاح واحد فقط يحدد مكان وضع الوسيطة الثانية،
وهي السلسلة التي تريد إضافتها إلى ملف .pm. التجزئة هي واحدة من هذه
ثلاثة:

{في => 'الأعلى'}
{في => 'الوسط'}
{في => "بوت"}

فمثلا:

pp_addpm({At => 'Bot'}, <

=head1 بعض الوثائق

أعلم أنني أكتب هذا في منتصف ملفي، لكنه سينتهي
القاع.

= قص

POD

تحذير: إذا قمت، في منتصف ملف .pd، بوضع وثائق مخصصة لملف .pd
أسفل جرابك، سوف تخلط بين CPAN تمامًا. ومن ناحية أخرى، إذا كان في
في منتصف ملف .pd الخاص بك، يمكنك إضافة بعض أكواد Perl المخصصة للجزء السفلي أو العلوي من ملفك
ملف .pm، ليس لديك سوى إرباك نفسك. :-)

pp_beginwrap
يضيف التفاف كتلة BEGIN. ومع ذلك، يمكن تغليف بعض الإعلانات في كتل BEGIN
السلوك الافتراضي هو عدم وجود مثل هذا الالتفاف.

pp_addbegin
يضبط التعليمات البرمجية المراد إضافتها إلى أعلى ملف .pm الخاص بك، حتى أعلى التعليمات البرمجية التي تحددها
مع "pp_addpm({At => 'Top'}, ...)". على عكس pp_addpm، يؤدي استدعاء هذا إلى الكتابة فوق أي شيء
كان هناك من قبل. بشكل عام، ربما لا ينبغي عليك استخدامه.

تتبع الشحن لاين أرقام
عندما تحصل على أخطاء في الترجمة، إما من التعليمات البرمجية المشابهة لـ C أو من تعليمات Perl الخاصة بك، فقد يساعدك ذلك
لإعادة هذه الأخطاء إلى أرقام الأسطر في الملف المصدر الذي حدث فيه الخطأ
حدث.

pp_line_numbers
يأخذ رقم سطر وسلسلة من التعليمات البرمجية (طويلة عادةً). يجب أن يكون رقم السطر
تشير إلى السطر الذي يبدأ منه الاقتباس. هذا عادةً هو "__LINE__" الخاص بـ Perl
حرفيًا، إلا إذا كنت تستخدم المستندات الوراثية، وفي هذه الحالة يكون "__LINE__ + 1". ال
تحتوي السلسلة التي تم إرجاعها على توجيهات #line متفرقة لمساعدة المترجم في الإبلاغ عن الأخطاء
على الخط الصحيح.

تعديل القادم رمز طاولات و تصدير سلوك
يقوم PDL::PP عادةً بتصدير جميع الوظائف التي تم إنشاؤها باستخدام pp_def، وعادةً ما يقوم بتثبيتها
في جدول رموز PDL. ومع ذلك، يمكنك تعديل هذا السلوك باستخدام هذه الوظائف.

pp_bless
يضبط الحزمة (جدول الرموز) التي يُضاف إليها رمز XS. الافتراضي هو PDL،
وهو عموما ما تريد. إذا استخدمت البركة الافتراضية وقمت بإنشاء ملف
وظيفة myfunc، فيمكنك القيام بما يلي:

$piddle->myfunc();
PDL::myfunc($piddle, );

من ناحية أخرى، إذا قمت بمباركة وظائفك في حزمة أخرى، فلن تتمكن من الاستدعاء
لهم كطرق PDL، ويجب استدعاءهم على النحو التالي:

MyPackage::myfunc($piddle, );

بالطبع، يمكنك دائمًا استخدام مفتاح PMFunc لإضافة وظيفتك إلى رمز PDL
الجدول، ولكن لماذا تفعل ذلك؟

pp_add_isa
يضيف إلى قائمة الوحدات التي منها وحدة يرث. القائمة الافتراضية هي

كيو دبليو (PDL::مصدر DynaLoader)

pp_core_importlist
يوجد في الجزء العلوي من ملف .pm الذي تم إنشاؤه سطر يشبه هذا:

استخدم PDL::Core؛

يمكنك تعديل ذلك عن طريق تحديد سلسلة إلى pp_core_importlist. على سبيل المثال،

pp_core_importlist('::Blarg');

سوف يؤدي إلى

استخدم PDL::Core::Blarg;

يمكنك استخدام هذا، على سبيل المثال، لإضافة قائمة رموز لاستيرادها من PDL::Core. ل
مثال:

pp_core_importlist(" ':داخلي'");

سيؤدي إلى بيان الاستخدام التالي:

استخدم PDL::Core ':داخلي'؛

pp_setversion
يضبط إصدار الوحدة النمطية الخاصة بك. يجب أن يكون الإصدار متناسقًا بين ‎.xs و‎.pm
الملف، ويتم استخدامه للتأكد من أن مكتبات Perl الخاصة بك لا تعاني من الإصدار
انحراف.

pp_add_exported
يضيف إلى قائمة التصدير أي أسماء تعطيها له. الوظائف التي تم إنشاؤها باستخدام pp_def
تتم إضافتها تلقائيا إلى القائمة. هذه الوظيفة مفيدة إذا قمت بتعريف أي لغة Perl
الوظائف باستخدام pp_addpm أو pp_addxs التي تريد تصديرها أيضًا.

pp_export_nothing
يؤدي هذا إلى إعادة تعيين قائمة الرموز المصدرة إلى لا شيء. ربما يكون من الأفضل تسمية هذا
"pp_export_clear"، حيث يمكنك إضافة الرموز المصدرة بعد الاتصال
"pp_export_nothing". عند الاتصال قبل الاتصال بـ pp_done مباشرة، فهذا يضمن أن ملفك
لا تقوم الوحدة بتصدير أي شيء، على سبيل المثال، إذا كنت تريد فقط أن يستخدم المبرمجون ملفك
وظائف كأساليب.

استخدم PDL::PPp عبر الإنترنت باستخدام خدمات onworks.net


خوادم ومحطات عمل مجانية

قم بتنزيل تطبيقات Windows و Linux

أوامر لينكس

Ad




×
الإعلانات
❤️تسوق أو احجز أو اشترِ هنا - بدون تكلفة، مما يساعد على إبقاء الخدمات مجانية.