Ini ialah arahan PDL::PPp yang boleh dijalankan dalam penyedia pengehosan percuma OnWorks menggunakan salah satu daripada berbilang stesen kerja dalam talian percuma kami seperti Ubuntu Online, Fedora Online, emulator dalam talian Windows atau emulator dalam talian MAC OS.
JADUAL:
NAMA
PDL::PP - Hasilkan rutin PDL daripada penerangan ringkas
SINOPSIS
contohnya
pp_def(
'sumover',
Pars => 'a(n); [o]b();',
Kod => q{
double tmp=0;
gelung(n) %{
tmp += $a();
%}
$b() = tmp;
},
);
pp_done();
FUNGSI
Berikut ialah senarai rujukan pantas fungsi yang disediakan oleh PDL::PP.
pp_add_boot
Tambahkan kod pada bahagian BOOT fail XS yang dijana
pp_add_exported
Tambahkan fungsi pada senarai fungsi yang dieksport
pp_add_isa
Tambahkan entri pada senarai @ISA
pp_addbegin
Menetapkan kod untuk ditambahkan di bahagian atas fail generate .pm
pp_addhdr
Tambahkan kod dan sertakan pada bahagian C fail XS yang dijana
pp_addpm
Tambahkan kod pada fail .pm yang dijana
pp_addxs
Tambahkan kod XS tambahan pada fail XS yang dijana
pp_beginwrap
Tambahkan pembalut blok BEGIN pada kod untuk fail .pm yang dijana
pp_bless
Menetapkan pakej yang mana kod XS ditambahkan (lalai ialah PDL)
pp_boundscheck
Kawal keadaan aktiviti semakan sempadan PDL
pp_core_importList
Nyatakan perkara yang diimport daripada PDL::Core
pp_def
Tentukan fungsi PDL baharu
pp_deprecate_module
Tambahkan amaran masa jalan dan POD tentang modul yang ditamatkan
pp_selesai
Tandai penghujung definisi PDL::PP dalam fail
pp_eksport_nothing
Kosongkan senarai eksport untuk modul yang anda hasilkan
pp_line_numbers
Tambahkan maklumat nombor baris untuk memudahkan penyahpepijatan kod PDL::PP
pp_setversion
Tetapkan versi untuk fail .pm dan .xs
TINJAUAN
Mengapa kita memerlukan PP? Beberapa sebab: pertama, kami mahu dapat menjana subrutin
kod untuk setiap jenis data PDL (PDL_Byte, PDL_Short,. dll). SECARA AUTOMATIK. Kedua,
apabila merujuk kepada kepingan tatasusunan PDL dalam Perl (cth. "$a->slice('0:10:2,:')" atau lain-lain
perkara seperti transpose) adalah bagus untuk dapat melakukan ini dengan telus dan dapat
untuk melakukan ini 'di-tempat' - iaitu, tidak perlu membuat salinan memori bahagian. pemegang PP
semua elemen yang diperlukan dan aritmetik mengimbangi untuk anda. Terdapat juga tanggapan tentang
threading (panggilan berulang rutin yang sama untuk berbilang keping, lihat PDL::Indexing)
dan aliran data (lihat PDL::Dataflow) yang membenarkan penggunaan PP.
Dalam kebanyakan perkara yang berikut kita akan menganggap kebiasaan pembaca dengan konsep
manipulasi tersirat dan eksplisit dan indeks dalam PDL. Jika anda belum lagi
mendengar tentang konsep ini atau tidak begitu selesa dengannya sudah tiba masanya untuk menyemak
PDL::Pengindeksan.
Seperti yang anda mungkin hargai daripada namanya PDL::PP ialah Pra-Pemproses, iaitu ia mengembangkan kod melalui
penggantian untuk membuat kod C sebenar. Secara teknikal, output ialah kod XS (lihat perlxs) tetapi
yang sangat dekat dengan C.
Jadi bagaimana anda menggunakan PP? Untuk sebahagian besar anda hanya menulis kod C biasa kecuali untuk
binaan PP khas yang berbentuk:
$sesuatu (sesuatu yang lain)
atau:
PPfungsi %{
%}
Pembinaan PP yang paling penting ialah bentuk "$array()". Pertimbangkan PP yang sangat mudah
berfungsi untuk menjumlahkan elemen vektor 1D (sebenarnya ini sangat serupa dengan vektor sebenar
kod yang digunakan oleh 'sumover'):
pp_def('puncak',
Pars => 'a(n); [o]b();',
Kod => q{
tmp berganda;
tmp = 0;
gelung(n) %{
tmp += $a();
%}
$b() = tmp;
}
);
Apa yang sedang berlaku? Baris "Pars =>" sangat penting untuk PP - ia menentukan semua
hujah dan dimensinya. Kami memanggil ini tanda tangan daripada fungsi PP (bandingkan
juga penjelasan dalam PDL::Indexing). Dalam kes ini rutin mengambil fungsi 1-D sebagai
input dan mengembalikan skalar 0-D sebagai output. Pembinaan "$a()" PP digunakan untuk mengakses
elemen tatasusunan a(n) untuk anda - PP mengisi semua kod C yang diperlukan.
Anda akan perasan bahawa kami menggunakan operator petikan tunggal "q{}". Ini bukan satu
kemalangan. Anda biasanya ingin menggunakan petikan tunggal untuk menandakan bahagian Kod PP anda. PDL::PP
menggunakan "$var()" untuk penghuraian dan jika anda tidak menggunakan petikan tunggal, Perl akan cuba
interpolasi "$var()". Selain itu, menggunakan operator petikan tunggal "q" dengan pendakap kerinting menjadikannya
kelihatan seperti anda sedang mencipta blok kod, iaitu Maksud Anda. (Perl cukup bijak untuk
cari kurung kerinting bersarang dan jangan tutup petikan sehingga jumpa kerinting yang sepadan
pendakap, jadi selamat untuk mempunyai blok bersarang.) Dalam keadaan lain, seperti semasa anda
mencantumkan blok Kod menggunakan gabungan rentetan, selalunya ia paling mudah digunakan
petikan tunggal sebenar sebagai
Kod => 'sesuatu'.$interpolatable.'somethingelse;'
Dalam kes mudah di sini di mana semua elemen diakses konstruk PP "gelung(n) %{ ...
%}" digunakan untuk menggelungkan semua elemen dalam dimensi "n". Perhatikan ciri PP ini: SEMUA
DIMENSI DINYATAKAN OLEH NAMA.
Ini menjadi lebih jelas jika kita mengelakkan PP gelung () bina dan tulis gelung secara eksplisit
menggunakan C konvensional:
pp_def('puncak',
Pars => 'a(n); [o]b();',
Kod => q{
int i,n_size;
tmp berganda;
n_saiz = $SIZE(n);
tmp = 0;
untuk(i=0; i<n_saiz; i++) {
tmp += $a(n=>i);
}
$b() = tmp;
},
);
yang melakukan perkara yang sama seperti sebelumnya, tetapi lebih panjang lebar. Anda boleh lihat untuk mendapatkan elemen "i" daripada
a() kita sebut "$a(n =>i)" - kita menentukan dimensi dengan nama "n". Dalam 2D kita mungkin berkata:
Pars => 'a(m,n);',
...
tmp += $a(m=>i,n=>j);
...
Sintaks "m => i" meminjam daripada cincangan Perl, yang sebenarnya digunakan dalam pelaksanaan
daripada PP. Seseorang juga boleh menyebut "$a(n=>j,m=>i)" kerana susunan tidak penting.
Anda juga boleh melihat dalam contoh di atas penggunaan satu lagi konstruk PP - $SIZE(n) untuk mendapatkan
panjang dimensi "n".
Walau bagaimanapun, perlu diingat bahawa anda tidak sepatutnya menulis gelung C yang jelas apabila anda boleh
telah menggunakan binaan "gelung" PP sejak PDL::PP menyemak secara automatik had gelung untuk
anda, penggunaan "gelung" menjadikan kod lebih ringkas, dsb. Tetapi pasti ada situasi
di mana anda memerlukan kawalan eksplisit gelung dan kini anda tahu bagaimana untuk melakukannya;).
Untuk melawat semula 'Mengapa PP?' - kod di atas untuk summit() akan dijana untuk setiap jenis data. Ia
akan beroperasi pada kepingan tatasusunan 'di tempat'. Ia akan bersambung secara automatik - mis. jika 2D
tatasusunan diberikan ia akan dipanggil berulang kali untuk setiap baris 1D (sekali semak PDL::Pengindeksan untuk
butiran benang). Dan kemudian b() akan menjadi tatasusunan 1D jumlah setiap baris. Kita boleh
panggil dengan $a->xchg(0,1) untuk menjumlahkan lajur. Dan pengesanan Dataflow dsb
diperlukan.
Anda boleh melihat PP menyelamatkan pengaturcara daripada menulis banyak kod C berulang yang tidak perlu --
pada pendapat kami ini adalah salah satu ciri terbaik PDL membuat penulisan subrutin C baharu
untuk PDL satu latihan yang sangat ringkas. Sebab kedua ialah keupayaan untuk membuat PP berkembang
definisi kod ringkas anda kepada kod C yang berbeza berdasarkan keperluan komputer
seni bina berkenaan. Bayangkan sebagai contoh anda bertuah kerana mempunyai superkomputer di
tangan awak; dalam kes itu anda mahu PDL::PP pasti menghasilkan kod yang mengambil kesempatan
ciri pengkomputeran vektor/selari mesin anda (ini projek untuk
masa depan). Walau apa pun, perkara utama ialah kod anda yang tidak berubah masih perlu dikembangkan
kod XS berfungsi walaupun dalaman PDL berubah.
Selain itu, kerana anda menjana kod dalam skrip Perl sebenar, terdapat banyak keseronokan
perkara yang boleh anda lakukan. Katakan anda perlu menulis kedua-dua sumit (seperti di atas) dan multit.
Dengan sedikit kreativiti, kita boleh lakukan
untuk({Nama => 'sumit', Init => '0', Op => '+='},
{Nama => 'berbilang', Init => '1', Op => '*='}) {
pp_def($_->{Nama},
Pars => 'a(n); [o]b();',
Kod => '
tmp berganda;
tmp = '.$_->{Init}.';
gelung(n) %{
tmp '.$_->{Op}.' $a();
%}
$b() = tmp;
');
}
yang mentakrifkan kedua-dua fungsi dengan mudah. Sekarang, jika anda kemudian perlu menukar tandatangan atau
dimensi atau apa sahaja, anda hanya perlu menukar satu tempat dalam kod anda. Ya pasti,
editor anda mempunyai 'cut and paste' dan 'search and replace' tetapi masih kurang
menyusahkan dan pastinya lebih sukar untuk melupakan hanya satu tempat dan mempunyai pepijat pelik
merayap masuk. Selain itu, menambah 'orit' (bitwise atau) kemudian adalah satu pelapik.
Dan ingat, anda benar-benar mempunyai kebolehan penuh Perl bersama anda - anda boleh membaca dengan mudah
sebarang fail input dan buat rutin daripada maklumat dalam fail tersebut. Untuk kes mudah seperti
di atas, pengarang (Tjl) pada masa ini menyukai sintaks hash seperti di atas - tidak terlalu
lebih banyak aksara daripada sintaks tatasusunan yang sepadan tetapi lebih mudah difahami dan
berubah.
Kita harus menyebut di sini juga keupayaan untuk mendapatkan penunjuk ke permulaan data masuk
memori - prasyarat untuk antara muka PDL ke beberapa perpustakaan. Ini dikendalikan dengan
Arahan "$P(var)", lihat di bawah.
Apabila memulakan kerja pada fungsi pp_def'ined baharu, jika anda membuat kesilapan, anda biasanya akan
cari timbunan ralat pengkompil yang menunjukkan nombor baris dalam fail XS yang dijana. Jika awak
tahu cara membaca fail XS (atau jika anda ingin belajar dengan cara yang sukar), anda boleh membuka fail
menghasilkan fail XS dan cari nombor baris dengan ralat. Walau bagaimanapun, baru-baru ini
tambahan kepada PDL::PP membantu melaporkan nombor baris yang betul bagi ralat anda:
"pp_line_numbers". Bekerja dengan contoh sidang kemuncak asal, jika anda mempunyai salah ejaan
tmp dalam kod anda, anda boleh menukar kod (erroneos) kepada sesuatu seperti ini dan
pengkompil akan memberi anda maklumat yang lebih berguna:
pp_def('puncak',
Pars => 'a(n); [o]b();',
Kod => pp_line_numbers(__LINE__, q{
tmp berganda;
tmp = 0;
gelung(n) %{
tmp += $a();
%}
$b() = rmp;
})
);
Untuk situasi di atas, pengkompil saya memberitahu saya:
...
test.pd:15: ralat: 'rmp' tidak diisytiharkan (penggunaan pertama dalam fungsi ini)
...
Dalam skrip contoh saya (dipanggil test.pd), baris 15 adalah betul-betul baris yang saya buat
kesilapan taip: "rmp" bukannya "tmp".
Jadi, selepas gambaran ringkas ini tentang rasa umum pengaturcaraan rutin PDL menggunakan
PDL::PP mari kita ringkaskan dalam keadaan yang mana anda patut menggunakan ini
prapemproses/precompiler. Anda harus menggunakan PDL::PP jika anda mahu
· antara muka PDL ke beberapa perpustakaan luaran
· tulis beberapa algoritma yang akan menjadi perlahan jika dikodkan dalam Perl (ini tidak sekerap anda
fikir; lihat pada threading dan aliran data dahulu).
· menjadi pembangun PDL (walaupun ia tidak wajib)
BERKHATAN :
Oleh kerana seni binanya, PDL::PP boleh menjadi fleksibel dan mudah digunakan pada satu tangan,
namun sangat rumit pada masa yang sama. Pada masa ini, sebahagian daripada masalah adalah kesilapan itu
mesej tidak begitu bermaklumat dan jika berlaku masalah, anda lebih baik tahu apa yang anda
sedang melakukan dan dapat menggodam cara anda melalui dalaman (atau dapat mengetahui dengan
percubaan dan kesilapan apa yang salah dengan args anda kepada "pp_def"). Walaupun kerja sedang dilakukan untuk
menghasilkan amaran yang lebih baik, jangan takut untuk menghantar soalan anda ke senarai mel jika
anda menghadapi masalah.
DESCRIPTION
Sekarang anda mempunyai idea bagaimana untuk menggunakan "pp_def" untuk menentukan fungsi PDL baharu, sudah tiba masanya untuk
terangkan sintaks umum "pp_def". "pp_def" mengambil nama pertama sebagai argumen
fungsi yang anda tentukan dan kemudian senarai cincang yang boleh mengandungi pelbagai kunci.
Berdasarkan kekunci ini PP menjana kod XS dan fail .pm. Fungsi "pp_done" (lihat
contoh dalam SINOPSIS) digunakan untuk memberitahu PDL::PP bahawa tiada lagi definisi dalam
fail ini dan sudah tiba masanya untuk menjana .xs dan
fail .pm.
Akibatnya, mungkin terdapat beberapa pp_def() panggilan di dalam fail (oleh fail konvensyen
dengan kod PP mempunyai sambungan .pd atau .pp) tetapi secara amnya hanya satu pp_done().
Terdapat dua jenis penggunaan utama yang berbeza pp_def(), 'operasi data' dan 'slice
prototaip operasi.
'Operasi data' digunakan untuk mengambil beberapa data, mengoyaknya dan mengeluarkan beberapa data lain; ini
termasuk contohnya operasi '+', songsang matriks, penjumlahan dll dan semua contoh
kita telah bercakap tentang dalam dokumen ini setakat ini. Benang tersirat dan tersurat dan
penciptaan hasilnya dijaga secara automatik dalam operasi tersebut. Anda boleh juga
lakukan aliran data dengan "sumit", "sumover", dll (jangan kecewa jika anda tidak memahami
konsep aliran data dalam PDL dengan sangat baik lagi; ia masih sangat banyak eksperimen).
'Operasi hirisan' ialah jenis operasi yang berbeza: dalam operasi hirisan, anda tidak
menukar mana-mana data, anda mentakrifkan surat-menyurat antara elemen dua yang berbeza
piddles (contoh termasuk definisi fungsi manipulasi/menghiris indeks dalam fail
hirisan.pd itu adalah sebahagian daripada pengedaran PDL; tapi awas, ini bukan tahap pengenalan
barangan).
Jika PDL telah disusun dengan sokongan untuk nilai buruk (iaitu "WITH_BADVAL => 1"), maka tambahan
kunci diperlukan untuk "pp_def", seperti yang dijelaskan di bawah.
Jika anda hanya berminat untuk berkomunikasi dengan beberapa perpustakaan luaran (contohnya beberapa
algebra linear/pustaka matriks), anda biasanya mahukan 'operasi data' jadi kami akan pergi
untuk membincangkannya dahulu.
Tarikh operasi
A mudah contoh
Dalam operasi data, anda mesti tahu dimensi data yang anda perlukan. Pertama, contoh
dengan skalar:
pp_def('tambah',
Pars => 'a(); b(); [o]c();',
Kod => '$c() = $a() + $b();'
);
Itu kelihatan agak pelik tetapi mari kita membedahnya. Baris pertama adalah mudah: kami mentakrifkan a
rutin dengan nama 'tambah'. Baris kedua hanya mengisytiharkan parameter kami dan
kurungan bermaksud bahawa ia adalah skalar. Kami memanggil rentetan yang mentakrifkan parameter kami dan
dimensi mereka tanda tangan daripada fungsi itu. Untuk kaitannya dengan
threading dan manipulasi indeks semak halaman manual PDL::Indexing.
Baris ketiga ialah operasi sebenar. Anda perlu menggunakan tanda dolar dan kurungan
untuk merujuk kepada parameter anda (ini mungkin akan berubah pada satu ketika pada masa hadapan, sekali a
sintaks yang baik ditemui).
Garis-garis ini adalah semua yang diperlukan untuk benar-benar menentukan fungsi untuk PDL (baik,
sebenarnya ia tidak; anda juga perlu menulis Makefile.PL (lihat di bawah) dan membinanya
modul (sesuatu seperti 'perl Makefile.PL; make'); tetapi mari kita abaikan itu buat masa ini).
Jadi sekarang anda boleh lakukan
gunakan MyModule;
$a = pdl 2,3,4;
$b = pdl 5;
$c = tambah($a,$b);
# atau
tambah($a,$b,($c=null)); # Bentuk alternatif, berguna jika $c telah
# pratetap kepada sesuatu yang besar, tidak berguna di sini.
dan kerjakan threading dengan betul (hasilnya ialah $c == [7 8 9]).
. Pars seksyen: yang tanda tangan of a PP fungsi
Melihat kod contoh di atas, anda mungkin akan bertanya: apakah "$c=null" yang pelik ini
sintaks dalam panggilan kedua ke fungsi "tambah" baharu kami? Jika anda melihat sekali lagi pada
takrif "tambah" anda akan melihat bahawa hujah ketiga "c" dibenderakan dengan
qualifier "[o]" yang memberitahu PDL::PP bahawa ini ialah hujah keluaran. Jadi panggilan di atas kepada
tambah bermaksud 'buat $c baharu dari awal dengan dimensi yang betul' - "null" adalah istimewa
token untuk 'piddle kosong' (anda mungkin bertanya mengapa kami tidak menggunakan nilai "undef" untuk membenderakan ini
bukannya "null" khusus PDL; kami sedang memikirkannya ;).
[Ini harus dijelaskan dalam beberapa bahagian lain dalam manual juga!!] Sebabnya
mempunyai sintaks ini sebagai alternatif ialah jika anda mempunyai piddle yang sangat besar, anda boleh melakukannya
$c = PDL->null;
untuk(beberapa gelung panjang) {
# munge a,b
tambah($a,$b,$c);
# munge c, letakkan semula sesuatu pada a,b
}
dan elakkan memperuntukkan dan memperuntukkan $c setiap kali. Ia diperuntukkan sekali pada mulanya
Tambah() dan selepas itu ingatan kekal sehingga $c dimusnahkan.
Jika anda hanya berkata
$c = tambah($a,$b);
kod yang dijana oleh PP akan mengisi "$c=null" secara automatik dan mengembalikan hasilnya. Jika
anda ingin mengetahui lebih lanjut tentang sebab mengapa PDL::PP menyokong gaya ini di mana output
hujah diberikan sebagai hujah terakhir menyemak halaman manusia PDL::Indexing.
"[o]" bukan satu-satunya kelayakan yang boleh dimiliki oleh hujah pdl dalam tandatangan. Satu lagi
kelayakan penting ialah pilihan "[t]" yang menandakan pdl sebagai sementara. Buat apa itu
maksudnya? Anda memberitahu PDL::PP bahawa pdl ini hanya digunakan untuk hasil sementara dalam perjalanan
pengiraan dan anda tidak berminat dengan nilainya selepas pengiraan telah
selesai. Tetapi mengapa perlu PDL::PP ingin tahu tentang perkara ini sejak awal? Sebabnya
berkait rapat dengan konsep penciptaan auto pdl (anda mendengar tentang perkara di atas) dan
benang tersirat. Jika anda menggunakan benang tersirat dimensi secara automatik
pdls yang dibuat sebenarnya lebih besar daripada yang dinyatakan dalam tandatangan. Dengan "[o]" dibenderakan
pdls akan dibuat supaya mereka mempunyai dimensi tambahan seperti yang diperlukan oleh nombor
daripada dimensi benang tersirat. Apabila mencipta pdl sementara, bagaimanapun, ia akan sentiasa sahaja
dibuat cukup besar supaya ia boleh memegang hasil untuk satu lelaran dalam gelung benang, i.e.
sebesar yang dikehendaki oleh tandatangan. Jadi kurang memori yang terbuang apabila anda menandakan pdl sebagai
Sementara. Kedua, anda boleh menggunakan penciptaan auto output dengan pdls sementara walaupun anda
menggunakan penjalinan eksplisit yang dilarang untuk pdls keluaran biasa yang ditandai dengan "[o]"
(lihat PDL::Pengindeksan).
Berikut ialah contoh di mana kita menggunakan kelayakan [t]. Kami mentakrifkan fungsi "callf" itu
memanggil rutin C "f" yang memerlukan tatasusunan sementara dengan saiz dan jenis yang sama seperti tatasusunan
"a" (maaf tentang rujukan hadapan untuk $P; ia adalah akses penuding, lihat di bawah):
pp_def('callf',
Pars => 'a(n); [t] tmp(n); [o] b()',
Kod => 'int ns = $SIZE(n);
f($P(a),$P(b),$P(tmp),ns);
'
);
Hujah dimensi and yang tanda tangan
Sekarang kita baru sahaja bercakap tentang dimensi pdls dan tandatangan. Bagaimana mereka berkaitan?
Katakan kita mahu menambah skalar + nombor indeks pada vektor:
pp_def('tambah2',
Pars => 'a(n); b(); [o]c(n);',
Kod => 'gelung(n) %{
$c() = $a() + $b() + n;
%}'
);
Terdapat beberapa perkara yang perlu diperhatikan di sini: pertama, hujah "Pars" kini mengandungi n
hujah untuk menunjukkan bahawa kita mempunyai satu dimensi dalam a and c. Adalah penting untuk diperhatikan
bahawa dimensi adalah entiti sebenar yang diakses mengikut nama jadi ini diisytiharkan a and c kepada
mempunyai sama dimensi pertama. Dalam kebanyakan definisi PP, saiz dimensi yang dinamakan akan
ditetapkan daripada dimensi pdls bukan keluaran masing-masing (yang tiada bendera "[o]") tetapi
kadangkala anda mungkin mahu menetapkan saiz dimensi bernama secara eksplisit melalui
parameter integer. Lihat di bawah dalam perihalan bahagian "OtherPars" bagaimana ia berfungsi.
Malar hujah dimensi in yang tanda tangan
Katakan anda mahu piddle keluaran dibuat secara automatik dan anda tahu itu pada setiap
panggil dimensinya akan mempunyai saiz yang sama (katakan 9) tanpa mengira dimensi
piddles input. Dalam kes ini, anda menggunakan sintaks berikut dalam bahagian Pars untuk menentukan
saiz dimensi:
' [o] y(n=9); '
Seperti yang dijangkakan, dimensi tambahan yang diperlukan oleh threading akan dibuat jika perlu. Jika awak
perlu menetapkan dimensi bernama mengikut formula yang lebih rumit (daripada pemalar)
anda mesti menggunakan kekunci "RedoDimsCode" yang diterangkan di bawah.
Jenis penukaran and yang tanda tangan
Tandatangan juga menentukan jenis penukaran yang akan dilakukan apabila PP
fungsi dipanggil. Jadi apa yang berlaku apabila kami menggunakan salah satu daripada kami yang ditakrifkan sebelum ini
fungsi dengan pdls berlainan jenis, mis.
add2($a,$b,($ret=null));
di mana $a adalah jenis "PDL_Float" dan $b jenis "PDL_Short"? Dengan tandatangan seperti yang ditunjukkan dalam
takrifan "tambah2" di atas jenis data operasi (seperti yang ditentukan pada masa jalan) ialah
pdl dengan jenis 'tertinggi' (jujukan ialah bait < pendek < ushort < panjang < float
< ganda). Dalam contoh add2 jenis data operasi adalah terapung ($a mempunyai itu
jenis data). Semua hujah pdl kemudiannya jenis ditukar kepada jenis data itu (ia tidak
ditukar di tempat tetapi salinan dengan jenis yang betul dibuat jika hujah pdl tidak mempunyai
jenis operasi). Null pdls tidak menyumbang jenis dalam penentuan
jenis operasi. Walau bagaimanapun, mereka akan dibuat dengan jenis data operasi;
di sini, sebagai contoh, $ret akan menjadi jenis terapung. Anda harus mengetahui peraturan ini apabila
memanggil fungsi PP dengan pdls pelbagai jenis untuk mengambil storan tambahan dan
keperluan runtime diambil kira.
Penukaran jenis ini betul untuk kebanyakan fungsi yang biasa anda tentukan dengan "pp_def".
Walau bagaimanapun, terdapat kes tertentu di mana tingkah laku penukaran jenis diubah sedikit
dikehendaki. Untuk kes ini, kelayakan tambahan dalam tandatangan boleh digunakan untuk menentukan
sifat yang dikehendaki berkenaan dengan penukaran jenis. Kelayakan ini boleh digabungkan dengan
yang telah kita temui (the penciptaan kelayakan "[o]" dan "[t]"). Mari pergi
melalui senarai kelayakan yang mengubah tingkah laku penukaran jenis.
Yang paling penting ialah kelayakan "int" yang berguna apabila hujah pdl
mewakili indeks ke dalam pdl lain. Mari kita lihat contoh daripada "PDL::Ufunc":
pp_def('maksimum_ind',
Pars => 'a(n); int [o] b()',
Kod => '$GENERIC() cur;
int curind;
gelung(n) %{
jika (!n || $a() > cur) {cur = $a(); curind = n;}
%}
$b() = curind;',
);
Fungsi "maximum_ind" mencari indeks elemen terbesar bagi sesuatu vektor. kalau tengok
pada tandatangan anda melihat bahawa argumen output "b" telah diisytiharkan dengan
kelayakan "int" tambahan. Ini mempunyai akibat berikut untuk penukaran jenis:
tidak kira jenis input pdl "a" output pdl "b" akan menjadi jenis "PDL_Long"
yang masuk akal kerana "b" akan mewakili indeks menjadi "a". Tambahan pula, jika anda memanggil
fungsi dengan output pdl "b" sedia ada jenisnya tidak akan mempengaruhi jenis data bagi
operasi (lihat di atas). Oleh itu, walaupun "a" adalah jenis yang lebih kecil daripada "b", ia tidak akan menjadi
ditukar untuk dipadankan dengan jenis "b" tetapi kekal tidak disentuh, yang menjimatkan memori dan kitaran CPU
dan merupakan perkara yang betul untuk dilakukan apabila "b" mewakili indeks. Juga ambil perhatian bahawa anda boleh menggunakan
'int' kelayakan bersama-sama dengan kelayakan lain ("[o]" dan "[t]" kelayakan). Perintah adalah
penting -- jenis kelayakan mendahului penciptaan kelayakan ("[o]" dan "[t]").
Contoh di atas juga menunjukkan penggunaan biasa makro "$GENERIC()". Ia mengembang
kepada jenis semasa dalam gelung generik yang dipanggil. Apakah gelung generik? Seperti yang anda sudah
mendengar fungsi PP mempunyai jenis data masa jalan seperti yang ditentukan oleh jenis argumen pdl
ia telah dipanggil dengan. Oleh itu, kod XS yang dihasilkan PP untuk fungsi ini mengandungi a
suis seperti "switch (type) {case PDL_Byte: ... case PDL_Double: ...}" yang memilih case
berdasarkan jenis data masa jalan bagi fungsi (ia dipanggil jenis ``gelung'' kerana di sana
ialah gelung dalam kod PP yang menjana kes). Walau apa pun kod anda dimasukkan sekali
untuk setiap jenis PDL ke dalam pernyataan suis ini. Makro "$GENERIC()" hanya berkembang ke
jenis masing-masing dalam setiap salinan kod yang dihuraikan anda dalam pernyataan "suis" ini, mis., dalam
"case PDL_Byte" bahagian "cur" akan berkembang kepada "PDL_Byte" dan seterusnya untuk kes yang lain
kenyataan. Saya rasa anda sedar bahawa ini adalah makro yang berguna untuk memegang nilai pdls dalam sesetengahnya
kod.
Terdapat beberapa kelayakan lain dengan kesan yang sama seperti "int". Untuk kamu
kemudahan terdapat kelayakan "terapung" dan "berganda" dengan akibat yang serupa pada
taipkan penukaran sebagai "int". Katakan anda mempunyai a sangat tatasusunan besar yang anda mahukan
hitung jumlah baris dan lajur dengan setara dengan fungsi "sumover". Walau bagaimanapun, dengan
takrifan biasa "sumover" anda mungkin menghadapi masalah apabila data anda, mis. daripada
taip pendek. Panggilan seperti
sumover($large_pdl,($sums = null));
akan menyebabkan $sums menjadi jenis pendek dan oleh itu terdedah kepada ralat limpahan jika
$large_pdl ialah tatasusunan yang sangat besar. Sebaliknya memanggil
@dims = $large_pdl->dims; shift @dims;
sumover($large_pdl,($sums = zeroes(double,@dims)));
bukan alternatif yang baik juga. Sekarang kita tidak mempunyai masalah limpahan dengan $sums tetapi pada
perbelanjaan penukaran jenis $large_pdl kepada dua kali ganda, sesuatu yang buruk jika ini benar-benar
pdl besar. Di situlah "berganda" berguna:
pp_def('sumoverd',
Pars => 'a(n); ganda [o] b()',
Kod => 'tmp berganda=0;
gelung(n) %{ tmp += a(); %}
$b() = tmp;',
);
Ini membawa kita mengatasi masalah penukaran jenis dan limpahan. Sekali lagi, sama dengan
"int" qualifier "double" menghasilkan "b" sentiasa jenis double tanpa mengira jenisnya
daripada "a" tanpa membawa kepada penukaran jenis "a" sebagai kesan sampingan.
Akhir sekali, terdapat kelayakan "jenis+" di mana jenis ialah salah satu daripada "int" atau "float". Apa
adakah itu bermakna. Mari kita gambarkan kelayakan "int+" dengan takrifan sebenar
sumover:
pp_def('sumover',
Pars => 'a(n); int+ [o] b()',
Kod => '$GENERIC(b) tmp=0;
gelung(n) %{ tmp += a(); %}
$b() = tmp;',
);
Seperti yang telah kita lihat untuk kelayakan "int", "float" dan "double", pdl ditandakan dengan
kelayakan "type+" tidak mempengaruhi jenis data operasi pdl. Maksudnya ialah
"jadikan pdl ini sekurang-kurangnya jenis "jenis" atau lebih tinggi, seperti yang diperlukan oleh jenis
operasi". Dalam contoh sumover ini bermakna apabila anda memanggil fungsi dengan "a"
daripada jenis PDL_Short output pdl akan menjadi jenis PDL_Long (sama seperti yang akan menjadi
kes dengan kelayakan "int"). Ini sekali lagi cuba mengelakkan masalah limpahan semasa menggunakan
jenis data kecil (cth. imej bait). Walau bagaimanapun, apabila jenis data operasi lebih tinggi
daripada jenis yang dinyatakan dalam kelayakan "jenis+" "b" akan dibuat dengan jenis data daripada
operasi, cth. apabila "a" adalah jenis double maka "b" akan menjadi dua kali ganda juga. Kami berharap
anda bersetuju bahawa ini adalah tingkah laku yang wajar untuk "sumover". Ia sepatutnya jelas bagaimana
kelayakan "float+" berfungsi dengan analogi. Ia mungkin menjadi perlu untuk dapat menentukan set
jenis alternatif untuk parameter. Walau bagaimanapun, ini mungkin tidak akan dilaksanakan
sehingga seseorang datang dengan penggunaan yang munasabah untuknya.
Ambil perhatian bahawa kita kini perlu menentukan makro $GENERIC dengan nama pdl untuk memperoleh
taip daripada hujah itu. Kenapa begitu? Jika anda mengikuti penjelasan kami dengan teliti, anda akan melakukannya
telah menyedari bahawa dalam beberapa kes "b" akan mempunyai jenis yang berbeza daripada jenis
operasi. Memanggil makro '$GENERIC' dengan "b" sebagai argumen memastikan bahawa jenis
akan sentiasa sama seperti "b" di bahagian gelung generik itu.
Ini adalah tentang semua yang boleh dikatakan tentang bahagian "Pars" dalam panggilan "pp_def". Kamu patut
ingat bahawa bahagian ini mentakrifkan tanda tangan daripada fungsi yang ditentukan PP, anda boleh gunakan
beberapa pilihan untuk melayakkan hujah tertentu sebagai output dan hujah sementara dan semua
dimensi yang anda boleh rujuk kemudian dalam bahagian "Kod" ditakrifkan mengikut nama.
Adalah penting anda memahami maksud tandatangan sejak dalam PDL terkini
versi yang anda boleh gunakan untuk menentukan fungsi berulir dari dalam Perl, iaitu apa yang kami panggil
Perl tahap menjalar. Sila semak PDL::Indexing untuk butiran.
. Kod seksyen
Bahagian "Kod" mengandungi kod XS sebenar yang akan berada di bahagian paling dalam a
gelung benang (jika anda tidak tahu apakah gelung benang maka anda masih belum membaca
PDL::Pengindeksan; lakukan sekarang ;) selepas sebarang makro PP (seperti $GENERIC) dan fungsi PP telah
dikembangkan (seperti fungsi "gelung" yang akan kami jelaskan seterusnya).
Mari kita ulangi dengan cepat contoh "sumover":
pp_def('sumover',
Pars => 'a(n); int+ [o] b()',
Kod => '$GENERIC(b) tmp=0;
gelung(n) %{ tmp += a(); %}
$b() = tmp;',
);
Binaan "gelung" dalam bahagian "Kod" juga merujuk kepada nama dimensi supaya anda tidak
perlu menentukan sebarang had: gelung bersaiz betul dan semuanya dilakukan untuk anda,
lagi.
Seterusnya, terdapat fakta yang mengejutkan bahawa "$a()" dan "$b()" lakukan tidak mengandungi indeks. ini
tidak perlu kerana kita sedang bergelung n dan kedua-dua pembolehubah tahu dimensi mana
mereka mempunyai supaya mereka secara automatik tahu bahawa mereka sedang digelung.
Ciri ini sangat berguna di banyak tempat dan menjadikan kod lebih pendek. Daripada
sudah tentu, ada kalanya anda ingin memintas perkara ini; di sini adalah fungsi yang membuat a
simetri matriks dan berfungsi sebagai contoh cara mengekodkan gelung eksplisit:
pp_def('symm',
Pars => 'a(n,n); [o]c(n,n);',
Kod => 'gelung(n) %{
int n2;
untuk(n2=n; n2<$SAIZ(n); n2++) {
$c(n0 => n, n1 => n2) =
$c(n0 => n2, n1 => n) =
$a(n0 => n, n1 => n2);
}
%}
'
);
Mari kita membedah apa yang berlaku. Pertama, apakah fungsi ini sepatutnya dilakukan? Daripadanya
tandatangan anda melihat bahawa ia memerlukan matriks 2D dengan bilangan lajur dan baris yang sama dan
mengeluarkan matriks yang sama saiz. Daripada matriks input yang diberikan $a ia mengira simetri
matriks keluaran $c (simetrik dalam pengertian matriks bahawa A^T = A dengan ^T bermaksud matriks
transpose, atau dalam bahasa PDL $c == $c->xchg(0,1)). Ia melakukan ini dengan hanya menggunakan nilai
pada dan di bawah pepenjuru $a. Dalam matriks keluaran $c semua nilai pada dan di bawah
pepenjuru adalah sama dengan yang di $a manakala yang di atas pepenjuru adalah imej cermin bagi
yang di bawah pepenjuru (di atas dan di bawah ditafsirkan di sini dengan cara PDL mencetak
pdls 2D). Jika penjelasan ini masih kedengaran agak pelik teruskan sahaja, buat sedikit fail
di mana anda menulis definisi ini, bina sambungan PDL baharu (lihat bahagian pada
Makefiles untuk kod PP) dan cuba dengan beberapa contoh.
Setelah menjelaskan fungsi yang sepatutnya dilakukan, terdapat beberapa mata yang bernilai
mencatat dari sudut sintaksis. Pertama, kita mendapat saiz dimensi yang dinamakan
"n" sekali lagi dengan menggunakan makro $SIZE. Kedua, tiba-tiba terdapat "n0" dan "n1" yang lucu ini
nama indeks dalam kod walaupun tandatangan hanya mentakrifkan dimensi "n". Kenapa ini? The
sebab menjadi jelas apabila anda perhatikan bahawa kedua-dua dimensi pertama dan kedua $a dan $b
dinamakan "n" dalam tandatangan "symm". Ini memberitahu PDL::PP bahawa yang pertama dan kedua
dimensi hujah ini harus mempunyai saiz yang sama. Jika tidak, fungsi yang dihasilkan
akan menimbulkan ralat masa jalan. Walau bagaimanapun, kini dalam akses kepada $a dan $c PDL::PP tidak dapat mengira
keluar yang mana indeks "n" merujuk kepada apa-apa lagi hanya daripada nama indeks. Oleh itu,
indeks dengan nama dimensi yang sama dinomborkan dari kiri ke kanan bermula pada 0, mis. dalam
contoh di atas "n0" merujuk kepada dimensi pertama $a dan $c, "n1" kepada dimensi kedua dan
sebagainya.
Dalam semua contoh setakat ini, kami hanya menggunakan ahli "Pars" dan "Kod" cincang itu
telah diserahkan kepada "pp_def". Sudah tentu terdapat kunci lain yang diiktiraf oleh PDL::PP dan
kita akan mendengar tentang sebahagian daripada mereka dalam perjalanan dokumen ini. Cari (tidak lengkap)
senarai kunci dalam Lampiran A. Senarai makro dan fungsi PP (kami hanya menemui
beberapa daripada contoh di atas lagi) yang dikembangkan dalam nilai hujah cincang
kepada "pp_def" diringkaskan dalam Lampiran B.
Pada ketika ini, mungkin wajar untuk menyebut bahawa PDL::PP bukanlah statik sepenuhnya,
set rutin yang direka dengan baik (seperti yang dikatakan oleh Tuomas: "berhenti memikirkan PP sebagai satu set
rutin yang diukir dalam batu") tetapi lebih kepada koleksi perkara yang pengarang PDL::PP
(Tuomas J. Lukka) menganggap dia perlu kerap menulis dalam rutin sambungan PDLnya.
PP cuba dikembangkan supaya pada masa hadapan, apabila keperluan baru timbul, kod biasa baharu boleh
disarikan kembali ke dalamnya. Jika anda ingin mengetahui lebih lanjut tentang sebab anda mungkin mahu berubah
PDL::PP dan cara melakukannya semak bahagian pada dalaman PDL::PP.
pengendalian buruk nilai
Jika anda tidak mempunyai sokongan nilai buruk yang disusun ke dalam PDL anda boleh mengabaikan bahagian ini dan bahagian
kunci berkaitan: "BadCode", "HandleBad", ... (cuba cetak nilai bagi
$PDL::Bad::Status - jika ia sama dengan 0 maka teruskan terus).
Terdapat beberapa kunci dan makro yang digunakan semasa menulis kod untuk mengendalikan nilai buruk. Yang pertama
satu ialah kunci "HandleBad":
HandleBad => 0
Ini menandakan rutin pp sebagai TIDAK mengendalikan nilai buruk. Jika rutin ini dihantar piddles
dengan set "badflag" mereka, maka mesej amaran dicetak ke STDOUT dan piddles
diproses seolah-olah nilai yang digunakan untuk mewakili nilai buruk adalah nombor yang sah. The
nilai "badflag" tidak dicadangkan ke piddles output.
Contoh apabila ini digunakan adalah untuk rutin FFT, yang biasanya tidak mempunyai cara
mengabaikan sebahagian daripada data.
HandleBad => 1
Ini menyebabkan PDL::PP menulis kod tambahan yang memastikan bahagian BadCode digunakan dan
bahawa makro "$ISBAD()" (dan saudara-saudaranya) berfungsi.
HandleBad tidak diberikan
Jika mana-mana piddle input mempunyai set "badflag", maka piddles output akan
mempunyai set "badflag" mereka, tetapi sebarang BadCode yang dibekalkan diabaikan.
Nilai "HandleBad" digunakan untuk menentukan kandungan kunci "BadDoc", jika ia tidak
diberi.
Untuk mengendalikan nilai buruk, kod mesti ditulis agak berbeza; sebagai contoh,
$c() = $a() + $b();
menjadi sesuatu seperti
jika ($a() != BADVAL && $b() != BADVAL ) {
$c() = $a() + $b();
} Lain {
$c() = BADVAL;
}
Walau bagaimanapun, kami hanya mahu versi kedua jika nilai buruk terdapat dalam piddle input
(dan sokongan bernilai buruk itu dikehendaki!) - jika tidak, kami sebenarnya mahukan kod asal.
Di sinilah kunci "BadCode" masuk; anda menggunakannya untuk menentukan kod untuk dilaksanakan jika buruk
nilai mungkin ada, dan PP menggunakan kedua-duanya dan bahagian "Kod" untuk mencipta sesuatu
seperti:
jika (nilai_buruk_ada_ada) {
fancy_threadloop_stuff {
BadCode
}
} Lain {
fancy_threadloop_stuff {
Kod
}
}
Pendekatan ini bermakna bahawa hampir tiada overhed apabila nilai buruk tidak hadir
(iaitu rutin badflag mengembalikan 0).
Bahagian BadCode boleh menggunakan makro dan binaan gelung yang sama seperti bahagian Kod.
Walau bagaimanapun, ia tidak akan banyak digunakan tanpa makro tambahan berikut:
$ISBAD(var)
Untuk menyemak sama ada nilai piddle adalah buruk, gunakan makro $ISBAD:
if ($ISBAD(a()) ) { printf("a() is bad\n"); }
Anda juga boleh mengakses elemen piddle yang diberikan:
if ($ISBAD(a(n=>l)) ) { printf("elemen %d a() is bad\n", l); }
$ISGOOD(var)
Ini adalah bertentangan dengan makro $ISBAD.
$SETBAD(var)
Untuk apabila anda ingin menetapkan unsur piddle bad.
$ISBADVAR(c_var,pdl)
Jika anda telah menyimpan nilai piddle "$a()" ke dalam pembolehubah c ("foo" katakan), kemudian ke
semak sama ada ia buruk, gunakan "$ISBADVAR(foo,a)".
$ISGOODVAR(c_var,pdl)
Seperti di atas, tetapi kali ini menyemak bahawa nilai cache tidak buruk.
$SETBADVAR(c_var,pdl)
Untuk menyalin nilai buruk bagi piddle ke dalam pembolehubah c, gunakan "$SETBADVAR(foo,a)".
SEMUANYA: sebutkan makro "$PPISBAD()" dsb.
Menggunakan makro ini, kod di atas boleh ditentukan sebagai:
Kod => '$c() = $a() + $b();',
BadCode => '
jika ($ISBAD(a()) || $ISBAD(b()) ) {
$SETBAD(c());
} Lain {
$c() = $a() + $b();
}',
Oleh kerana ini adalah Perl, TMTOWTDI, jadi anda juga boleh menulis:
BadCode => '
jika ($ISGOOD(a()) && $ISGOOD(b()) ) {
$c() = $a() + $b();
} Lain {
$SETBAD(c());
}',
Jika anda mahukan akses kepada nilai badflag untuk piddle yang diberikan, anda boleh menggunakan
Makro "$PDLSTATExxxx()":
$PDLSTATEISBAD(pdl)
$PDLSTATEISGOOD(pdl)
$PDLSTATESETBAD(pdl)
$PDLSTATESETGOOD(pdl)
SEMUANYA: sebutkan pilihan "FindBadStatusCode" dan "CopyBadStatusCode" kepada "pp_def", serta
sebagai kunci "BadDoc".
Interfacing Matlamat sendiri/perpustakaan fungsi menggunakan PP
Sekarang, pertimbangkan perkara berikut: anda mempunyai fungsi C anda sendiri (yang sebenarnya mungkin sebahagian daripada
beberapa perpustakaan yang anda mahu antara muka ke PDL) yang mengambil sebagai hujah dua petunjuk kepada
vektor ganda:
void myfunc(int n,double *v1,double *v2);
Cara yang betul untuk mentakrifkan fungsi PDL ialah
pp_def('myfunc',
Pars => 'a(n); [o]b(n);',
GenericTypes => ['D'],
Kod => 'myfunc($SIZE(n),$P(a),$P(b));'
);
"$P("olehSintaks ")" mengembalikan penunjuk kepada elemen pertama dan elemen lain adalah
dijamin berbohong selepas itu.
Perhatikan bahawa di sini adalah mungkin untuk membuat banyak kesilapan. Pertama, $SIZE(n) mesti digunakan
bukannya "n". Kedua, anda tidak sepatutnya meletakkan sebarang gelung dalam kod ini. Ketiga, di sini kita bertemu
kunci cincang baharu yang diiktiraf oleh PDL::PP : perisytiharan "GenericTypes" memberitahu PDL::PP untuk
HANYA JANA TYPELOOP FOP SENARAI JENIS YANG DITETAPKAN. Dalam kes ini "berganda". ini
mempunyai dua kelebihan. Pertama saiz kod yang disusun dikurangkan dengan ketara, kedua jika
hujah bukan berganda dihantar kepada "myfunc()" PDL akan menukarnya secara automatik kepada
gandakan sebelum beralih ke rutin C luaran dan tukarkannya semula selepas itu.
Seseorang juga boleh menggunakan "Pars" untuk melayakkan jenis hujah individu. Oleh itu, seseorang juga boleh
tulis ini sebagai:
pp_def('myfunc',
Pars => 'double a(n); ganda [o]b(n);',
Kod => 'myfunc($SIZE(n),$P(a),$P(b));'
);
Spesifikasi jenis dalam "Pars" mengecualikan hujah daripada variasi dalam gelung taip -
sebaliknya ia juga ditukar secara automatik dan daripada jenis yang ditentukan. Ini jelas sekali
berguna dalam contoh yang lebih umum, mis.:
void myfunc(int n,float *v1,long *v2);
pp_def('myfunc',
Pars => 'apungkan a(n); panjang [o]b(n);',
GenericTypes => ['F'],
Kod => 'myfunc($SIZE(n),$P(a),$P(b));'
);
Ambil perhatian bahawa kami masih menggunakan "GenericTypes" untuk mengurangkan saiz gelung jenis, jelas sekali PP boleh
pada dasarnya lihat ini dan lakukannya secara automatik walaupun kod itu masih belum mencapainya
tahap kecanggihan!
Akhir sekali ambil perhatian apabila jenis ditukar secara automatik seseorang MESTI menggunakan kelayakan "[o]".
pembolehubah output atau anda sukar satu perubahan akan dioptimumkan oleh PP!
Jika anda antara muka perpustakaan yang besar anda boleh mengautomasikan antara muka dengan lebih jauh lagi. Perl boleh
membantu anda sekali lagi(!) dalam melakukan ini. Dalam kebanyakan perpustakaan anda mempunyai konvensyen panggilan tertentu.
Ini boleh dieksploitasi. Ringkasnya, anda boleh menulis sedikit penghurai (yang sebenarnya tidak
sukar dalam Perl) yang kemudian menjana panggilan ke "pp_def" daripada perihalan yang dihuraikan
fungsi dalam perpustakaan itu. Sebagai contoh, sila semak Slatec antara muka dalam
Pokok "Lib" taburan PDL. Jika anda ingin menyemak (semasa penyahpepijatan) yang memanggil
PP berfungsi kod Perl anda menghasilkan pakej pembantu kecil yang berguna
menggantikan fungsi PP dengan nama yang sama yang membuang hujah mereka ke stdout.
Katakan saja
perl -MPDL::PP::Buang myfile.pd
untuk melihat panggilan ke "pp_def" dan rakan. Cuba dengan ops.pd and slatec.pd. Jika anda
berminat (atau ingin mempertingkatkannya), sumbernya ada dalam Basic/Gen/PP/Dump.pm
lain-lain makro and fungsi in yang Kod seksyen
Makro: Setakat ini kami telah menemui makro $SIZE, $GENERIC dan $P. Sekarang kita akan
terangkan dengan cepat makro lain yang dikembangkan dalam bahagian "Kod" PDL::PP bersama-sama
dengan contoh penggunaannya.
$T Makro $T digunakan untuk suis jenis. Ini sangat berguna apabila anda perlu menggunakannya
fungsi luaran (cth. perpustakaan) berbeza bergantung pada jenis input argumen.
Sintaks umum ialah
$Ttypeletters(type_alternatives)
dengan "huruf taip" ialah pilih atur subset huruf "BSULFD" yang berdiri
untuk Byte, Short, Ushort, dsb. dan "type_alternatives" ialah pengembangan apabila jenis
operasi PP adalah sama dengan yang ditunjukkan oleh surat masing-masing. Jom
menggambarkan penerangan yang tidak dapat difahami ini dengan contoh. Dengan mengandaikan anda mempunyai dua C
fungsi dengan prototaip
void float_func(float *in, float *out);
void double_func(double *in, double *out);
yang pada dasarnya melakukan perkara yang sama tetapi satu menerima apungan dan penunjuk berganda yang lain.
Anda boleh antara muka mereka ke PDL dengan mentakrifkan fungsi generik "foofunc" (yang akan
panggil fungsi yang betul bergantung pada jenis transformasi):
pp_def('foofunc',
Pars => ' a(n); [o] b();',
Kod => ' $TFD(float_func,double_func) ($P(a),$P(b));'
GenericTypes => [qw(FD)],
);
Sila ambil perhatian bahawa anda tidak boleh mengatakan
Kod => ' $TFD(float,double)_func ($P(a),$P(b));'
memandangkan makro $T mengembang dengan ruang belakang, secara analog kepada makro prapemproses C.
Bentuk yang lebih panjang sedikit yang digambarkan di atas adalah betul. Jika anda benar-benar mahukan singkat, anda
sudah tentu boleh buat
'$TBSULFD('.(sertai ',',peta {"nama_pengenal_panjang_$_"}
qw/byt pendek unseigned lounge flotte dubble/).');'
$PP
Makro $PP digunakan untuk apa yang dipanggil fizikal penunjuk mengakses. Yang fizikal merujuk kepada
beberapa pengoptimuman dalaman PDL (bagi mereka yang biasa dengan teras PDL kami
bercakap tentang pengoptimuman vaffine). Makro ini terutamanya untuk kegunaan dalaman dan anda
tidak perlu menggunakannya dalam mana-mana kod biasa anda.
$COMP (dan bahagian "OtherPars")
Makro $COMP digunakan untuk mengakses nilai bukan pdl dalam bahagian kod. Namanya ialah
terhasil daripada pelaksanaan transformasi dalam PDL. Pembolehubah yang anda boleh rujuk
menggunakan $COMP adalah ahli struktur ``disusun'' yang mewakili PDL
transformasi yang dipersoalkan tetapi belum lagi mengandungi sebarang maklumat tentang dimensi
(untuk butiran lanjut semak PDL::Internals). Walau bagaimanapun, anda boleh merawat $COMP hanya sebagai a
kotak hitam tanpa mengetahui apa-apa tentang pelaksanaan transformasi dalam PDL.
Jadi bilakah anda akan menggunakan makro ini? Penggunaan utamanya adalah untuk mengakses nilai argumen yang
diisytiharkan dalam bahagian "OtherPars" bagi definisi "pp_def". Tetapi kemudian anda tidak
pernah dengar tentang kunci "OtherPars"?! Mari kita ada satu lagi contoh yang menggambarkan
penggunaan biasa kedua-dua ciri baharu:
pp_def('pnmout',
Pars => 'a(m)',
OtherPars => "char* fd",
GenericTypes => [qw(BUSL)],
Kod => 'PerlIO *fp;
IO *io;
io = GvIO(gv_fetchpv($COMP(fd),FALSE,SVt_PVIO));
jika (!io || !(fp = IoIFP(io)))
croak("Tidak dapat mengetahui FP");
jika (PerlIO_write(fp,$P(a),len) != len)
croak("Ralat menulis fail pnm");
');
Fungsi ini digunakan untuk menulis data dari pdl ke fail. Deskriptor fail diluluskan
sebagai rentetan ke dalam fungsi ini. Parameter ini tidak masuk ke bahagian "Pars".
kerana ia tidak boleh dianggap berguna seperti pdl tetapi lebih kepada nama yang sesuai
Bahagian "OtherPars". Parameter dalam bahagian "OtherPars" mengikuti parameter dalam "Pars"
bahagian apabila menggunakan fungsi, i.e.
buka FAIL,">out.dat" atau mati "tidak boleh buka keluar.dat";
pnmout($pdl,'FAIL');
Apabila anda ingin mengakses parameter ini di dalam bahagian kod anda perlu memberitahu PP oleh
menggunakan makro $COMP, iaitu anda menulis "$COMP(fd)" seperti dalam contoh. Jika tidak PP
tidak akan tahu bahawa "fd" yang anda maksudkan adalah sama seperti yang dinyatakan dalam
Bahagian "OtherPars".
Penggunaan lain untuk bahagian "OtherPars" adalah untuk menetapkan dimensi bernama dalam tandatangan.
Mari kita berikan contoh bagaimana ia dilakukan:
pp_def('setdim',
Pars => '[o] a(n)',
OtherPars => 'int ns => n',
Kod => 'gelung(n) %{ $a() = n; %}',
);
Ini mengatakan bahawa dimensi bernama "n" akan dimulakan daripada nilai lain
parameter "ns" yang merupakan jenis integer (saya rasa anda telah menyedari bahawa kami menggunakan
"CType From => named_dim" sintaks). Kini anda boleh memanggil fungsi ini dengan cara biasa:
setdim(($a=null),5);
cetak $a;
[ 0 1 2 3 4 ]
Memang diakui fungsi ini tidak begitu berguna tetapi ia menunjukkan cara ia berfungsi. Jika awak
panggil fungsi dengan pdl sedia ada dan anda tidak perlu menyatakan secara eksplisit
saiz "n" kerana PDL::PP boleh memikirkannya daripada dimensi pdl bukan nol. Dalam
kes itu anda hanya memberikan parameter dimensi sebagai "-1":
$a = sejarah($b);
setdim($a,-1);
Itu patut dilakukan.
Satu-satunya fungsi PP yang telah kami gunakan dalam contoh setakat ini ialah "gelung". Selain itu,
Pada masa ini terdapat dua fungsi lain yang diiktiraf dalam bahagian "Kod":
gelung benang
Seperti yang kita dengar di atas tandatangan fungsi yang ditentukan PP mentakrifkan dimensi semua
hujah pdl yang terlibat dalam a primitif operasi. Walau bagaimanapun, anda sering menghubungi
fungsi yang anda takrifkan dengan PP dengan pdls yang mempunyai lebih banyak dimensi daripada itu
dinyatakan dalam tandatangan. Dalam kes ini operasi primitif dilakukan pada semua
subslices dimensi yang sesuai dalam apa yang dipanggil a thread gelung (Lihat juga
gambaran keseluruhan di atas dan PDL::Indexing). Dengan mengandaikan anda mempunyai beberapa tanggapan tentang konsep ini anda
mungkin akan menghargai bahawa operasi yang dinyatakan dalam bahagian kod sepatutnya
dioptimumkan kerana ini adalah gelung paling ketat di dalam gelung benang. Namun, jika anda melihat semula
contoh di mana kami mentakrifkan fungsi "pnmout", anda akan segera menyedari bahawa mencari
sehingga deskriptor fail "IO" dalam gelung benang dalam tidak begitu cekap semasa menulis
pdl dengan banyak baris. Pendekatan yang lebih baik ialah mencari deskriptor "IO" sekali
di luar gelung benang dan gunakan nilainya kemudian di dalam gelung benang yang paling ketat. Ini adalah
tepat di mana fungsi "threadloop" berguna. Berikut ialah definisi yang dipertingkatkan
daripada "pnmout" yang menggunakan fungsi ini:
pp_def('pnmout',
Pars => 'a(m)',
OtherPars => "char* fd",
GenericTypes => [qw(BUSL)],
Kod => 'PerlIO *fp;
IO *io;
int len;
io = GvIO(gv_fetchpv($COMP(fd),FALSE,SVt_PVIO));
jika (!io || !(fp = IoIFP(io)))
croak("Tidak dapat mengetahui FP");
len = $SAIZ(m) * saiz($GENERIC());
gelung benang %{
jika (PerlIO_write(fp,$P(a),len) != len)
croak("Ralat menulis fail pnm");
%}
');
Ini berfungsi seperti berikut. Biasanya kod C yang anda tulis di dalam bahagian "Kod" diletakkan
di dalam gelung benang (iaitu PP menjana kod XS pembalut yang sesuai di sekelilingnya).
Walau bagaimanapun, apabila anda menggunakan fungsi "threadloop" secara eksplisit, PDL::PP mengenali ini dan
tidak membungkus kod anda dengan gelung benang tambahan. Ini mempunyai kesan yang mengekod anda
tulis di luar gelung benang hanya dilaksanakan sekali setiap transformasi dan hanya kod
dengan pasangan "%{ ... %}" di sekeliling diletakkan dalam gelung benang yang paling ketat. ini
juga berguna apabila anda ingin melakukan keputusan (atau mana-mana kod lain, terutamanya
Kod intensif CPU) hanya sekali setiap utas, i.e.
pp_addhdr('
#define RAW 0
#define ASCII 1
');
pp_def('do_raworascii',
Pars => 'a(); b(); [o]c()',
OtherPars => 'mod int',
Kod => ' suis ($COMP(mod)) {
kes RAW:
gelung benang %{
/* buat barang mentah */
%}
memecahkan;
kes ASCII:
gelung benang %{
/* buat perkara ASCII */
%}
memecahkan;
lalai:
croak("mod tidak diketahui");
}'
);
jenis
Fungsi jenis berfungsi serupa dengan makro $T. Walau bagaimanapun, dengan fungsi "jenis".
kod dalam blok berikut (dibataskan oleh "%{" dan "%}" seperti biasa) dilaksanakan untuk semua
kes di mana jenis data operasi itu mana-mana of jenis yang diwakili oleh
huruf dalam hujah untuk "menaip", cth.
Kod => '...
jenis(BSUL) %{
/* lakukan operasi jenis integer */
%}
jenis(FD) %{
/* lakukan operasi titik terapung */
%}
... '
. RedoDimsCode seksyen
Kunci "RedoDimsCode" ialah kunci pilihan yang digunakan untuk mengira dimensi piddle di
masa jalan sekiranya peraturan standard untuk pengiraan dimensi daripada tandatangan tidak
mencukupi. Kandungan entri "RedoDimsCode" ditafsirkan dengan cara yang sama
bahagian Kod ditafsirkan-- iaitu, makro PP dikembangkan dan hasilnya ialah
ditafsirkan sebagai kod C. Tujuan kod adalah untuk menetapkan saiz beberapa dimensi yang
muncul dalam tandatangan. Peruntukan storan dan gelung benang dan sebagainya akan ditetapkan sebagai
jika dimensi yang dikira telah muncul dalam tandatangan. Dalam kod anda, anda mula-mula mengira
saiz yang dikehendaki bagi dimensi bernama dalam tandatangan mengikut keperluan anda dan kemudian
tetapkan nilai itu kepadanya melalui $SAIZ() makro.
Sebagai contoh, pertimbangkan situasi berikut. Anda sedang mengadaptasi perpustakaan luaran
rutin yang memerlukan tatasusunan sementara untuk ruang kerja diluluskan sebagai hujah. dua
tatasusunan data input yang dilalui ialah p(m) dan x(n). Tatasusunan data keluaran ialah y(n). The
rutin memerlukan tatasusunan ruang kerja dengan panjang n+m*m dan anda mahukan storan itu
dicipta secara automatik sama seperti mana-mana piddle yang dibenderakan dengan [t] atau [o]. Apa
yang anda mahu ialah mengatakan sesuatu seperti
pp_def("myexternalfunc",
Pars => " p(m); x(n); [o] y; [t] kerja(n+m*m); ",...
tetapi itu tidak akan berfungsi, kerana PP tidak boleh mentafsir ungkapan dengan aritmetik dalam
tandatangan. Sebaliknya anda menulis
pp_def("myexternalfunc",
Pars => " p(m); x(n); [o] y; [t] kerja(wn); ",
RedoDimsCode => "
int im = $PDL(p)->malap[0];
int in = $PDL(x)->malap[0];
int min = dalam + im * im;
int inw = $PDL(kerja)->malap[0];
$SIZE(wn) = inw >= min ? inw: min; ",
Kod => "
externalfunc($P(p),$P(x),$SAIZ(m),$SIZE(n),$P(kerja));
";)
Kod ini berfungsi seperti berikut: Makro $PDL(p) mengembang kepada penuding kepada struct pdl untuk
piddle p. Anda tidak mahu penunjuk kepada data ( ie $P ) dalam kes ini, kerana anda
ingin mengakses kaedah untuk piddle pada tahap C. Anda mendapat dimensi pertama
setiap piddle dan simpannya dalam integer. Kemudian anda mengira panjang minimum
susunan kerja boleh. Jika pengguna menghantar piddle "bekerja" dengan storan yang mencukupi, maka biarkan ia
bersendirian. Jika pengguna menghantar, sebut pdl batal, atau tiada pdl langsung, maka saiz wn akan menjadi
sifar dan anda menetapkannya semula kepada nilai minimum. Sebelum kod di bahagian Kod adalah
PP yang dilaksanakan akan mencipta storan yang sesuai untuk "kerja" jika ia tidak wujud. Perhatikan bahawa anda
hanya mengambil dimensi pertama "p" dan "x" kerana pengguna mungkin telah menghantar piddle dengan
dimensi benang tambahan. Sudah tentu, piddle sementara "berfungsi" (perhatikan bendera [t])
tidak boleh diberikan sebarang dimensi benang pula.
Anda juga boleh menggunakan "RedoDimsCode" untuk menetapkan dimensi piddle yang dibenderakan dengan [o]. Di dalam ini
kes anda menetapkan dimensi untuk dimensi yang dinamakan dalam tandatangan menggunakan $SAIZ() seperti dalam
contoh sebelumnya. Walau bagaimanapun, kerana piddle ditandai dengan [o] dan bukannya [t],
dimensi benang akan ditambah jika diperlukan sama seperti saiz dimensi
dikira daripada tandatangan mengikut peraturan biasa. Berikut adalah contoh daripada
PDL::Matematik
pp_def("polyroots",
Pars => 'cr(n); ci(n); [o]rr(m); [o]ri(m);',
RedoDimsCode => 'int sn = $PDL(cr)->dims[0]; $SAIZ(m) = sn-1;',
Piddle input ialah bahagian sebenar dan khayalan bagi pekali kompleks a
polinomial. Piddles keluaran adalah bahagian akar yang nyata dan khayalan. Terdapat "n"
akar kepada polinomial tertib "n" dan polinomial sedemikian mempunyai pekali "n+1" (
zeoreth melalui "n"th). Dalam contoh ini, threading akan berfungsi dengan betul. Iaitu, yang
dimensi pertama piddle keluaran dengan mempunyai dimensi yang diselaraskan, tetapi threading lain
dimensi akan diberikan sama seperti tiada "RedoDimsCode".
Peta taip mengendalikan in yang "OtherPars" seksyen
Bahagian "OtherPars" yang dibincangkan di atas selalunya sangat penting apabila anda
antara muka perpustakaan luaran dengan PDL. Walau bagaimanapun dalam banyak kes perpustakaan luaran sama ada
gunakan jenis terbitan atau penunjuk pelbagai jenis.
Cara standard untuk mengendalikan ini dalam Perl ialah menggunakan fail "peta taip". Ini dibincangkan dalam
beberapa perincian dalam perlxs dalam dokumentasi Perl standard. Dalam PP fungsinya sangat
serupa, jadi anda boleh mencipta fail "peta taip" dalam direktori tempat fail PP anda berada
dan apabila ia dibina ia dibaca secara automatik untuk mengetahui terjemahan yang sesuai
antara jenis C dan jenis terbina dalam Perl.
Walau bagaimanapun, terdapat beberapa perbezaan penting daripada pengendalian umum jenis
dalam XS. Yang pertama, dan mungkin yang paling penting, ialah pada masa ini petunjuk kepada jenis adalah
tidak dibenarkan dalam bahagian "OtherPars". Untuk mengatasi had ini, anda mesti menggunakan
Jenis "IV" (terima kasih kepada Judd Taylor kerana menunjukkan bahawa ini adalah perlu untuk mudah alih).
Mungkin lebih baik untuk menggambarkan ini dengan beberapa coretan kod:
Sebagai contoh, fungsi "gsl_spline_init" mempunyai pengisytiharan C berikut:
int gsl_spline_init(gsl_spline * spline,
const double xa[], const double ya[], size_t size);
Jelas sekali tatasusunan "xa" dan "ya" adalah calon untuk diluluskan sebagai piddles dan
hujah "saiz" hanyalah panjang piddles ini supaya boleh dikendalikan oleh
"$SIZE()" makro dalam PP. Masalahnya ialah penunjuk kepada jenis "gsl_spline". Yang semula jadi
penyelesaiannya adalah dengan menulis pengisytiharan "OtherPars" borang
OtherPars => 'gsl_spline *spl'
dan tulis fail "peta taip" pendek yang mengendalikan jenis ini. Ini tidak berfungsi pada masa ini
namun! Jadi apa yang anda perlu lakukan ialah mengatasi masalah itu sedikit (dan dalam beberapa cara
ini lebih mudah juga!):
Penyelesaiannya adalah untuk mengisytiharkan "spline" dalam bahagian "OtherPars" menggunakan "Nilai Integer",
"IV". Ini menyembunyikan sifat pembolehubah daripada PP dan anda perlu (baik untuk mengelakkan
amaran pengkompil sekurang-kurangnya!) lakukan cast jenis apabila anda menggunakan pembolehubah dalam kod anda.
Oleh itu "OtherPars" harus mengambil bentuk:
OtherPars => 'IV spl'
dan apabila anda menggunakannya dalam kod anda akan menulis
INT2PTR(gsl_spline *, $COMP(spl))
di mana makro API Perl "INT2PTR" telah digunakan untuk mengendalikan hantaran penunjuk untuk dielakkan
amaran pengkompil dan masalah untuk mesin dengan campuran 32bit dan 64bit Perl
konfigurasi. Menyatukan ini seperti yang telah dilakukan oleh Andres Jordan (dengan pengubahsuaian
menggunakan "IV" oleh Judd Taylor) dalam "gsl_interp.pd" dalam sumber pengedaran yang anda dapat:
pp_def('init_meat',
Pars => 'double x(n); ganda y(n);',
OtherPars => 'IV spl',
Kod =>'
gsl_spline_init,( INT2PTR(gsl_spline *, $COMP(spl)), $P(x),$P(y),$SIZE(n)));'
);
di mana saya telah mengalih keluar panggilan pembalut makro, tetapi itu akan mengaburkan perbincangan.
Perbezaan kecil yang lain berbanding dengan pengendalian peta taip standard dalam Perl, ialah itu
pengguna tidak boleh menentukan lokasi peta taip bukan standard atau nama fail peta taip menggunakan
Pilihan "TYPEMAPS" dalam MakeMaker... Oleh itu anda hanya boleh menggunakan fail yang dipanggil "typemap" dan/atau
Helah "IV" di atas.
lain-lain berguna PP kunci in data operasi definisi
Anda telah pun mendengar tentang kekunci "OtherPars". Pada masa ini, tidak banyak kunci lain
untuk operasi data yang berguna dalam pengaturcaraan PP biasa (apa pun itu). Dalam
Sebenarnya, adalah menarik untuk mendengar tentang kes yang anda fikir anda memerlukan lebih daripada apa
disediakan pada masa ini. Sila bercakap di salah satu senarai mel PDL. Kebanyakan yang lain
kunci yang diiktiraf oleh "pp_def" hanya benar-benar berguna untuk apa yang kami panggil keping operasi (Lihat
juga di atas).
Satu perkara yang sangat dirancang ialah bilangan hujah yang berubah-ubah, yang akan menjadi a
sedikit rumit.
Senarai kunci yang tersedia yang tidak lengkap:
Inplace
Menetapkan kunci ini menandakan rutin sebagai berfungsi di tempat - iaitu input dan output
piddles pun sama. Contohnya ialah "$a->inplace->sqrt()" (atau "sqrt(inplace($a))").
Inplace => 1
Gunakan apabila rutin ialah fungsi unary, seperti "sqrt".
Inplace => ['a']
Jika terdapat lebih daripada satu piddle input, nyatakan nama piddle yang boleh
ditukar di tempat menggunakan rujukan tatasusunan.
Inplace => ['a','b']
Jika terdapat lebih daripada satu piddle keluaran, nyatakan nama piddle input dan
piddle keluaran dalam rujukan tatasusunan 2 elemen. Ini mungkin tidak diperlukan, tetapi dibiarkan
dalam untuk kesempurnaan.
Jika nilai buruk digunakan, penjagaan mesti diambil untuk memastikan penyebaran
badflag apabila inplace sedang digunakan; pertimbangkan petikan ini daripada Asas/Bad/bad.pd:
pp_def('replacebad',HandleBad => 1,
Pars => 'a(); [o]b();',
OtherPars => 'double newval',
Inplace => 1,
CopyBadStatusCode =>
'/* propogate badflag jika di tempat DAN ia telah berubah */
jika ( a == b && $ISPDLSTATEBAD(a) )
PDL->propogate_badflag( b, 0 );
/* sentiasa pastikan output adalah "baik" */
$SETPDLSATEGOOD(b);
',
...
Memandangkan rutin ini mengalih keluar semua nilai buruk, maka piddle keluaran mempunyai bendera buruknya
dibersihkan. Jika dijalankan di tempatnya (jadi "a == b"), maka kita perlu memberitahu semua anak "a"
bahawa bendera buruk telah dikosongkan (untuk menjimatkan masa kami memastikan bahawa kami memanggil
"PDL->propogate_badgflag" hanya jika piddle input mempunyai set bendera buruknya).
NOTA: satu idea ialah dokumentasi untuk rutin boleh dibuat secara automatik
dibenderakan untuk menunjukkan bahawa ia boleh dilaksanakan di tempat, iaitu sesuatu yang serupa dengan bagaimana
"HandleBad" menetapkan "BadDoc" jika ia tidak dibekalkan (ia bukan penyelesaian yang ideal).
lain-lain PDL::PP fungsi kepada menyokong ringkas pakej definisi
Setakat ini, kami telah menerangkan fungsi "pp_def" dan "pp_done". PDL::PP mengeksport beberapa
fungsi lain untuk membantu anda menulis definisi pakej sambungan PDL yang ringkas.
pp_addhdr
Selalunya apabila anda antara muka perpustakaan berfungsi seperti dalam contoh di atas anda perlu sertakan
tambahan C termasuk fail. Oleh kerana fail XS dijana oleh PP, kami memerlukan beberapa cara untuk
buat PP memasukkan arahan sertakan yang sesuai di tempat yang betul ke dalam XS yang dihasilkan
fail. Untuk tujuan ini terdapat fungsi "pp_addhdr". Ini juga fungsi untuk digunakan
apabila anda ingin menentukan beberapa fungsi C untuk kegunaan dalaman oleh beberapa fungsi XS
(yang kebanyakannya fungsi yang ditakrifkan oleh "pp_def"). Dengan memasukkan fungsi ini di sini anda
pastikan PDL::PP memasukkan kod anda sebelum titik di mana modul XS sebenar
bahagian bermula dan oleh itu tidak akan disentuh oleh xsubpp (rujuk. perlxs and perlxstut
halaman manusia).
Panggilan biasa ialah
pp_addhdr('
#include /* kami memerlukan defs sebanyak XXXX */
#include "libprotos.h" /* prototaip fungsi perpustakaan */
#include "mylocaldecs.h" /* Decs tempatan */
kekosongan statik do_the real_work(PDL_Byte * in, PDL_Byte * out, int n)
{
/* buat beberapa pengiraan dengan data */
}
');
Ini memastikan bahawa semua pemalar dan prototaip yang anda perlukan akan dimasukkan dengan betul dan
bahawa anda boleh menggunakan fungsi dalaman yang ditakrifkan di sini dalam "pp_def", cth.:
pp_def('barfoo',
Pars => ' a(n); [o] b(n)',
GenericTypes => ['B'],
Kod => ' int ns = $SIZE(n);
buat_kerja_sebenar($P(a),$P(b),ns);
',
);
pp_addpm
Dalam kebanyakan kes, kod PP sebenar (bermaksud argumen untuk panggilan "pp_def") hanyalah sebahagian daripada
pakej yang anda sedang laksanakan. Selalunya terdapat kod Perl tambahan dan XS
kod yang biasanya anda tulis ke dalam fail pm dan XS yang kini secara automatik
dihasilkan oleh PP. Jadi bagaimana untuk memasukkan bahan ini ke dalam fail yang dijana secara dinamik?
Nasib baik, terdapat beberapa fungsi, biasanya dipanggil "pp_addXXX" yang membantu anda
dalam melakukan ini.
Katakan anda mempunyai kod Perl tambahan yang harus dimasukkan ke dalam kod yang dihasilkan pm-fail. ini
mudah dicapai dengan arahan "pp_addpm":
pp_addpm(<<'EOD');
=head1 NAMA
PDL::Lib::Mylib -- antara muka PDL ke perpustakaan Mylib
=kepala1 HURAIAN
Pakej ini melaksanakan antara muka kepada pakej Mylib dengan penuh
threading dan sokongan pengindeksan (lihat L).
= potong
gunakan PGPLOT;
=head2 use_myfunc
fungsi ini menggunakan operasi myfunc untuk semua
elemen pdl input tanpa mengira dimensi
dan mengembalikan jumlah hasil
= potong
sub use_myfunc {
my $pdl = shift;
myfunc($pdl->gumpal(-1),($res=null));
pulangkan $res->sum;
}
Eod
pp_add_exported
Anda mungkin telah mendapat idea itu. Dalam sesetengah kes, anda juga ingin mengeksport tambahan anda
fungsi. Untuk mengelak daripada menghadapi masalah dengan PP yang turut mengacaukan @EXPORT
array anda hanya memberitahu PP untuk menambah fungsi anda ke senarai fungsi yang dieksport:
pp_add_exported('use_myfunc gethynx');
pp_add_isa
Perintah "pp_add_isa" berfungsi seperti fungsi "pp_add_exported". Hujah-hujah kepada
"pp_add_isa" ditambahkan dalam senarai @ISA, mis.
pp_add_isa(' Some::Other::Class ');
pp_bless
Jika rutin pp_def anda akan digunakan sebagai kaedah objek gunakan "pp_bless" untuk menentukan
pakej (iaitu kelas) yang anda pp_defkaedah ed akan ditambah. Sebagai contoh,
"pp_bless('PDL::MyClass')". Lalai ialah "PDL" jika ini ditinggalkan.
pp_addxs
Kadangkala anda ingin menambah kod XS tambahan anda sendiri (yang biasanya tidak terlibat dengan
sebarang isu threading/pengindeksan tetapi membekalkan beberapa fungsi lain yang anda ingin akses
dari sisi Perl) ke fail XS yang dijana, sebagai contoh
pp_addxs('','
# Tentukan endianness mesin
int
isbigendian()
KOD:
pendek tidak bertanda i;
PDL_Byte *b;
i = 42; b = (PDL_Byte*) (kosong*) &i;
jika (*b == 42)
RETVAL = 0;
lain jika (*(b+1) == 42)
RETVAL = 1;
lagi
croak("Mustahil - mesin bukan endian besar mahupun kecil!!\n");
PENGELUARAN:
RETVAL
');
Terutamanya "pp_add_exported" dan "pp_addxs" harus digunakan dengan berhati-hati. PP menggunakan
PDL::Pengeksport, justeru membiarkan PP mengeksport fungsi anda bermakna mereka ditambahkan pada
senarai standard fungsi yang dieksport secara lalai (senarai yang ditakrifkan oleh teg eksport
``:Fungsi''). Jika anda menggunakan "pp_addxs" anda tidak sepatutnya cuba melakukan apa-apa yang melibatkan penjalinan
atau pengindeksan secara langsung. PP adalah lebih baik dalam menjana kod yang sesuai daripada anda
takrifan.
pp_add_boot
Akhir sekali, anda mungkin mahu menambah beberapa kod pada bahagian BOOT fail XS (jika anda tidak melakukannya
tahu apa itu semak perlxs). Ini mudah dilakukan dengan arahan "pp_add_boot":
pp_add_boot(<
descrip = mylib_initialize(KEEP_OPEN);
jika (huraikan == NULL)
croak("Tidak dapat memulakan perpustakaan");
GlobalStruc->descrip = huraian;
GlobalStruc->maxfiles = 200;
EOB
pp_eksport_nothing
Secara lalai, PP.pm meletakkan semua subs yang ditakrifkan menggunakan fungsi pp_def ke dalam output .pm
senarai EXPORT fail. Ini boleh menimbulkan masalah jika anda mencipta objek subkelas di mana
anda tidak mahu sebarang kaedah dieksport. (iaitu kaedah hanya akan dipanggil menggunakan
$objek-> sintaks kaedah).
Untuk kes ini anda boleh menghubungi pp_export_nothing() untuk mengosongkan senarai eksport. Contoh (Pada
penghujung fail .pd):
pp_export_nothing();
pp_done();
pp_core_importList
Secara lalai, PP.pm meletakkan 'use Core;' baris ke dalam fail .pm output. Ini mengimport Core
nama yang dieksport ke dalam ruang nama semasa, yang boleh menimbulkan masalah jika anda terlalu-
menunggang salah satu kaedah Teras dalam fail semasa. Anda akhirnya mendapat mesej seperti
"Amaran: sub sumover ditakrifkan semula dalam fail subclass.pm" semasa menjalankan program.
Untuk kes ini, pp_core_importList boleh digunakan untuk menukar perkara yang diimport
Teras.pm. Sebagai contoh:
pp_core_importList('()')
Ini akan mengakibatkan
gunakan Core();
sedang dijana dalam fail .pm output. Ini akan menyebabkan tiada nama diimport dari
Teras.pm. Begitu juga dengan panggilan
pp_core_importList(' qw/ barf /')
akan mengakibatkan
gunakan Core qw/ barf/;
sedang dijana dalam fail .pm output. Ini akan menyebabkan hanya 'barf' diimport
daripada Core.pm.
pp_setversion
Saya cukup pasti bahawa ini membolehkan anda menetapkan fail .pm dan .xs secara serentak'
versi, dengan itu mengelakkan versi-skew yang tidak perlu antara keduanya. Untuk menggunakan ini, cukup miliki
baris berikut pada satu ketika dalam fail .pd anda:
pp_setversion('0.0.3');
Walau bagaimanapun, jangan gunakan ini jika anda menggunakan Module::Build::PDL. Lihat dokumentasi modul itu untuk
butiran.
pp_deprecate_module
Jika modul tertentu dianggap usang, fungsi ini boleh digunakan untuk menandakannya sebagai
ditamatkan. Ini mempunyai kesan mengeluarkan amaran apabila pengguna cuba "menggunakan" itu
modul. POD yang dijana untuk modul ini juga membawa notis penamatan. The
modul gantian boleh diluluskan sebagai hujah seperti ini:
pp_deprecate_module( infavor => "PDL::NewNonDeprecatedModule" );
Perhatikan bahawa fungsi mempengaruhi hanyalah amaran masa jalan dan POD.
Membuat Matlamat PP fungsi "swasta"
Katakan anda mempunyai fungsi dalam modul anda yang dipanggil PDL::foo yang menggunakan PP
fungsi "bar_pp" untuk melakukan pengangkatan berat. Tetapi anda tidak mahu mengiklankan "bar_pp" itu
wujud. Untuk melakukan ini, anda mesti mengalihkan fungsi PP anda ke bahagian atas fail modul anda, kemudian
memanggil
pp_export_nothing()
untuk mengosongkan senarai "EKSPORT". Untuk memastikan tiada dokumentasi (walaupun dokumen PP lalai) adalah
dihasilkan, ditetapkan
Doc => undef
dan untuk mengelakkan fungsi daripada ditambahkan pada jadual simbol, tetapkan
PMFunc => ''
dalam perisytiharan pp_def anda (lihat Image2D.pd untuk contoh). Ini berkesan akan membuat
fungsi PP anda "peribadi." Walau bagaimanapun, ia adalah sentiasa boleh diakses melalui PDL::bar_pp kerana Perl's
reka bentuk modul. Tetapi menjadikannya peribadi akan menyebabkan pengguna pergi sangat jauh darinya
cara menggunakannya, jadi dia memikul akibatnya!
Slice operasi
Bahagian operasi hirisan manual ini disediakan menggunakan aliran data dan penilaian malas:
apabila anda memerlukannya, minta Tjl menulisnya. penghantaran dalam seminggu selepas saya menerima e-mel
adalah 95% berkemungkinan dan penghantaran dua minggu adalah 99% berkemungkinan.
Bagaimanapun, operasi hirisan memerlukan pengetahuan yang lebih mendalam tentang dalaman PDL
daripada operasi data. Tambahan pula, kerumitan isu yang terlibat adalah
jauh lebih tinggi daripada itu dalam operasi data purata. Jika anda ingin meyakinkan
diri anda fakta ini lihat pada Asas/Kepingan/hirisan.pd fail dalam PDL
pengedaran :-). Namun begitu, fungsi yang dijana menggunakan operasi hirisan adalah di
jantung manipulasi indeks dan keupayaan aliran data PDL.
Selain itu, terdapat banyak isu kotor dengan piddle dan vaffin maya yang kami akan lakukan
langkau di sini sepenuhnya.
Keping and buruk nilai
Operasi hirisan perlu dapat mengendalikan nilai buruk (jika sokongan disusun ke dalam PDL).
Perkara yang paling mudah dilakukan ialah melihat Asas/Kepingan/hirisan.pd untuk melihat bagaimana ini berfungsi.
Bersama-sama dengan "BadCode", terdapat juga kekunci "BadBackCode" dan "BadRedoDimsCode" untuk
"pp_def". Walau bagaimanapun, mana-mana "EquivCPOffsCode" sepatutnya tidak perlu berubah, kerana sebarang perubahan adalah
diserap ke dalam takrifan makro "$EQUIVCPOFFS()" (iaitu ia dikendalikan
secara automatik oleh PDL::PP>.
A beberapa nota on bertulis a mengiris rutin ...
Beberapa perenggan berikut menerangkan penulisan rutin penghirisan baharu ('julat'); mana-mana
ralat adalah CED. (--CED 26-Ogos 2002)
pengendalian of "beri amaran" and "barf" in PP Kod
Untuk mencetak mesej amaran atau menggugurkan/mati, anda boleh memanggil "amaran" atau "barf" daripada PP
kod. Walau bagaimanapun, anda harus sedar bahawa panggilan ini telah ditakrifkan semula menggunakan C
makro prapemproses kepada "PDL->barf" dan "PDL->warn". Takrifan semula ini disediakan untuk
menghalang anda daripada memanggil "amaran" atau "barf" perl secara tidak sengaja, yang boleh menyebabkan
segfault semasa pthreading (iaitu pemproses multi-threading).
Versi "barf" dan "warn" PDL sendiri akan beratur baris amaran atau mesej barf sehingga selepas
pthreading selesai, dan kemudian panggil versi perl rutin ini.
Lihat PDL::ParallelCPU untuk mendapatkan maklumat lanjut tentang pthreading.
BERGUNA RUTIN
Struktur "Teras" PDL, ditakrifkan dalam Asas/Teras/pdlcore.h.PL, mengandungi penunjuk kepada a
bilangan rutin yang mungkin berguna kepada anda. Majoriti rutin ini berurusan dengan
memanipulasi piddles, tetapi ada yang lebih umum:
PDL->qsort_B( PDL_Byte *xx, int a, int b )
Isih tatasusunan "xx" antara indeks "a" dan "b". Terdapat juga versi untuk
jenis data PDL lain, dengan postfix "_S", "_U", "_L", "_F", dan "_D". Sebarang modul menggunakan
ini mesti memastikan bahawa "PDL::Ufunc" dimuatkan.
PDL->qsort_ind_B( PDL_Byte *xx, int *ix, int a, int b )
Bagi "PDL->qsort_B", tetapi kali ini mengisih indeks dan bukannya data.
Rutin "med2d" dalam Lib/Image2D/image2d.pd menunjukkan bagaimana rutin tersebut digunakan.
MAKEFILES UNTUK PP FILES
Jika anda akan menjana pakej daripada fail PP anda (sambungan fail biasa ialah
".pd" atau ".pp" untuk fail yang mengandungi kod PP) adalah paling mudah dan selamat untuk ditinggalkan
penjanaan arahan yang sesuai untuk Makefile. Di bawah ini kami akan gariskan
format biasa Perl Makefile untuk membina dan memasang pakej anda secara automatik
penerangan dalam fail PP. Kebanyakan peraturan untuk membina fail xs, pm dan lain-lain yang diperlukan
daripada fail PP sudah dipratentukan dalam pakej PDL::Core::Dev. Kita hanya perlu
beritahu MakeMaker untuk menggunakannya.
Dalam kebanyakan kes anda boleh menentukan Makefile anda seperti
# Makefile.PL untuk pakej yang ditakrifkan oleh kod PP.
gunakan PDL::Core::Dev; # Ambil utiliti pembangunan
gunakan ExtUtils::MakeMaker;
$package = ["mylib.pd",Mylib,PDL::Lib::Mylib];
% hash = pdlpp_stdargs($pakej);
$hash{OBJECT} .= ' additional_Ccode$(OBJ_EXT) ';
$hash{bersih}->{FILES} .= ' todelete_Ccode$(OBJ_EXT) ';
$hash{'VERSION_FROM'} = 'mylib.pd';
WriteMakefile(%hash);
sub MY::postamble { pdlpp_postamble($package); }
Di sini, senarai dalam $package ialah: pertama: Nama fail sumber PP, kemudian awalan untuk
menghasilkan fail dan akhirnya nama pakej keseluruhan. Anda boleh mengubah suai cincang dalam apa sahaja
cara yang anda suka tetapi adalah munasabah untuk kekal dalam beberapa had supaya pakej anda
akan terus berfungsi dengan versi PDL yang lebih baru.
Jika anda tidak mahu menggunakan hujah yang telah dibungkus, berikut ialah yang generik Makefile.PL yang anda boleh
menyesuaikan diri untuk keperluan anda sendiri:
# Makefile.PL untuk pakej yang ditakrifkan oleh kod PP.
gunakan PDL::Core::Dev; # Ambil utiliti pembangunan
gunakan ExtUtils::MakeMaker;
WriteMakefile(
'NAME' => 'PDL::Lib::Mylib',
'VERSION_FROM' => 'mylib.pd',
'TYPEMAPS' => [&PDL_TYPEMAP()],
'OBJECT' => 'mylib$(OBJ_EXT) additional_Ccode$(OBJ_EXT)',
'PM' => { 'Mylib.pm' => '$(INST_LIBDIR)/Mylib.pm'},
'INC' => &PDL_INCLUDE(), # add sertakan dir seperti yang diperlukan oleh lib anda
'LIBS' => [''], # tambah arahan pautan jika perlu
'bersih' => {'FAIL' =>
'Mylib.pm Mylib.xs Mylib$(OBJ_EXT)
additional_Ccode$(OBJ_EXT)'},
);
# Tambah peraturan genpp; ini akan menggunakan PDL::PP pada fail PP kami
# hujah ialah rujukan tatasusunan di mana tatasusunan mempunyai tiga elemen rentetan:
# arg1: nama fail sumber yang mengandungi kod PP
# arg2: nama asas fail xs dan pm yang akan dijana
# arg3: nama pakej yang akan dijana
sub MY::postamble { pdlpp_postamble(["mylib.pd",Mylib,PDL::Lib::Mylib]); }
Untuk menjadikan hidup lebih mudah PDL::Core::Dev mentakrifkan fungsi "pdlpp_stdargs" yang mengembalikan
cincang dengan nilai lalai yang boleh dihantar (sama ada secara langsung atau selepas yang sesuai
pengubahsuaian) kepada panggilan ke WriteMakefile. Pada masa ini, "pdlpp_stdargs" mengembalikan cincang di mana
kekunci diisi seperti berikut:
(
'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' => [''],
'clean' => {'FILES' => "$pref.xs $pref.pm $pref\$(OBJ_EXT)"},
)
Di sini, $src ialah nama fail sumber dengan kod PP, $pref awalan untuk yang dihasilkan
fail .pm dan .xs dan $mod nama modul sambungan untuk dijana.
DALAMAN
Bahagian dalaman versi semasa terdiri daripada jadual besar yang memberikan peraturan
mengikut mana perkara diterjemahkan dan subs yang melaksanakan peraturan ini.
Kemudian, adalah baik untuk membuat jadual yang boleh diubah suai oleh pengguna supaya berbeza
perkara boleh dicuba.
[Komen meta: di sini diharapkan akan lebih banyak lagi pada masa hadapan; buat masa ini, pertaruhan terbaik anda ialah
untuk membaca kod sumber :-( atau tanya dalam senarai (cuba yang terakhir dahulu) ]
Umbai usus A: Sesetengah kunci dikenali by PDL::PP
Melainkan dinyatakan sebaliknya, hujah adalah rentetan. Kekunci yang ditanda dengan (buruk) adalah sahaja
digunakan jika sokongan nilai buruk disusun ke dalam PDL.
Pars
tentukan tandatangan fungsi anda
OtherPar
hujah yang bukan pdls. Lalai: tiada. Ini ialah senarai dipisahkan koma bertitik
argumen, cth., "OtherPars => 'int k; nilai berganda; char* fd'". Lihat $COMP(x) dan juga
entri yang sama dalam Lampiran B.
Kod
kod sebenar yang melaksanakan fungsi; beberapa makro PP dan fungsi PP
diiktiraf dalam nilai rentetan
HandleBad (buruk)
Jika ditetapkan kepada 1, rutin diandaikan menyokong nilai buruk dan kod dalam BadCode
kunci digunakan jika nilai buruk ada; ia juga menetapkan perkara supaya "$ISBAD()"
dll makro boleh digunakan. Jika ditetapkan kepada 0, menyebabkan rutin mencetak amaran jika ada
piddles input mempunyai set bendera buruk mereka.
BadCode (buruk)
Berikan kod untuk digunakan jika nilai buruk mungkin terdapat dalam piddles input. Hanya digunakan
jika "HandleBad => 1".
GenericTypes
Rujukan tatasusunan. Tatasusunan mungkin mengandungi mana-mana subset rentetan satu aksara `B',
`S', `U', `L', `Q', `F' dan `D', yang menentukan jenis operasi anda akan terima.
Maksud setiap jenis ialah:
B - bait yang ditandatangani (iaitu aksara yang ditandatangani)
S - ditandatangani pendek (integer dua bait)
U - pendek tidak ditandatangani
L - panjang yang ditandatangani (integer empat bait, int pada sistem 32 bit)
Q - panjang panjang yang ditandatangani (integer lapan bait)
F - terapung
D - berganda
Ini sangat berguna (dan penting!) apabila antara muka perpustakaan luaran. Lalai:
[qw/BSULQFD/]
Inplace
Tandakan fungsi sebagai boleh bekerja di tempatnya.
Inplace => 1 jika Pars => 'a(); [o]b();'
Inplace => ['a'] if Pars => 'a(); b(); [o]c();'
Inplace => ['a','b'] if Pars => 'a(); b(); [o]c(); [o]d();'
Jika nilai buruk digunakan, penjagaan mesti diambil untuk memastikan penyebaran
badflag apabila inplace sedang digunakan; contohnya lihat kod untuk "replacebad" dalam
Asas/Bad/bad.pd.
Doc Digunakan untuk menentukan rentetan dokumentasi dalam format Pod. Lihat PDL::Doc untuk maklumat tentang
Konvensyen dokumentasi PDL. Nota: dalam kes khas di mana rentetan PP 'Doc' berada
satu baris ini digunakan secara tersirat untuk rujukan pantas DAN dokumentasi!
Jika medan Dokumen ditinggalkan PP akan menjana dokumentasi lalai (selepas semua ia tahu
tentang Tandatangan).
Jika anda benar-benar mahu fungsi TIDAK didokumenkan dalam apa jua cara pada ketika ini (cth.
untuk rutin dalaman, atau kerana anda melakukannya di tempat lain dalam kod) secara eksplisit
nyatakan "Doc => undef".
BadDoc (buruk)
Mengandungi teks yang dikembalikan oleh arahan "badinfo" (dalam "perldl") atau suis "-b".
kepada skrip shell "pdldoc". Dalam banyak kes, anda tidak perlu menyatakan ini, kerana
maklumat boleh dibuat secara automatik oleh PDL::PP. Walau bagaimanapun, sesuai dengan komputer-
teks yang dihasilkan, ia agak kaku; mungkin lebih baik untuk melakukannya sendiri!
NoPthread
Bendera pilihan untuk menunjukkan fungsi PDL sepatutnya tidak gunakan benang pemproses (iaitu.
pthreads atau POSIX threads) untuk membahagikan kerja merentas berbilang teras CPU. Pilihan ini ialah
biasanya ditetapkan kepada 1 jika fungsi PDL asas tidak selamat untuk benang. Jika pilihan ini
tidak hadir, maka fungsi itu dianggap selamat untuk benang. Pilihan ini hanya terpakai
jika PDL telah disusun dengan urutan POSIX didayakan.
PMCode
Fungsi PDL membolehkan anda memasukkan piddle ke mana anda mahu output disimpan. ini
berguna kerana anda boleh memperuntukkan piddle keluaran sekali dan menggunakannya semula berkali-kali; yang
alternatif adalah untuk PDL membuat piddle baharu setiap kali, yang mungkin membazirkan pengiraan
kitaran atau, lebih berkemungkinan, RAM. Fleksibiliti tambahan ini datang dengan kos lebih
kerumitan: PDL::PP perlu menulis fungsi yang cukup pintar untuk mengira
hujah diteruskan kepadanya dan mencipta piddles baharu dengan cepat, tetapi hanya jika anda mahukannya.
PDL::PP cukup bijak untuk melakukannya, tetapi terdapat sekatan pada susunan hujah dan
seumpamanya. Jika anda mahukan fungsi yang lebih fleksibel, anda boleh menulis bahagian Perl anda sendiri
pembungkus dan nyatakannya dalam kekunci PMCode. Rentetan yang anda bekalkan mesti (sepatutnya)
tentukan fungsi Perl dengan nama yang sepadan dengan apa yang anda berikan kepada pp_def pada yang pertama
tempat. Apabila anda akhirnya ingin menggunakan fungsi yang dihasilkan PP, anda perlu melakukannya
bekalkan semua piddle dalam susunan yang tepat yang dinyatakan dalam tandatangan: piddles output adalah
bukan pilihan, dan fungsi yang dihasilkan PP tidak akan mengembalikan apa-apa. Yang keliru
nama yang anda akan panggil ialah __int.
Saya percaya dokumentasi ini memerlukan penjelasan lanjut, tetapi ini perlu dilakukan.
:-(
PMFunc
Apabila pp_def menjana fungsi, ia biasanya mentakrifkannya dalam pakej PDL. Kemudian,
dalam fail .pm yang dijana untuk modul anda, ia biasanya menambah baris itu
pada asasnya menyalin yang berfungsi ke dalam jadual simbol pakej semasa anda dengan kod
yang kelihatan seperti ini:
*func_name = \&PDL::func_name;
Ia sedikit lebih bijak daripada itu (ia tahu bila hendak membungkus perkara semacam itu dalam a
BEGIN blok, sebagai contoh, dan jika anda menentukan sesuatu yang berbeza untuk pp_bless), tetapi
itulah intipatinya. Jika anda tidak mengambil berat untuk mengimport fungsi ke semasa anda
jadual simbol pakej, anda boleh tentukan
PMFunc => '',
PMFunc tidak mempunyai kesan sampingan lain, jadi anda boleh menggunakannya untuk memasukkan kod Perl sewenang-wenangnya
ke dalam modul anda jika anda suka. Walau bagaimanapun, anda harus menggunakan pp_addpm jika anda ingin menambah Perl
kod ke modul anda.
Umbai usus B: PP makro and fungsi
Makro
Makro yang dilabelkan oleh (buruk) hanya digunakan jika sokongan nilai buruk disusun ke dalam PDL.
$variablename_from_sig()
akses pdl (dengan namanya) yang dinyatakan dalam tandatangan
$COMP(x)
akses nilai dalam struktur data peribadi transformasi ini (terutamanya digunakan untuk
gunakan hujah yang dinyatakan dalam bahagian "OtherPars")
$SIZE(n)
digantikan pada masa jalan dengan saiz sebenar a bernama dimensi (seperti yang dinyatakan dalam
tanda tangan)
$GENERIK()
digantikan dengan jenis C yang sama dengan jenis masa jalan operasi
$P(a) akses penunjuk kepada PDL bernama "a" dalam tandatangan. Berguna untuk antara muka kepada C
fungsi
$PP(a) akses penunjuk fizikal kepada pdl "a"; terutamanya untuk kegunaan dalaman
$TXXX(Alternatif, Alternatif)
alternatif pengembangan mengikut jenis operasi masa jalan, dengan XXX adalah beberapa
rentetan yang dipadankan dengan "/[BSULFD+]/".
$PDL(a)
kembalikan penunjuk kepada struktur data pdl (pdl *) piddle "a"
$ISBAD(a()) (buruk)
mengembalikan benar jika nilai yang disimpan dalam "a()" sama dengan nilai buruk untuk piddle ini.
Memerlukan "HandleBad" ditetapkan kepada 1.
$ISGOOD(a()) (buruk)
mengembalikan benar jika nilai yang disimpan dalam "a()" tidak sama dengan nilai buruk untuk ini
piddle. Memerlukan "HandleBad" ditetapkan kepada 1.
$SETBAD(a()) (buruk)
Tetapkan "a()" untuk menyamai nilai buruk untuk piddle ini. Memerlukan "HandleBad" ditetapkan
untuk 1.
fungsi
"gelung(DIMS) %{ ... %}"
gelung pada dimensi yang dinamakan; had dijana secara automatik oleh PP
"threadloop %{ ... %}"
sertakan kod berikut dalam gelung benang
"jenis(JENIS) %{ ... %}"
laksanakan kod berikut jika jenis operasi adalah mana-mana "JENIS"
Umbai usus C: Fungsi diimport by PDL::PP
Beberapa fungsi diimport apabila anda "menggunakan PDL::PP". Ini termasuk fungsi yang
mengawal kod C atau XS yang dijana, fungsi yang mengawal kod Perl yang dijana, dan
fungsi yang memanipulasi pakej dan jadual simbol di mana kod dicipta.
Menjana C and XS Kod
PDL::Tujuan utama PP adalah untuk memudahkan anda membalut enjin benang di sekeliling anda
kod C sendiri, tetapi anda boleh melakukan beberapa perkara lain juga.
pp_def
Digunakan untuk membungkus enjin benang di sekeliling kod C anda. Hampir semua dokumen ini
membincangkan penggunaan pp_def.
pp_selesai
Menunjukkan anda telah selesai menggunakan PDL::PP dan ia sepatutnya menjana fail .xs dan .pmnya
berdasarkan fungsi pp_* lain yang telah anda panggil. Fungsi ini mengambil no
hujah-hujah.
pp_addxs
Ini membolehkan anda menambah kod XS pada fail .xs anda. Ini berguna jika anda ingin membuat Perl-
fungsi boleh diakses yang menggunakan kod C tetapi tidak boleh atau tidak boleh menggunakan benang
enjin. XS ialah cara standard yang anda gunakan untuk membungkus kod C yang boleh diakses oleh Perl. Awak boleh
ketahui lebih lanjut di perlxs.
pp_add_boot
Fungsi ini menambah apa sahaja rentetan yang anda hantar ke bahagian XS BOOT. Bahagian BOOT
ialah kod C yang dipanggil oleh Perl apabila modul anda dimuatkan dan berguna untuk
permulaan automatik. Anda boleh mengetahui lebih lanjut tentang XS dan bahagian BOOT di perlxs.
pp_addhdr
Menambah kod pure-C pada fail XS anda. Fail XS distrukturkan supaya kod C tulen mesti
datang sebelum spesifikasi XS. Ini membolehkan anda menentukan kod C tersebut.
pp_boundscheck
PDL biasanya menyemak had akses anda sebelum membuatnya. Anda boleh mengubahnya
hidup atau mati pada masa jalan dengan menetapkan MyPackage::set_boundscheck. Fungsi ini membolehkan anda
untuk mengalih keluar fleksibiliti masa jalan itu dan pernah melakukan semakan sempadan. Ia juga mengembalikan
status penyemakan sempadan semasa jika dipanggil tanpa sebarang hujah.
NOTA: Saya tidak menemui apa-apa tentang semakan sempadan dalam dokumentasi lain. Itu
perlu ditangani.
Menjana Perl Kod
Banyak fungsi yang diimport apabila anda menggunakan PDL::PP membolehkan anda mengubah suai kandungan
fail .pm yang dihasilkan. Sebagai tambahan kepada pp_def dan pp_done, peranan fungsi ini ialah
terutamanya untuk menambah kod pada pelbagai bahagian fail .pm yang anda hasilkan.
pp_addpm
Menambah kod Perl pada fail .pm yang dijana. PDL::PP sebenarnya menjejaki tiga
bahagian berbeza kod yang dijana: Bahagian Atas, Tengah dan Bawah. Anda boleh menambah
Kod Perl ke bahagian Tengah menggunakan bentuk satu hujah, di mana hujahnya ialah
Kod Perl yang ingin anda berikan. Dalam bentuk dua hujah, hujah pertama ialah an
hash tanpa nama dengan hanya satu kunci yang menentukan tempat untuk meletakkan hujah kedua,
yang merupakan rentetan yang anda mahu tambah pada fail .pm. Hash adalah salah satu daripada ini
tiga:
{Di => 'Atas'}
{Di => 'Tengah'}
{Di => 'Bot'}
Sebagai contoh:
pp_addpm({Di => 'Bot'}, <<POD);
=head1 Beberapa dokumentasi
Saya tahu saya sedang menaip ini di tengah-tengah fail saya, tetapi ia akan pergi pada
bahagian bawah.
= potong
POD
Amaran: Jika, di tengah-tengah fail .pd anda, anda meletakkan dokumentasi yang dimaksudkan untuk
bahagian bawah pod anda, anda akan mengelirukan CPAN sepenuhnya. Sebaliknya, jika dalam
tengah-tengah fail .pd anda, anda menambah beberapa kod Perl yang ditujukan untuk bahagian bawah atau atas anda
.pm fail, anda hanya perlu mengelirukan diri anda sendiri. :-)
pp_beginwrap
Menambah pembalut blok BEGIN. Perisytiharan tertentu boleh dibungkus dalam blok BEGIN, walaupun
tingkah laku lalai adalah tidak mempunyai pembalut sedemikian.
pp_addbegin
Menetapkan kod untuk ditambahkan pada bahagian atas fail .pm anda, malah di atas kod yang anda tentukan
dengan "pp_addpm({Di => 'Atas'}, ...)". Tidak seperti pp_addpm, memanggil ini menggantikan apa sahaja
berada di sana sebelum ini. Secara amnya, anda mungkin tidak sepatutnya menggunakannya.
Jejak Bungkusan Talian nombor
Apabila anda mendapat ralat kompilasi, sama ada daripada kod seperti C anda atau kod Perl anda, ia boleh membantu
untuk membuat ralat tersebut kembali ke nombor baris dalam fail sumber di mana ralat itu
berlaku.
pp_line_numbers
Mengambil nombor baris dan rentetan kod (biasanya panjang). Nombor baris sepatutnya
nyatakan baris di mana petikan bermula. Ini biasanya "__LINE__" Perl
literal, melainkan anda menggunakan heredocs, dalam hal ini ia adalah "__LINE__ + 1". The
rentetan yang dikembalikan mempunyai arahan #baris yang diselingi untuk membantu pengkompil melaporkan ralat
pada baris yang betul.
Mengubahsuai yang Simbol Jadual and Eksport Kelakuan
PDL::PP biasanya mengeksport semua fungsi yang dijana menggunakan pp_def, dan biasanya memasangnya
ke dalam jadual simbol PDL. Walau bagaimanapun, anda boleh mengubah suai tingkah laku ini dengan fungsi ini.
pp_bless
Menetapkan pakej (jadual simbol) yang mana kod XS ditambahkan. Lalai ialah PDL,
yang secara amnya adalah apa yang anda mahukan. Jika anda menggunakan berkat lalai dan anda membuat a
fungsi myfunc, maka anda boleh melakukan perkara berikut:
$piddle->myfunc();
PDL::myfunc($piddle, );
Sebaliknya, jika anda memberkati fungsi anda ke dalam pakej lain, anda tidak boleh menggunakan
mereka sebagai kaedah PDL, dan mesti memanggilnya sebagai:
MyPackage::myfunc($piddle, );
Sudah tentu, anda sentiasa boleh menggunakan kekunci PMFunc untuk menambah fungsi anda pada simbol PDL
meja, tetapi mengapa berbuat demikian?
pp_add_isa
Menambah kepada senarai modul dari mana anda modul mewarisi. Senarai lalai ialah
qw(PDL::Pengeksport DynaLoader)
pp_core_importlist
Di bahagian atas fail .pm anda yang dijana ialah baris yang kelihatan seperti ini:
gunakan PDL::Core;
Anda boleh mengubah suai itu dengan menentukan rentetan kepada pp_core_importlist. Sebagai contoh,
pp_core_importlist('::Blarg');
akan menghasilkan
gunakan PDL::Core::Blarg;
Anda boleh menggunakan ini, sebagai contoh, untuk menambah senarai simbol untuk diimport daripada PDL::Core. Untuk
contoh:
pp_core_importlist(" ':Dalaman'");
akan membawa kepada pernyataan penggunaan berikut:
gunakan PDL::Core ':Internal';
pp_setversion
Tetapkan versi modul anda. Versi mesti konsisten antara .xs dan .pm
fail, dan digunakan untuk memastikan bahawa perpustakaan Perl anda tidak mengalami versi
senget.
pp_add_exported
Menambahkan pada senarai eksport apa sahaja nama yang anda berikan. Fungsi yang dibuat menggunakan pp_def
ditambah secara automatik ke senarai. Fungsi ini berguna jika anda menentukan sebarang Perl
fungsi menggunakan pp_addpm atau pp_addxs yang anda mahu eksport juga.
pp_eksport_nothing
Ini menetapkan semula senarai simbol yang dieksport kepada tiada. Ini mungkin lebih baik dipanggil
"pp_export_clear", kerana anda boleh menambah simbol yang dieksport selepas membuat panggilan
"pp_eksport_nothing". Apabila dipanggil sejurus sebelum memanggil pp_done, ini memastikan bahawa anda
modul tidak mengeksport apa-apa, sebagai contoh, jika anda hanya mahu pengaturcara menggunakan anda
berfungsi sebagai kaedah.
Gunakan PDL::PPp dalam talian menggunakan perkhidmatan onworks.net