זוהי הפקודה PDL::APIp שניתן להריץ בספק האירוח החינמי של OnWorks באמצעות אחת מתחנות העבודה המקוונות החינמיות שלנו כגון Ubuntu Online, Fedora Online, אמולטור מקוון של Windows או אמולטור מקוון של MAC OS.
תָכְנִית:
שֵׁם
PDL::API - יצירת פידלים מקוד Perl ו-C/XS
תיאור
ספר בישול פשוט כיצד ליצור פידלס באופן ידני. הוא מכסה גם את Perl וגם את C/XS.
רמה. בנוסף, הוא מתאר את שגרות הליבה של PDL אליהן ניתן לגשת מאחרים
מודולים. שגרות אלו מגדירות בעצם את ממשק ה-API של PDL. אם אתה צריך לגשת ל-piddles מ-
C/XS כנראה שאתם צריכים לדעת על הפונקציות האלה.
תַקצִיר
השתמש ב-PDL;
תת-mkmypiddle {
...
}
יוצרים a בלול באופן ידני החל מ- פרל
לפעמים אתה רוצה ליצור פידל באופן ידני מנתונים בינאריים. אתה יכול לעשות זאת ב
רמת פרל. דוגמאות בהפצה כוללות חלק משגרות ה-IO. הקוד
הקטע למטה ממחיש את השלבים הנדרשים.
השתמש קרפיון;
תת-mkmypiddle {
שלי $class = shift;
ה-$pdl שלי = $class->new;
$pdl->set_datatype($PDL_B);
ה-@dims שלי = (1,3,4);
הגודל שלי = 1;
עבור (@dims) { $size *= $_ }
$pdl->setdims([@dims]);
הקובץ $dref שלי = $pdl->get_dataref();
# קרא נתונים ישירות מהקובץ
פתח את הקובץ שלי, '
הערך $len שלי = $size*PDL::Core::howbig($pdl->get_datatype);
croak "לא הצליח לקרוא מספיק נתונים" אם
read( $file, $$dref, $len) != $len;
סגור את הקובץ $;
$pdl->upd_data();
החזר $pdl;
}
יוצרים a בלול in C
הדוגמה הבאה יוצרת פידל ברמת C. אנו משתמשים במודול "Inline" אשר
זוהי באמת הדרך הנכונה לממשק בין פרל ל-C בימינו. שימו לב לשימוש ב-"PDL_INCLUDE",
הפונקציות "PDL_TYPEMAP", "PDL_AUTO_INCLUDE" ו-"PDL_BOOT" שיובאו מ-
"PDL::Core::Dev". הם משמשים יחד עם קריאה ל-Inline Config כדי להבטיח ש
מפת הסוגים של PDL, קבצי ההכללה של PDL ושגרות הליבה של PDL נמצאות במהלך
קומפילציה וביצוע בזמן ריצה מאוחר יותר.
השתמש ב-PDL::LiteF;
השתמש ב-PDL::Core::Dev;
# תרגיל את בנאי הפידלים ב-C שלנו
הדפס $a->info,"\n";
# הסיבה לקריאה זו להגדרות מוסברת להלן
השתמש ב-Inline C => תצורה =>
INC => &PDL_INCLUDE, # ודא שאנו מוצאים את pdlcore.h וכו'
TYPEMAPS => &PDL_TYPEMAP, # השתמש במפת הסוגים של PDL
AUTO_INCLUDE => &PDL_AUTO_INCLUDE, # הצהרות גלובליות וכלולים
BOOT => &PDL_BOOT; # קוד אתחול לטעינת מבנה הליבה
השתמש ב-C מוטבע;
Inline->init; # שימושי אם ברצונך להיות מסוגל לטעון את הסקריפט הזה
__נְתוּנִים__
__C__
pdl סטטי* new_pdl(int datatype, PDL_Indx dims[], int ndims)
{
pdl *p = PDL->pdlnew();
PDL->setdims(p, dims, ndims); /* set dims */
p->סוג נתונים = סוג נתונים; /* וסוג נתונים */
PDL->allocdata (p); /* הקצה את נתח הנתונים */
החזר את p;
}
pdl* myfloatseq()
{
PDL_Indx dims[] = {5,5,5};
pdl *p = new_pdl(PDL_F,dims,3);
PDL_Float *נתונים = (PDL_Float *) p->נתונים;
PDL_Indx i; /* המימדים עשויים להיות 64 סיביות */
עבור (i=0;i<5*5*5;i++)
dataf[i] = i; /* יש לאתחל את הנתונים! */
החזר את p;
}
גלישה שֶׁלְךָ שֶׁלוֹ נתונים אל תוך a בלול
לפעמים אתה מקבל נתח נתונים ממקור אחר, למשל ממעבד תמונה
ספרייה וכו'. כל מה שאתה רוצה לעשות במקרה כזה הוא לעטוף את הנתונים שלך לתוך מבנה piddle ב-
רמת C. דוגמאות המשתמשות בגישה זו ניתן למצוא במודולי IO (כאשר FastRaw
ו-FlexRaw משתמשים בו לגישה באמצעות mmapped) ומודול Gimp Perl (שמשתמש בו כדי לעטוף את Gimp
אזורי פיקסלים ל-piddles). הסקריפט הבא מדגים דוגמה פשוטה:
השתמש ב-PDL::LiteF;
השתמש ב-PDL::Core::Dev;
השתמש ב-PDL::Graphics::PGPLOT;
$b = mkpiddle();
הדפס $b->info,"\n";
תמונה 1 $b;
השתמש ב-Inline C => תצורה =>
כולל => &PDL_INCLUDE,
TYPEMAPS => &PDL_TYPEMAP,
AUTO_INCLUDE => &PDL_AUTO_INCLUDE,
אתחול => &PDL_BOOT;
השתמש ב-C מוטבע;
מוטבע->init;
__נְתוּנִים__
__C__
/* עוטפים נתח נתונים שסופק על ידי המשתמש לתוך פידל
* עליך לציין את המידות (dims,ndims) ו-
* סוג הנתונים (הקבועים עבור סוגי הנתונים מוצהרים
* ב-pdl.h; לדוגמה PDL_B עבור סוג בייט, וכו')
*
* כאשר הפידל שנוצר 'npdl' נהרס על
* בצד פרל הפונקציה הועברה כ-'delete_magic'
הפרמטר ייקרא עם המצביע למבנה pdl
* והטיעון 'דלפאראם'.
* זה נותן לך הזדמנות לבצע כל ניקיון
* שזה הכרחי. לדוגמה, ייתכן שתצטרך
* קריאה מפורשת לפונקציה כדי לפנות את המשאבים
* המשויך למצביע הנתונים שלך.
* לכל הפחות, 'delete_magic' צריך לאפס את מצביע הנתונים של ה-piddle:
*
* void delete_mydata(pdl* pdl, int param)
* {
* pdl->נתונים = 0;
* }
* pdl *p = pdl_wrap(הנתונים שלי, PDL_B, dims, ndims, delete_mydata,0);
*
* pdl_wrap מחזיר את המצביע ל- pdl
* שנוצר.
*/
typedef void (*DelMagic)(pdl *, int param);
סטטי חלל default_magic(pdl *p, int pa) { p->נתונים = 0; }
pdl static* pdl_wrap(void *data, int datatype, PDL_Indx dims[],
int ndims, DelMagic delete_magic, int delparam)
{
pdl* npdl = PDL->pdlnew(); /* קבל את המיכל הריק */
PDL->setdims(npdl,dims,ndims); /* set dims */
npdl->datatype = datatype; /* ו- datatype */
npdl->data = data; /* הפנה אותו לנתונים שלך */
/* ודא שהליבה לא מתערבת בנתונים שלך */
npdl->מצב |= PDL_DONTTOUCHDATA | PDL_ALLOCATED;
אם (delete_magic != NULL)
PDL->add_deletedata_magic(npdl, delete_magic, delparam);
אחר
PDL->add_deletedata_magic(npdl, default_magic, 0);
להחזיר npdl;
}
#הגדר SZ 256
/* פונקציה ממש טיפשית שיוצרת תמונת רמפה
* במציאות זו יכולה להיות פונקציה אטומה
* בספרייה כלשהי בה אתה משתמש
*/
PDL_Byte סטטי* mkramp(void)
{
PDL_Byte *נתונים;
int i; /* צריך להשתמש ב-PDL_Indx כדי לתמוך באינדוקס pdl של 64 סיביות */
אם ((נתונים = malloc(SZ*SZ*sizeof(PDL_Byte))) == NULL)
croak("mkramp: לא ניתן היה להקצות זיכרון");
עבור (i=0;i
נתונים[i] = i % SZ;
נתוני החזרה;
}
/* פונקציה זו מטפלת בניקוי הנדרש */
חלל סטטי delete_myramp(pdl* p, int param)
{
אם (p->נתונים)
חופשי(p->נתונים);
p->נתונים = 0;
}
pdl* mkpiddle()
{
PDL_Indx dims[] = {SZ,SZ};
pdl *p;
p = pdl_wrap((void *) mkramp(), PDL_B, dims, 2,
delete_myramp,0); /* ה-delparam מוגדר באופן אקראי ל-0 */
החזר את p;
}
השמיים הרים פרטים
השמיים ליבה מבנה -- מקבל at PDL הליבה שגרות at זמן ריצה
PDL משתמש בטכניקה דומה לזו המופעלת על ידי מודולי Tk כדי לאפשר למודולים אחרים להשתמש
שגרות הליבה שלה. מצביע לכל שגרות הליבה המשותפות של PDL מאוחסן בקובץ $PDL::SHARE
משתנה. קוד XS אמור לתפוס את המצביע הזה בזמן האתחול כך ששאר
קוד C/XS יכול לאחר מכן להשתמש במצביע זה לצורך גישה בזמן ריצה. טעינה ראשונית זו של
ניתן להשיג את המצביע בקלות רבה ביותר באמצעות הפונקציות "PDL_AUTO_INCLUDE" ו-"PDL_BOOT"
מוגדרים ומיוצאים על ידי "PDL::Core::Dev". שימוש אופייני עם מודול Inline כולל
כבר הודגם:
השתמש ב-Inline C => תצורה =>
כולל => &PDL_INCLUDE,
TYPEMAPS => &PDL_TYPEMAP,
AUTO_INCLUDE => &PDL_AUTO_INCLUDE, מספר הצהרות
BOOT => &PDL_BOOT; # קוד עבור מקטע האתחול של XS
הקוד המוחזר על ידי "PDL_AUTO_INCLUDE" מוודא ש pdlcore.h כלול ומכריז
המשתנים הסטטיים כדי להחזיק את המצביע למבנה "Core". זה נראה בערך כך
זֶה:
הדפס PDL_AUTO_INCLUDE;
#לִכלוֹל
ליבה סטטית* PDL; /* המבנה מכיל פונקציות ליבה ב-C */
SV סטטי* CoreSV; /* מקבל מצביע למשתנה Perl המחזיק את מבנה הליבה */
הקוד המוחזר על ידי "PDL_BOOT" מאחזר את המשתנה $PDL::SHARE ומאתחל את
מצביע למבנה "Core". למי שמבין את דרכו ב-API של Perl, הנה ה...
קוד:
הדפס PDL_BOOT;
perl_require_pv ("PDL::Core"); /* ודא ש-PDL::Core נטען */
CoreSV = perl_get_sv("PDL::SHARE",FALSE); /* ערך SV* */
#ifndef aTHX_
#הגדר_aTHX
#endif
אם (CoreSV==NULL)
Perl_croak(aTHX_ "אנו זקוקים למודול PDL::Core, שלא נמצא");
PDL = INT2PTR(ליבה*,SvIV( ליבהSV )); /* ערך ליבה* */
אם (PDL->גרסה != PDL_CORE_VERSION)
Perl_croak(aTHX_ "יש לקמפל מחדש את הקוד כנגד קובץ ה-PDL שהותקן לאחרונה");
מבנה ה-"Core" מכיל מידע גרסה כדי להבטיח שהמבנה המוגדר ב pdlcore.h
באמת תואם את זה שהתקבל בזמן ריצה. הקוד שלמעלה בודק זאת
אם (PDL->גרסה != PDL_CORE_VERSION)
....
למידע נוסף על מבנה הליבה ראו PDL::Internals.
עם הכנות אלו, הקוד שלך יכול כעת לגשת לשגרות הליבה כפי שכבר מוצג ב
חלק מהדוגמאות לעיל, למשל
pdl *p = PDL->pdlnew();
כברירת מחדל, משתנה C בשם "PDL" משמש להחזקת המצביע למבנה "Core". אם
שזו (מסיבה כלשהי) בעיה, אתה יכול לציין במפורש שם עבור
משתנה עם הרוטינות "PDL_AUTO_INCLUDE" ו-"PDL_BOOT":
השתמש ב-Inline C => תצורה =>
כולל => &PDL_INCLUDE,
TYPEMAPS => &PDL_TYPEMAP,
AUTO_INCLUDE => &PDL_AUTO_INCLUDE 'PDL_Corep',
אתחול => &PDL_BOOT 'PDL_Corep';
ודא שאתה משתמש באותו מזהה עם "PDL_AUTO_INCLUDE" ו-"PDL_BOOT" והשתמש בו
אותו מזהה בקוד שלך. לדוגמה, בהמשך לדוגמה לעיל:
pdl *p = PDL_Corep->pdlnew();
כמה נבחר הליבה שגרות מוסבר
ניתן למצוא את ההגדרה המלאה של מבנה ה-"Core" בקובץ pdlcore.h. ב
להלן מוסברות בקצרה פונקציות האיבר הנפוצות ביותר של מבנה זה.
· "pdl *SvPDLV(SV *sv)"
· "pdl *SetSV_PDL(SV *sv, pdl *it)"
· "pdl *pdlnew()"
"pdlnew" מחזירה אובייקט pdl ריק הדורש אתחול נוסף כדי להפעילו.
לתוך מיכל תקין. דוגמה:
pdl *p = PDL->pdlnew();
PDL->setdims(p,dims,ndims);
p->סוג נתונים = PDL_B;
· "pdl *null()"
· "SV *copy(pdl* p, char* )"
· "void *smalloc(STRLEN nbytes)"
· "int howbig(int pdl_datatype)"
· "void add_deletedata_magic(pdl *p, void (*func)(pdl*, int), int param)"
· "void allocdata(pdl *p)"
· "void make_physical(pdl *p)"
· "void make_physdims(pdl *p)"
· "void make_physvaffine(pdl *p)"
· "void qsort_X(PDL_Xtype *data, PDL_Indx a, PDL_Indx b)" ו-"void"
qsort_ind_X(PDL_Xtype *data, PDL_Indx *ix, PDL_Indx a, PDL_Indx b)"
כאשר X הוא אחד מ-B,S,U,L,F,D ו-Xtype הוא אחד מ-Byte, Short, Ushort, Long, Float או
כפול. PDL_Indx הוא סוג המספר השלם C המתאים לגודל האינדקס המתאים.
עבור תצורת ה-perl (ivsize ו-ivtype). זה יכול להיות 'long' או 'long'
long' תלוי אם ה-perl שלך מאופשר ב-32 סיביות או ב-64 סיביות.
· "float NaN_float" ו-"double NaN_double"
אלו הם קבועים לייצור ערכי NaN הנדרשים.
· "void pdl_barf(const char* pat,...)" ו-"void pdl_warn(const char* pat,...)"
אלו הן מילות מקבילות של "barf" ו-"warn" בקוד C. הן כוללות טיפול מיוחד ב...
הודעות שגיאה או אזהרה במהלך pthreading (כלומר, ריבוי-הליכים במעבד) ש
דחו את ההודעות עד לאחר השלמת ה-pthreading. כאשר ה-pthreading הושלם,
ה-"barf" או ה-"warn" של פרל נקראים יחד עם ההודעות הנדחות. זה נחוץ כדי לשמור
מקריאה לפונקציות "barf" או "warn" של פרל במהלך pthreading, מה שעלול לגרום לתקלות סג (segfaults).
שימו לב ש-"barf" ו-"warn" הוגדרו מחדש (באמצעות פקודות מאקרו של c-preprocessor) ב-
pdlcore.h ל-"PDL->barf" ו-"PDL->warn". זה כדי למנוע כל קוד XS או PP מ...
קריאה ישירה ל-"barf" או "warn" של פרל, מה שעלול לגרום לתקלות סג במהלך
פתיחה.
ראה PDL::ParallelCPU למידע נוסף על pthreading.
השתמש ב-PDL::APIp באופן מקוון באמצעות שירותי onworks.net