GoGPT Best VPN GoSearch

favorit OnWorks

perlguts - Online di Cloud

Jalankan perlguts di penyedia hosting gratis OnWorks melalui Ubuntu Online, Fedora Online, emulator online Windows, atau emulator online MAC OS

Ini adalah perintah perlguts yang dapat dijalankan di penyedia hosting gratis OnWorks menggunakan salah satu dari beberapa workstation online gratis kami seperti Ubuntu Online, Fedora Online, emulator online Windows atau emulator online MAC OS

PROGRAM:

NAMA


perlguts - Pengantar Perl API

DESKRIPSI


Dokumen ini mencoba menjelaskan cara menggunakan Perl API, serta memberikan beberapa
info tentang cara kerja dasar dari inti Perl. Ini jauh dari lengkap dan mungkin
mengandung banyak kesalahan. Silakan merujuk pertanyaan atau komentar apa pun kepada penulis di bawah ini.

Variabel


Jenis data
Perl memiliki tiga typedef yang menangani tiga tipe data utama Perl:

Nilai Skalar SV
Nilai Array AV
Nilai Hash HV

Setiap typedef memiliki rutinitas khusus yang memanipulasi berbagai tipe data.

Apa is an "IV"?
Perl menggunakan tipe khusus IV yang merupakan tipe integer bertanda sederhana yang dijamin untuk
cukup besar untuk menampung pointer (serta integer). Selain itu, ada UV,
yang hanya merupakan IV yang tidak ditandatangani.

Perl juga menggunakan dua typedef khusus, I32 dan I16, yang akan selalu setidaknya 32-bit
dan panjang 16-bit, masing-masing. (Sekali lagi, ada U32 dan U16 juga.) Mereka akan
biasanya panjangnya tepat 32 dan 16 bit, tetapi pada Cray keduanya akan menjadi 64 bit.

Kerja dengan SV
SV dapat dibuat dan dimuat dengan satu perintah. Ada lima jenis nilai yang dapat
dimuat: nilai integer (IV), nilai integer yang tidak ditandatangani (UV), double (NV), string
(PV), dan skalar lainnya (SV). ("PV" adalah singkatan dari "Nilai Penunjuk". Anda mungkin berpikir bahwa itu
salah nama karena digambarkan hanya menunjuk ke string. Namun, itu mungkin
memilikinya menunjuk ke hal-hal lain. Misalnya, itu bisa menunjuk ke array UV. Tetapi,
menggunakannya untuk non-string membutuhkan kehati-hatian, karena asumsi yang mendasari sebagian besar
internal adalah bahwa PV hanya untuk string. Seringkali, misalnya, "NUL" di akhir adalah
ditempelkan secara otomatis. Penggunaan non-string hanya didokumentasikan dalam paragraf ini.)

Ketujuh rutinitas tersebut adalah:

SV* baruSViv(IV);
SV* baruSVuv(UV);
SV* baruSVnv(ganda);
SV* baruSVpv(const char*, STRLEN);
SV* baruSVpvn(const char*, STRLEN);
SV* baruSVpvf(const char*, ...);
SV* baruSVsv(SV*);

"STRLEN" adalah tipe integer (Ukuran_t, biasanya didefinisikan sebagai ukuran_t dalam konfigurasi.h) dijamin
cukup besar untuk mewakili ukuran string apa pun yang dapat ditangani oleh Perl.

Dalam kasus SV yang tidak mungkin membutuhkan inisialisasi yang lebih kompleks, Anda dapat membuat
SV kosong dengan newSV(len). Jika "len" adalah 0 SV kosong dari tipe NULL dikembalikan, jika tidak SV
dari tipe PV dikembalikan dengan len + 1 (untuk "NUL") byte penyimpanan yang dialokasikan, dapat diakses
melalui SvPVX. Dalam kedua kasus, SV memiliki nilai undef.

SV *sv = baruSV(0); /* tidak ada penyimpanan yang dialokasikan */
SV *sv = baruSV(10); /* 10 (+1) byte penyimpanan yang belum diinisialisasi
* dialokasikan */

Untuk mengubah nilai an sudah ada SV, ada delapan rutinitas:

batal sv_setiv(SV*, IV);
batal sv_setuv(SV*, UV);
batal sv_setnv(SV*, ganda);
batal sv_setpv(SV*, const char*);
batal sv_setpvn(SV*, const char*, STRLEN)
batal sv_setpvf(SV*, const char*, ...);
batal sv_vsetpvfn(SV*, const char*, STRLEN, va_list *,
SV**, I32, bool*);
batal sv_setsv(SV*, SV*);

Perhatikan bahwa Anda dapat memilih untuk menentukan panjang string yang akan ditetapkan dengan menggunakan
"sv_setpvn", "newSVpvn", atau "newSVpv", atau Anda dapat mengizinkan Perl menghitung panjangnya dengan
menggunakan "sv_setpv" atau dengan menetapkan 0 sebagai argumen kedua untuk "newSVpv". Diperingatkan,
meskipun, Perl itu akan menentukan panjang string dengan menggunakan "strlen", yang bergantung pada
string diakhiri dengan karakter "NUL", dan tidak mengandung NUL.

Argumen "sv_setpvf" diproses seperti "sprintf", dan output yang diformat
menjadi nilai.

"sv_vsetpvfn" adalah analog dari "vsprintf", tetapi memungkinkan Anda untuk menentukan salah satu pointer
ke daftar argumen variabel atau alamat dan panjang larik SV. Yang terakhir
argumen menunjuk ke boolean; saat kembali, jika boolean itu benar, maka khusus lokal
informasi telah digunakan untuk memformat string, dan oleh karena itu konten string adalah
tidak dapat dipercaya (lihat perlsec). Pointer ini mungkin NULL jika informasi itu tidak
penting. Perhatikan bahwa fungsi ini mengharuskan Anda untuk menentukan panjang format.

Fungsi "sv_set*()" tidak cukup umum untuk beroperasi pada nilai yang memiliki "ajaib".
Lihat "Tabel Virtual Ajaib" nanti di dokumen ini.

Semua SV yang berisi string harus diakhiri dengan karakter "NUL". Jika tidak
"NUL"-dihentikan ada risiko dump inti dan korupsi dari kode yang melewati
string ke fungsi C atau panggilan sistem yang mengharapkan string diakhiri "NUL". milik Perl
fungsi biasanya menambahkan "NUL" di akhir untuk alasan ini. Namun demikian, Anda harus
sangat berhati-hati ketika Anda meneruskan string yang disimpan dalam SV ke fungsi C atau panggilan sistem.

Untuk mengakses nilai aktual yang ditunjuk oleh SV, Anda dapat menggunakan makro:

SvV(SV*)
SVUV(SV*)
SvNV(SV*)
SvPV(SV*, STRLEN len)
SvPV_nolen(SV*)

yang secara otomatis akan memaksa jenis skalar yang sebenarnya menjadi IV, UV, ganda, atau string.

Dalam makro "SvPV", panjang string yang dikembalikan ditempatkan ke dalam variabel "len"
(ini adalah makro, jadi Anda melakukannya tidak gunakan & len). Jika Anda tidak peduli berapa panjang datanya
adalah, gunakan makro "SvPV_nolen". Secara historis makro "SvPV" dengan variabel global
"PL_na" telah digunakan dalam kasus ini. Tapi itu bisa sangat tidak efisien karena "PL_na"
harus diakses di penyimpanan lokal-utas di Perl berulir. Bagaimanapun, ingatlah itu
Perl memungkinkan string data sewenang-wenang yang mungkin berisi NUL dan mungkin tidak
diakhiri dengan "NUL".

Juga ingat bahwa C tidak mengizinkan Anda untuk mengatakan "foo(SvPV(s, len), len);". Itu mungkin
bekerja dengan kompiler Anda, tetapi itu tidak akan berfungsi untuk semua orang. Hancurkan pernyataan semacam ini
menjadi tugas terpisah:

SV *s;
STRLEN;
karakter *ptr;
ptr = SvPV(s, len);
foo(ptr, len);

Jika Anda ingin tahu apakah nilai skalarnya BENAR, Anda dapat menggunakan:

Sv BENAR(SV*)

Meskipun Perl akan secara otomatis menumbuhkan string untuk Anda, jika Anda perlu memaksa Perl untuk
mengalokasikan lebih banyak memori untuk SV Anda, Anda dapat menggunakan makro

SvGROW(SV*, STRLEN baru)

yang akan menentukan apakah lebih banyak memori perlu dialokasikan. Jika demikian, itu akan memanggil
fungsi "sv_grow". Perhatikan bahwa "SvGROW" hanya dapat menambah, tidak mengurangi, alokasi
memori SV dan itu tidak secara otomatis menambahkan ruang untuk byte "NUL" yang tertinggal
(Fungsi string Perl sendiri biasanya melakukan "SvGROW(sv, len + 1)").

Jika Anda ingin menulis ke buffer SV yang ada dan menetapkan nilainya ke string, gunakan
SvPV_force() atau salah satu variannya untuk memaksa SV menjadi PV. Ini akan menghapus salah satu dari
berbagai jenis non-stringness dari SV sambil mempertahankan konten SV di
PV. Ini dapat digunakan, misalnya, untuk menambahkan data dari fungsi API ke buffer
tanpa penyalinan tambahan:

(batal)SvPVbyte_force(sv, len);
s = SvGROW(sv, len + jarum + 1);
/* sesuatu yang memodifikasi hingga byte jarum di s+len, tapi
memodifikasi byte newlen
misalnya. newlen = baca(fd, s + len, jarum);
mengabaikan kesalahan untuk contoh-contoh ini
*/
s[len + barulen] = '\0';
SvCUR_set(sv, len + newlen);
SvUTF8_off(sv);
SvSETMAGIC(sv);

Jika Anda sudah memiliki data di memori atau jika Anda ingin membuat kode Anda tetap sederhana, Anda bisa
gunakan salah satu varian sv_cat*(), seperti sv_catpvn(). Jika Anda ingin menyisipkan di mana saja di
string yang dapat Anda gunakan sv_masukkan() or sv_insert_flags().

Jika Anda tidak memerlukan konten SV yang ada, Anda dapat menghindari penyalinan dengan:

sv_setpvn(sv, "", 0);
s = SvGROW(sv, jarum + 1);
/* sesuatu yang memodifikasi hingga byte jarum di s, tetapi memodifikasi
byte baru
misalnya. newlen = baca(fd, s. jarum);
*/
s[newlen] = '\0';
SvCUR_set(sv, newlen);
SvPOK_only(sv); /* juga menghapus SVf_UTF8 */
SvSETMAGIC(sv);

Sekali lagi, jika Anda sudah memiliki data di memori atau ingin menghindari kerumitan
di atas, Anda dapat menggunakan sv_setpvn().

Jika Anda memiliki buffer yang dialokasikan dengan Baru() dan ingin menetapkannya sebagai nilai SV, Anda bisa
menggunakan sv_usepvn_flags(). Itu memiliki beberapa persyaratan jika Anda ingin menghindari alokasi ulang Perl
buffer agar sesuai dengan NUL tambahan:

Newx(buf, beberapa ukuran+1, char);
/* ... isi buf ... */
buf[berukuran] = '\0';
sv_usepvn_flags(sv, buf, beberapa ukuran, SV_SMAGIC | SV_HAS_TRAILING_NUL);
/* buf sekarang milik perl, jangan dilepas */

Jika Anda memiliki SV dan ingin tahu jenis data apa yang menurut Perl disimpan di dalamnya, Anda bisa
gunakan makro berikut untuk memeriksa jenis SV yang Anda miliki.

SVIOK(SV*)
SvNOK(SV*)
SvPOK(SV*)

Anda bisa mendapatkan dan mengatur panjang string saat ini yang disimpan dalam SV dengan yang berikut:
makro:

SvCUR(SV*)
SvCUR_set(SV*, nilai I32)

Anda juga bisa mendapatkan pointer ke akhir string yang disimpan di SV dengan makro:

SvEND(SV*)

Tetapi perhatikan bahwa tiga makro terakhir ini hanya valid jika "SvPOK()" benar.

Jika Anda ingin menambahkan sesuatu ke akhir string yang disimpan dalam "SV*", Anda dapat menggunakan
fungsi berikut:

batal sv_catpv(SV*, const char*);
batal sv_catpvn(SV*, const char*, STRLEN);
batal sv_catpvf(SV*, const char*, ...);
batal sv_vcatpvfn(SV*, const char*, STRLEN, va_list *, SV **,
I32, bo);
batal sv_catsv(SV*, SV*);

Fungsi pertama menghitung panjang string yang akan ditambahkan dengan menggunakan "strlen".
Di bagian kedua, Anda menentukan sendiri panjang string. Fungsi ketiga
memproses argumennya seperti "sprintf" dan menambahkan output yang diformat. Yang keempat
fungsi berfungsi seperti "vsprintf". Anda dapat menentukan alamat dan panjang array SVs
alih-alih argumen va_list. Fungsi kelima memperluas string yang disimpan di
SV pertama dengan string yang disimpan di SV kedua. Itu juga memaksa SV kedua menjadi
ditafsirkan sebagai string.

Fungsi "sv_cat*()" tidak cukup umum untuk beroperasi pada nilai yang memiliki "ajaib".
Lihat "Tabel Virtual Ajaib" nanti di dokumen ini.

Jika Anda mengetahui nama variabel skalar, Anda bisa mendapatkan pointer ke SV-nya dengan menggunakan
sebagai berikut:

SV* get_sv("paket::varname", 0);

Ini mengembalikan NULL jika variabel tidak ada.

Jika Anda ingin tahu apakah variabel ini (atau SV lainnya) sebenarnya "didefinisikan", Anda bisa
hubungi:

SvOK(SV*)

Nilai skalar "undef" disimpan dalam instance SV yang disebut "PL_sv_undef".

Alamatnya dapat digunakan kapan pun "SV*" diperlukan. Pastikan Anda tidak mencoba
bandingkan sv acak dengan &PL_sv_undef. Misalnya saat menghubungkan kode Perl, itu akan berfungsi
dengan benar untuk:

foo(def);

Tetapi tidak akan berfungsi saat dipanggil sebagai:

$x = tidak pasti;
fo($x);

Jadi untuk mengulang selalu gunakan SvOK() untuk memeriksa apakah sv didefinisikan.

Anda juga harus berhati-hati saat menggunakan &PL_sv_undef sebagai nilai dalam AV atau HV (lihat "AV,
HV dan nilai yang tidak ditentukan").

Ada juga dua nilai "PL_sv_yes" dan "PL_sv_no", yang berisi boolean TRUE dan
nilai FALSE, masing-masing. Seperti "PL_sv_undef", alamat mereka dapat digunakan kapanpun dan
"SV*" diperlukan.

Jangan tertipu dengan berpikir bahwa "(SV *) 0" sama dengan &PL_sv_undef. Ambil ini
kode:

SV* sv = (SV*) 0;
if (Saya-untuk-mengembalikan-nilai-nyata) {
sv = sv_2fana(baruSViv(42));
}
sv_setsv(ST(0), sv);

Kode ini mencoba mengembalikan SV baru (yang berisi nilai 42) jika seharusnya mengembalikan a
nilai riil, atau undef sebaliknya. Sebaliknya ia telah mengembalikan pointer NULL yang, di suatu tempat
di telepon, akan menyebabkan pelanggaran segmentasi, kesalahan bus, atau hanya hasil yang aneh.
Ubah nol menjadi &PL_sv_undef di baris pertama dan semuanya akan baik-baik saja.

Untuk membebaskan SV yang telah Anda buat, panggil "SvREFCNT_dec(SV*)". Biasanya panggilan ini tidak
diperlukan (lihat "Jumlah Referensi dan Kematian").

Offset
Perl menyediakan fungsi "sv_chop" untuk menghapus karakter secara efisien dari awal
dari sebuah string; Anda memberinya SV dan penunjuk ke suatu tempat di dalam PV, dan itu dibuang
semuanya sebelum penunjuk. Efisiensi datang melalui sedikit peretasan: alih-alih
benar-benar menghapus karakter, "sv_chop" menetapkan bendera "OOK" (offset OK) untuk memberi sinyal
fungsi lain yang dilakukan oleh peretasan offset, dan itu menggerakkan penunjuk PV (disebut
"SvPVX") maju dengan jumlah byte yang dipotong, dan menyesuaikan "SvCUR" dan "SvLEN"
demikian. (Sebagian dari ruang antara pointer PV lama dan baru digunakan untuk menyimpan
jumlah byte yang dipotong.)

Oleh karena itu, pada titik ini, awal buffer yang kami alokasikan hidup di "SvPVX(sv) -
SvIV(sv)" di memori dan penunjuk PV menunjuk ke tengah alokasi ini
penyimpanan.

Ini paling baik ditunjukkan dengan contoh. Biasanya copy-on-write akan mencegah
substitusi dari operator dari menggunakan peretasan ini, tetapi jika Anda dapat membuat string yang
copy-on-write tidak dimungkinkan, Anda dapat melihatnya dalam permainan. Dalam implementasi saat ini,
byte terakhir dari buffer string digunakan sebagai jumlah referensi copy-on-write. Jika penyangga
tidak cukup besar, maka copy-on-write akan dilewati. Pertama lihat string kosong:

% ./perl -Ilib -MDevel::Peek -le '$a=""; $a.= ""; Buang $a'
SV = PV(0x7ffb7c008a70) at 0x7ffb7c030390
REFCNT = 1
BENDERA = (POK,pPOK)
PV = 0x7ffb7bc05b50 ""\0
kur = 0
LEN = 10

Perhatikan di sini LEN adalah 10. (Ini mungkin berbeda pada platform Anda.) Perpanjang panjangnya
string ke satu kurang dari 10, dan lakukan substitusi:

% ./perl -Ilib -MDevel::Peek -le '$a=""; $a.="123456789"; $a=~s/.//; Buang($a)'
SV = PV(0x7ffa04008a70) at 0x7ffa04030390
REFCNT = 1
BENDERA = (POK,OOK,pPOK)
OFFSET = 1
PV = 0x7ffa03c05b61 ( "\1" . ) "23456789"\0
kur = 8
LEN = 9

Di sini jumlah byte yang dipotong (1) ditampilkan berikutnya sebagai OFFSET. Bagian dari
string antara awalan "asli" dan "palsu" ditampilkan dalam tanda kurung, dan
nilai "SvCUR" dan "SvLEN" mencerminkan awal yang palsu, bukan yang asli. (Pertama
karakter buffer string kebetulan telah berubah menjadi "\1" di sini, bukan "1", karena
implementasi saat ini menyimpan jumlah offset dalam buffer string. Ini tunduk pada
mengubah.)

Sesuatu yang mirip dengan peretasan offset dilakukan pada AV untuk memungkinkan pemindahan yang efisien dan
splicing dari awal array; sementara "AvARRAY" menunjuk ke elemen pertama di
array yang terlihat dari Perl, "AvALLOC" menunjuk ke awal sebenarnya dari array C.
Ini biasanya sama, tetapi operasi "shift" dapat dilakukan dengan meningkatkan
"AvARRAY" satu per satu dan mengurangi "AvFILL" dan "AvMAX". Sekali lagi, lokasi aslinya
awal dari array C hanya ikut bermain saat membebaskan array. Lihat "av_shift" di av.c.

Apa Benar-benar Disimpan in an SV?
Ingatlah bahwa metode biasa untuk menentukan jenis skalar yang Anda miliki adalah dengan menggunakan "Sv*OK"
makro. Karena skalar dapat berupa angka dan string, biasanya makro ini akan
selalu mengembalikan TRUE dan memanggil makro "Sv*V" akan melakukan konversi yang sesuai dari
string ke integer/ganda atau integer/ganda ke string.

Jika kamu benar-benar perlu tahu apakah Anda memiliki pointer integer, double, atau string dalam SV, Anda
dapat menggunakan tiga makro berikut sebagai gantinya:

SVIOKp(SV*)
SvNOKp(SV*)
SvPOKp(SV*)

Ini akan memberi tahu Anda jika Anda benar-benar memiliki pointer integer, double, atau string yang disimpan di . Anda
SV Huruf "p" berarti pribadi.

Ada berbagai cara di mana bendera pribadi dan publik mungkin berbeda. Misalnya, di
perl 5.16 dan sebelumnya, SV yang diikat mungkin memiliki nilai dasar yang valid di slot IV (jadi
SvIOKp benar), tetapi data harus diakses melalui rutin FETCH daripada
langsung, jadi SvIOK salah. (Dalam Perl 5.18 dan seterusnya, skalar terikat menggunakan bendera yang sama
cara seperti skalar tak terikat.) Lain adalah ketika konversi numerik telah terjadi dan presisi telah
telah hilang: hanya bendera pribadi yang disetel pada nilai 'lossy'. Jadi ketika NV diubah menjadi
IV dengan kehilangan, SvIOKp, SvNOKp dan SvNOK akan disetel, sedangkan SvIOK tidak.

Namun, secara umum, yang terbaik adalah menggunakan makro "Sv*V".

Kerja dengan AV
Ada dua cara untuk membuat dan memuat AV. Metode pertama membuat AV kosong:

AV* baruAV();

Metode kedua membuat AV dan awalnya mengisinya dengan SV:

AV* av_make(Size_t num, SV **ptr);

Argumen kedua menunjuk ke array yang berisi "num" "SV*". Setelah AV telah
dibuat, SV dapat dihancurkan, jika diinginkan.

Setelah AV dibuat, operasi berikut dapat dilakukan di dalamnya:

batal av_push(AV*, SV*);
SV* av_pop(AV*);
SV* av_shift(AV*);
void av_unshift(AV*, SSsize_t num);

Ini harus merupakan operasi yang sudah dikenal, dengan pengecualian "av_unshift". Rutinitas ini
menambahkan elemen "num" di depan array dengan nilai "undef". Anda kemudian harus menggunakan
"av_store" (dijelaskan di bawah) untuk menetapkan nilai ke elemen baru ini.

Berikut beberapa fungsi lainnya:

SSsize_t av_top_index(AV*);
SV** av_fetch(AV*, kunci SSize_t, I32 lval);
SV** av_store(AV*, kunci SSize_t, SV* val);

Fungsi "av_top_index" mengembalikan nilai indeks tertinggi dalam larik (seperti $#array
di Perl). Jika array kosong, -1 dikembalikan. Fungsi "av_fetch" mengembalikan
nilai pada indeks "kunci", tetapi jika "lval" bukan nol, maka "av_fetch" akan menyimpan nilai undef
pada indeks itu. Fungsi "av_store" menyimpan nilai "val" pada indeks "kunci", dan melakukan
tidak menambah jumlah referensi "val". Dengan demikian penelepon bertanggung jawab untuk mengambil
perhatikan itu, dan jika "av_store" mengembalikan NULL, penelepon harus mengurangi
jumlah referensi untuk menghindari kebocoran memori. Perhatikan bahwa "av_fetch" dan "av_store" keduanya kembali
"SV**", bukan "SV*" sebagai nilai pengembaliannya.

Beberapa lagi:

batalkan av_clear(AV*);
batalkan av_undef(AV*);
void av_extend(AV*, kunci SSize_t);

Fungsi "av_clear" menghapus semua elemen dalam larik AV*, tetapi sebenarnya tidak
menghapus array itu sendiri. Fungsi "av_undef" akan menghapus semua elemen di
array ditambah array itu sendiri. Fungsi "av_extend" memperluas array sehingga
berisi setidaknya elemen "kunci+1". Jika "kunci +1" kurang dari yang dialokasikan saat ini
panjang array, maka tidak ada yang dilakukan.

Jika Anda mengetahui nama variabel array, Anda bisa mendapatkan pointer ke AV-nya dengan menggunakan
sebagai berikut:

AV* get_av("paket::varname", 0);

Ini mengembalikan NULL jika variabel tidak ada.

Lihat "Memahami Keajaiban Hash dan Array Terikat" untuk informasi lebih lanjut tentang cara menggunakan
fungsi akses array pada array terikat.

Kerja dengan HV
Untuk membuat HV, Anda menggunakan rutinitas berikut:

HV* baruHV();

Setelah HV dibuat, operasi berikut dapat dilakukan di dalamnya:

SV** hv_store(HV*, kunci const char*, klen U32, val SV*, hash U32);
SV** hv_fetch(HV*, kunci const char*, U32 klen, I32 lval);

Parameter "klen" adalah panjang kunci yang diteruskan (Perhatikan bahwa Anda tidak dapat melewati 0
di sebagai nilai "klen" untuk memberitahu Perl untuk mengukur panjang kunci). "val"
argumen berisi pointer SV ke skalar yang disimpan, dan "hash" adalah yang dihitung sebelumnya
nilai hash (nol jika Anda ingin "hv_store" menghitungnya untuk Anda). Parameter "lval"
menunjukkan apakah pengambilan ini sebenarnya merupakan bagian dari operasi penyimpanan, dalam hal ini yang baru
nilai yang tidak ditentukan akan ditambahkan ke HV dengan kunci yang disediakan dan "hv_fetch" akan kembali
seolah-olah nilainya sudah ada.

Ingat bahwa "hv_store" dan "hv_fetch" mengembalikan "SV**" dan bukan hanya "SV*". Untuk mengakses
nilai skalar, Anda harus terlebih dahulu melakukan dereferensi nilai kembalian. Namun, Anda harus memeriksa ke
pastikan bahwa nilai yang dikembalikan bukan NULL sebelum melakukan dereferensi.

Yang pertama dari dua fungsi ini memeriksa apakah ada entri tabel hash, dan yang kedua
menghapusnya.

bool hv_exists(HV*, kunci const char*, klen U32);
SV* hv_delete(HV*, kunci const char*, klen U32, flag I32);

Jika "flags" tidak menyertakan flag "G_DISCARD" maka "hv_delete" akan membuat dan mengembalikan
salinan fana dari nilai yang dihapus.

Dan lebih banyak fungsi lain-lain:

batal hv_clear(HV*);
batal hv_undef(HV*);

Seperti rekan-rekan AV mereka, "hv_clear" menghapus semua entri di tabel hash tetapi tidak
tidak benar-benar menghapus tabel hash. "hv_undef" menghapus entri dan hash
meja itu sendiri.

Perl menyimpan data aktual dalam daftar struktur yang ditautkan dengan typedef HE. Ini
berisi kunci aktual dan penunjuk nilai (ditambah overhead administratif tambahan). Kunci
adalah penunjuk string; nilainya adalah "SV*". Namun, setelah Anda memiliki "HE*", untuk mendapatkan
kunci dan nilai aktual, gunakan rutinitas yang ditentukan di bawah ini.

I32 hv_iterinit(HV*);
/* Mempersiapkan titik awal untuk melintasi tabel hash */
DIA* hv_iternext(HV*);
/* Dapatkan entri berikutnya, dan kembalikan pointer ke a
struktur yang memiliki kunci dan nilai */
char* hv_iterkey(HE* entri, I32* retlen);
/* Dapatkan kunci dari struktur HE dan juga kembali
panjang string kunci */
SV* hv_iterval(HV*, HE* masuk);
/* Mengembalikan pointer SV ke nilai HE
struktur */
SV* hv_iternextsv(HV*, kunci char**, I32* retlen);
/* Rutinitas kenyamanan ini menggabungkan hv_iternext,
hv_iterkey, dan hv_iterval. Kunci dan retlen
argumen adalah nilai balik untuk kunci dan
panjang. Nilai dikembalikan dalam argumen SV* */

Jika Anda mengetahui nama variabel hash, Anda bisa mendapatkan pointer ke HV-nya dengan menggunakan
sebagai berikut:

HV* get_hv("paket::varname", 0);

Ini mengembalikan NULL jika variabel tidak ada.

Algoritma hash didefinisikan dalam makro "PERL_HASH":

PERL_HASH(hash, kunci, klen)

Implementasi yang tepat dari makro ini bervariasi menurut arsitektur dan versi Perl, dan
nilai kembalian dapat berubah per pemanggilan, jadi nilainya hanya valid selama durasi a
proses perl tunggal.

Lihat "Memahami Keajaiban Hash dan Array Terikat" untuk informasi lebih lanjut tentang cara menggunakan
fungsi akses hash pada hash terikat.

Hash API Ekstensi
Dimulai dengan versi 5.004, fungsi berikut juga didukung:

HE* hv_fetch_ent (HV* tb, kunci SV*, I32 lval, hash U32);
HE* hv_store_ent (HV* tb, kunci SV*, SV* val, hash U32);

bool hv_exists_ent (HV* tb, kunci SV*, hash U32);
SV* hv_delete_ent (HV* tb, kunci SV*, flag I32, hash U32);

SV* hv_iterkeysv (entri HE*);

Perhatikan bahwa fungsi-fungsi ini menggunakan tombol "SV*", yang menyederhanakan penulisan kode ekstensi yang
berurusan dengan struktur hash. Fungsi-fungsi ini juga memungkinkan penerusan kunci "SV*" ke "tie"
berfungsi tanpa memaksa Anda untuk merangkai kunci (tidak seperti set sebelumnya dari
fungsi).

Mereka juga mengembalikan dan menerima seluruh entri hash ("HE*"), membuat penggunaannya lebih efisien
(karena nomor hash untuk string tertentu tidak harus dihitung ulang setiap saat).
Lihat perlapi untuk penjelasan rinci.

Makro berikut harus selalu digunakan untuk mengakses konten entri hash. Catatan
bahwa argumen untuk makro ini harus berupa variabel sederhana, karena mereka dapat dievaluasi
lebih dari sekali. Lihat perlapi untuk penjelasan rinci tentang makro ini.

HePV(DIA* dia, STRLEN len)
HeVAL(DIA* dia)
HEHASH(DIA* dia)
HeSVKEY(DIA* dia)
DiaSVKEY_force(DIA* dia)
HeSVKEY_set(DIA* dia, SV* sv)

Kedua makro tingkat yang lebih rendah ini ditentukan, tetapi hanya boleh digunakan ketika berhadapan dengan kunci
yang bukan "SV*":

HeKEY(DIA* dia)
HeKLEN(DIA* dia)

Perhatikan bahwa baik "hv_store" dan "hv_store_ent" tidak menambah jumlah referensi dari
disimpan "val", yang merupakan tanggung jawab pemanggil. Jika fungsi-fungsi ini mengembalikan NULL
nilai, penelepon biasanya harus mengurangi jumlah referensi "val" untuk menghindari a
kebocoran memori.

AV, HV dan tidak terdefinisi nilai-nilai
Terkadang Anda harus menyimpan nilai yang tidak ditentukan dalam AV atau HV. Meskipun ini mungkin langka
kasus, itu bisa rumit. Itu karena Anda terbiasa menggunakan &PL_sv_undef jika Anda membutuhkan
SV tidak terdefinisi

Misalnya, intuisi memberi tahu Anda bahwa kode XS ini:

AV *av = baruAV();
av_store( av, 0, &PL_sv_undef );

setara dengan kode Perl ini:

@av saya;
$av[0] = tidak pasti;

Sayangnya, ini tidak benar. Di Perl 5.18 dan sebelumnya, AV menggunakan &PL_sv_undef sebagai
penanda untuk menunjukkan bahwa elemen array belum diinisialisasi. Jadi, "ada
$av[0]" akan benar untuk kode Perl di atas, tetapi salah untuk larik yang dihasilkan oleh XS
kode. Di Perl 5.20, menyimpan &PL_sv_undef akan membuat elemen hanya-baca, karena
skalar &PL_sv_undef sendiri disimpan, bukan salinan.

Masalah serupa dapat terjadi saat menyimpan &PL_sv_undef di HV:

hv_store( hv, "kunci", 3, &PL_sv_undef, 0 );

Ini memang akan membuat nilai "undef", tetapi jika Anda mencoba mengubah nilai "kunci",
Anda akan mendapatkan kesalahan berikut:

Modifikasi nilai hash yang tidak dapat dibuat dicoba

Di Perl 5.8.0, &PL_sv_undef juga digunakan untuk menandai placeholder dalam hash terbatas. Ini
menyebabkan entri hash tersebut tidak muncul saat mengulangi hash atau saat memeriksa
tombol dengan fungsi "hv_exists".

Anda dapat mengalami masalah serupa saat menyimpan &PL_sv_yes atau &PL_sv_no ke dalam AV atau HV.
Mencoba memodifikasi elemen tersebut akan memberi Anda kesalahan berikut:

Modifikasi nilai read-only dicoba

Untuk mempersingkat cerita, Anda dapat menggunakan variabel khusus &PL_sv_undef, &PL_sv_yes dan
&PL_sv_no dengan AV dan HV, tetapi Anda harus memastikan bahwa Anda tahu apa yang Anda lakukan.

Umumnya, jika Anda ingin menyimpan nilai yang tidak ditentukan dalam AV atau HV, Anda sebaiknya tidak menggunakan
&PL_sv_undef, melainkan buat nilai baru yang tidak ditentukan menggunakan fungsi "newSV", untuk
contoh:

av_toko( av, 42, baruSV(0) );
hv_store( hv, "foo", 3, baruSV(0), 0 );

Referensi
Referensi adalah tipe skalar khusus yang menunjuk ke tipe data lain (termasuk
referensi).

Untuk membuat referensi, gunakan salah satu fungsi berikut:

SV* newRV_inc((SV*) hal);
SV* newRV_noinc((SV*) hal);

Argumen "hal" dapat berupa "SV*", "AV*", atau "HV*". Fungsinya identik
kecuali bahwa "newRV_inc" menambah jumlah referensi dari "benda", sementara "newRV_noinc"
tidak. Untuk alasan historis, "newRV" adalah sinonim untuk "newRV_inc".

Setelah Anda memiliki referensi, Anda dapat menggunakan makro berikut untuk melakukan dereferensi referensi:

SvRV(SV*)

lalu panggil rutinitas yang sesuai, casting "SV*" yang dikembalikan ke "AV*" atau
"HV*", jika diperlukan.

Untuk menentukan apakah SV adalah referensi, Anda dapat menggunakan makro berikut:

SvROK(SV*)

Untuk menemukan jenis nilai yang dirujuk oleh referensi, gunakan makro berikut dan kemudian
memeriksa nilai kembali.

SvTYPE(SvRV(SV*))

Jenis yang paling berguna yang akan dikembalikan adalah:

< SVt_PVAV Skalar
Array SVt_PVAV
SVt_PVHV Hash
Kode SVt_PVCV
SVt_PVGV Glob (mungkin pegangan file)

Lihat "svtype" di perlapi untuk lebih jelasnya.

Diberkati Referensi dan Kelas benda
Referensi juga digunakan untuk mendukung pemrograman berorientasi objek. Dalam kamus OO Perl, an
objek hanyalah referensi yang telah diberkati ke dalam paket (atau kelas). Sekali
diberkati, programmer sekarang dapat menggunakan referensi untuk mengakses berbagai metode di
kelas.

Referensi dapat diberkati ke dalam paket dengan fungsi berikut:

SV* sv_bless(SV* sv, HV* simpanan);

Argumen "sv" harus berupa nilai referensi. Argumen "simpanan" menentukan kelas mana
referensi akan menjadi milik. Lihat "Simpanan dan Gumpalan" untuk informasi tentang mengonversi kelas
nama menjadi simpanan.

/* Masih dalam pembangunan */

Fungsi berikut memutakhirkan rv ke referensi jika belum memilikinya. Membuat SV baru untuk
rv untuk menunjuk. Jika "nama kelas" bukan nol, SV diberkati ke dalam kelas yang ditentukan.
SV dikembalikan.

SV* newSVrv(SV* rv, const char* nama kelas);

Tiga fungsi berikut menyalin integer, unsigned integer atau double ke dalam SV yang
referensi adalah "rv". SV diberkati jika "nama kelas" bukan nol.

SV* sv_setref_iv(SV* rv, const char* nama kelas, IV iv);
SV* sv_setref_uv(SV* rv, const char* nama kelas, UV uv);
SV* sv_setref_nv(SV* rv, const char* nama kelas, NV iv);

Fungsi berikut menyalin nilai pointer (itu alamat, tidak itu rangkaian!) menjadi SV
yang referensinya adalah rv. SV diberkati jika "nama kelas" bukan nol.

SV* sv_setref_pv(SV* rv, const char* nama kelas, void* pv);

Fungsi berikut menyalin string ke dalam SV yang referensinya adalah "rv". Setel panjang ke
0 untuk membiarkan Perl menghitung panjang string. SV diberkati jika "nama kelas" bukan nol.

SV* sv_setref_pvn(SV* rv, const char* nama kelas, char* pv,
panjang STRLEN);

Fungsi berikut menguji apakah SV diberkati ke dalam kelas yang ditentukan. memang
tidak memeriksa hubungan warisan.

int sv_isa(SV* sv, const char* nama);

Fungsi berikut menguji apakah SV adalah referensi ke objek yang diberkati.

int sv_isobject(SV* sv);

Fungsi berikut menguji apakah SV diturunkan dari kelas yang ditentukan. SV bisa
menjadi referensi ke objek yang diberkati atau string yang berisi nama kelas. Ini
fungsi yang mengimplementasikan fungsi "UNIVERSAL::isa".

bool sv_derived_from(SV* sv, const char* nama);

Untuk memeriksa apakah Anda memiliki objek yang diturunkan dari kelas tertentu, Anda harus menulis:

if (sv_isobject(sv) && sv_derived_from(sv, class)) { ... }

membuat New Variabel
Untuk membuat variabel Perl baru dengan nilai undef yang dapat diakses dari Perl
script, gunakan rutinitas berikut, tergantung pada jenis variabel.

SV* get_sv("paket::varname", GV_ADD);
AV* get_av("paket::varname", GV_ADD);
HV* get_hv("paket::varname", GV_ADD);

Perhatikan penggunaan GV_ADD sebagai parameter kedua. Variabel baru sekarang dapat diatur, menggunakan
rutinitas yang sesuai dengan tipe data.

Ada makro tambahan yang nilainya mungkin bitwise ATAU dengan argumen "GV_ADD"
untuk mengaktifkan fitur tambahan tertentu. Bit-bit itu adalah:

GV_ADDMULTI
Menandai variabel sebagai definisi perkalian, sehingga mencegah:

Nama hanya digunakan sekali: kemungkinan salah ketik

peringatan.

GV_ADDPERINGATAN
Mengeluarkan peringatan:

Harus membuat tiba-tiba

jika variabel tidak ada sebelum fungsi dipanggil.

Jika Anda tidak menentukan nama paket, variabel dibuat dalam paket saat ini.

Referensi hitungan dan Mortalitas
Perl menggunakan mekanisme pengumpulan sampah berdasarkan jumlah referensi. SV, AV, atau HV (xV untuk
singkat berikut) memulai hidup mereka dengan hitungan referensi 1. Jika referensi
hitungan xV pernah turun ke 0, maka itu akan dihancurkan dan memorinya tersedia
untuk digunakan kembali.

Ini biasanya tidak terjadi pada level Perl kecuali sebuah variabel tidak terdefinisi atau yang terakhir
variabel memegang referensi untuk itu diubah atau ditimpa. Di tingkat internal,
namun, jumlah referensi dapat dimanipulasi dengan makro berikut:

int SvREFCNT(SV*sv);
SV* SvREFCNT_inc(SV* sv);
batal SvREFCNT_dec(SV* sv);

Namun, ada satu fungsi lain yang memanipulasi jumlah referensinya
argumen. Fungsi "newRV_inc", Anda akan ingat, membuat referensi ke yang ditentukan
argumen. Sebagai efek samping, ini menambah jumlah referensi argumen. Jika ini tidak
apa yang Anda inginkan, gunakan "newRV_noinc" sebagai gantinya.

Misalnya, bayangkan Anda ingin mengembalikan referensi dari fungsi XSUB. Di dalam
Rutin XSUB, Anda membuat SV yang awalnya memiliki jumlah referensi satu. Terus Anda
panggil "newRV_inc", meneruskannya ke SV yang baru saja dibuat. Ini mengembalikan referensi sebagai SV baru,
tetapi jumlah referensi SV yang Anda berikan ke "newRV_inc" telah bertambah menjadi dua.
Sekarang Anda mengembalikan referensi dari rutinitas XSUB dan melupakan SV. Tapi Perl
belum! Setiap kali referensi yang dikembalikan dihancurkan, jumlah referensi yang asli
SV dikurangi menjadi satu dan tidak ada yang terjadi. SV akan berkeliaran tanpa cara apa pun untuk
mengaksesnya sampai Perl itu sendiri berakhir. Ini adalah kebocoran memori.

Maka, prosedur yang benar adalah menggunakan "newRV_noinc" alih-alih "newRV_inc". Kemudian, jika dan
ketika referensi terakhir dihancurkan, jumlah referensi SV akan menjadi nol dan itu
akan dihancurkan, menghentikan kebocoran memori.

Ada beberapa fungsi kenyamanan yang tersedia yang dapat membantu dengan penghancuran xVs.
Fungsi-fungsi ini memperkenalkan konsep "kematian". Sebuah xV yang fana telah memiliki
jumlah referensi ditandai untuk dikurangi, tetapi tidak benar-benar dikurangi, sampai "pendek
waktu kemudian". Umumnya istilah "singkat waktu kemudian" berarti pernyataan Perl tunggal, seperti
panggilan ke fungsi XSUB. Penentu aktual kapan xV fana memiliki
jumlah referensi berkurang tergantung pada dua makro, SAVETMPS dan FREETMPS. Lihat perlcall
dan perlxs untuk detail lebih lanjut tentang makro ini.

"Kematian" kemudian paling sederhana adalah "SvREFCNT_dec" yang ditangguhkan. Namun, jika Anda
mematikan variabel dua kali, jumlah referensi nantinya akan dikurangi dua kali.

SV "Mortal" terutama digunakan untuk SV yang ditempatkan di tumpukan Perl. Misalnya SV
yang dibuat hanya untuk memberikan nomor ke sub yang dipanggil dibuat fana untuk dibersihkan
secara otomatis ketika itu muncul dari tumpukan. Demikian pula, hasil yang dikembalikan oleh XSUBs
(yang didorong di tumpukan) sering dibuat fana.

Untuk membuat variabel fana, gunakan fungsi:

SV* sv_newmortal()
SV* sv_2fana(SV*)
SV* sv_mortalcopy(SV*)

Panggilan pertama membuat SV fana (tanpa nilai), yang kedua mengubah SV yang ada menjadi
SV fana (dan dengan demikian menunda panggilan ke "SvREFCNT_dec"), dan yang ketiga membuat fana
salinan SV yang ada. Karena "sv_newmortal" tidak memberi nilai pada SV baru, itu harus
biasanya diberikan melalui "sv_setpv", "sv_setiv", dll. :

SV *tmp = sv_newmortal();
sv_setiv(tmp, an_integer);

Karena itu adalah beberapa pernyataan C, itu cukup umum jadi lihat idiom ini sebagai gantinya:

SV *tmp = sv_2mortal(newSViv(an_integer));

Anda harus berhati-hati dalam membuat variabel fana. Hal-hal aneh bisa terjadi jika Anda
buat nilai yang sama fana dalam berbagai konteks, atau jika Anda membuat variabel fana
beberapa kali. Memikirkan "Kematian" sebagai "SvREFCNT_dec" yang ditangguhkan akan membantu
meminimalkan masalah seperti itu. Misalnya jika Anda melewati SV yang Anda tahu memiliki tinggi
cukup REFCNT untuk bertahan dari penggunaannya di tumpukan Anda tidak perlu melakukan kematian apa pun. Jika kamu
tidak yakin maka melakukan "SvREFCNT_inc" dan "sv_2mortal", atau membuat "sv_mortalcopy" adalah
lebih aman.

Rutinitas fana bukan hanya untuk SV; AV dan HV dapat dibuat fana dengan melewati
alamat (ketik-dicor ke "SV*") ke rutinitas "sv_2mortal" atau "sv_mortalcopy".

Stash dan gumpalan
A menyimpan adalah hash yang berisi semua variabel yang didefinisikan dalam sebuah paket. Setiap kunci
simpanan adalah nama simbol (dibagikan oleh semua jenis objek berbeda yang memiliki
nama yang sama), dan setiap nilai dalam tabel hash adalah GV (Glob Value). GV ini pada gilirannya
berisi referensi ke berbagai objek dengan nama itu, termasuk (namun tidak terbatas pada)
berikut:

Nilai Skalar
Nilai Array
Nilai Hash
Pegangan I/O
dibentuk
Subrutin

Ada satu simpanan yang disebut "PL_defstash" yang menampung item yang ada di "utama"
kemasan. Untuk mendapatkan item dalam paket lain, tambahkan string "::" ke paket
nama. Item dalam paket "Foo" ada di simpanan "Foo::" di PL_defstash. Barang-barang
dalam paket "Bar::Baz" ada di simpanan "Baz::" di simpanan "Bar::".

Untuk mendapatkan penunjuk simpanan untuk paket tertentu, gunakan fungsi:

HV* gv_stashpv(nama const char*, flag I32)
HV* gv_stashsv(SV*, bendera I32)

Fungsi pertama mengambil string literal, yang kedua menggunakan string yang disimpan di SV.
Ingat bahwa simpanan hanyalah tabel hash, jadi Anda mendapatkan kembali "HV*". Bendera "bendera"
akan membuat paket baru jika disetel ke GV_ADD.

Nama yang diinginkan "gv_stash*v" adalah nama paket yang tabel simbolnya Anda inginkan.
Paket default disebut "utama". Jika Anda memiliki banyak paket bersarang, berikan
nama ke "gv_stash*v", dipisahkan oleh "::" seperti dalam bahasa Perl itu sendiri.

Sebagai alternatif, jika Anda memiliki SV yang merupakan referensi yang diberkati, Anda dapat mengetahui simpanannya
penunjuk dengan menggunakan:

HV* SvSTASH(SvRV(SV*));

kemudian gunakan yang berikut ini untuk mendapatkan nama paket itu sendiri:

char* HvNAME(HV* simpanan);

Jika Anda perlu memberkati atau memberkati kembali suatu objek, Anda dapat menggunakan fungsi berikut:

SV* sv_bless(SV*, HV* simpanan)

di mana argumen pertama, sebuah "SV*", harus menjadi referensi, dan argumen kedua adalah a
menyimpan. "SV*" yang dikembalikan sekarang dapat digunakan dengan cara yang sama seperti SV lainnya.

Untuk informasi lebih lanjut tentang referensi dan berkah, konsultasikan dengan perlref.

Diketik Ganda SV
Variabel skalar biasanya hanya berisi satu jenis nilai, integer, double, pointer, atau
referensi. Perl akan secara otomatis mengonversi data skalar aktual dari tipe yang disimpan
ke dalam tipe yang diminta.

Beberapa variabel skalar berisi lebih dari satu jenis data skalar. Misalnya,
variabel $! berisi nilai numerik "errno" atau string yang setara dari
baik "strerror" atau "sys_errlist[]".

Untuk memaksa beberapa nilai data menjadi SV, Anda harus melakukan dua hal: gunakan "sv_set*v"
rutin untuk menambahkan tipe skalar tambahan, lalu atur tanda sehingga Perl akan mempercayainya
berisi lebih dari satu jenis data. Empat makro untuk mengatur bendera adalah:

SvIOK_on
SvNOK_aktif
SvPOK_aktif
SvROK_aktif

Makro tertentu yang harus Anda gunakan bergantung pada rutin "sv_set*v" mana yang Anda panggil terlebih dahulu.
Ini karena setiap rutin "sv_set*v" hanya menyala sedikit untuk tipe tertentu
data sedang diatur, dan mematikan semua sisanya.

Misalnya, untuk membuat variabel Perl baru yang disebut "dberror" yang berisi keduanya numerik
dan nilai kesalahan string deskriptif, Anda dapat menggunakan kode berikut:

kesalahan luar ke dalam;
char eksternal *dberror_list;

SV* sv = get_sv("dberror", GV_ADD);
sv_setiv(sv, (IV) kesalahan);
sv_setpv(sv, dberror_list[dberror]);
SvIOK_on(sv);

Jika urutan "sv_setiv" dan "sv_setpv" telah dibalik, maka makro "SvPOK_on"
perlu dipanggil alih-alih "SvIOK_on".

Hanya Baca Nilai - Nilai
Di Perl 5.16 dan sebelumnya, copy-on-write (lihat bagian berikutnya) membagikan sedikit flag dengan
skalar hanya-baca. Jadi satu-satunya cara untuk menguji apakah "sv_setsv", dll., akan menaikkan
Kesalahan "Modifikasi nilai hanya-baca" dalam versi tersebut adalah:

SvREADONLY(sv) && !SvIsCOW(sv)

Di bawah Perl 5.18 dan yang lebih baru, SvREADONLY hanya berlaku untuk variabel read-only, dan, di bawah
5.20, skalar copy-on-write juga bisa read-only, jadi pemeriksaan di atas salah. Anda
hanya ingin:

SvBACA SAJA(sv)

Jika Anda perlu sering melakukan pemeriksaan ini, tentukan makro Anda sendiri seperti ini:

#jika PERL_VERSION >= 18
# tentukan SvTRULYREADONLY(sv) SvREADONLY(sv)
#lain
# tentukan SvTRULYREADONLY(sv) (SvREADONLY(sv) && !SvIsCOW(sv))
#berakhir jika

Copy on Menulis
Perl mengimplementasikan mekanisme copy-on-write (COW) untuk skalar, di mana salinan string adalah:
tidak segera dibuat ketika diminta, tetapi ditangguhkan sampai diperlukan oleh salah satu atau
perubahan skalar lainnya. Ini sebagian besar transparan, tetapi kita harus berhati-hati untuk tidak memodifikasi
buffer string yang digunakan bersama oleh beberapa SV.

Anda dapat menguji apakah SV menggunakan copy-on-write dengan "SvIsCOW(sv)".

Anda dapat memaksa SV untuk membuat salinan buffer stringnya sendiri dengan memanggil
"sv_force_normal(sv)" atau SvPV_force_nolen(sv).

Jika Anda ingin membuat SV menjatuhkan buffer string, gunakan "sv_force_normal_flags(sv,
SV_COW_DROP_PV)" atau cukup "sv_setsv(sv, NULL)".

Semua fungsi ini akan serak pada skalar read-only (lihat bagian sebelumnya untuk lebih lanjut
pada mereka).

Untuk menguji apakah kode Anda berfungsi dengan benar dan tidak mengubah buffer COW, pada sistem
dukungan itu mmap(2) (yaitu, Unix) Anda dapat mengonfigurasi Perl dengan
"-Accflags=-DPERL_DEBUG_READONLY_COW" dan itu akan mengubah pelanggaran buffer menjadi crash.
Anda akan merasa sangat lambat, jadi Anda mungkin ingin melewatkan tes Perl sendiri.

Sihir Variabel
[Bagian ini masih dalam pembangunan. Abaikan semuanya di sini. Posting tidak ada tagihan.
Segala sesuatu yang tidak diizinkan dilarang.]

Setiap SV mungkin ajaib, yaitu memiliki fitur khusus yang tidak dimiliki SV normal.
Fitur-fitur ini disimpan dalam struktur SV dalam daftar tertaut dari "struct magic",
diketik menjadi "MAGIC".

sihir struktur {
AJAIB* mg_moreajaib;
MGVTBL* mg_virtual;
U16 mg_pribadi;
karakter mg_type;
U8 mg_bendera;
I32 mg_len;
SV* mg_obj;
karakter* mg_ptr;
};

Perhatikan ini saat ini pada patchlevel 0, dan dapat berubah kapan saja.

Menugaskan Sihir
Perl menambahkan keajaiban ke SV menggunakan fungsi sv_magic:

void sv_magic(SV* sv, SV* obj, int how, const char* nama, I32 namlen);

Argumen "sv" adalah penunjuk ke SV untuk memperoleh fitur magis baru.

Jika "sv" belum ajaib, Perl menggunakan makro "SvUPGRADE" untuk mengonversi "sv" menjadi mengetik
"SVt_PVMG". Perl kemudian melanjutkan dengan menambahkan sihir baru ke awal daftar tertaut
fitur magis. Setiap entri sebelumnya dari jenis sihir yang sama akan dihapus. Perhatikan bahwa
ini dapat ditimpa, dan beberapa contoh dari jenis sihir yang sama dapat dikaitkan
dengan SV.

Argumen "nama" dan "namlen" digunakan untuk mengaitkan string dengan sihir, biasanya
nama sebuah variabel. "namlen" disimpan di bidang "mg_len" dan jika "nama" bukan
null maka salinan "savepvn" dari "nama" atau "nama" itu sendiri disimpan di "mg_ptr"
lapangan, tergantung pada apakah "namlen" lebih besar dari nol atau sama dengan nol masing-masing.
Sebagai kasus khusus, jika "(nama && namlen == HEf_SVKEY)" maka "nama" diasumsikan mengandung
"SV*" dan disimpan apa adanya dengan REFCNT-nya bertambah.

Fungsi sv_magic menggunakan "bagaimana" untuk menentukan, jika ada, "Magic Virtual" yang telah ditentukan sebelumnya
Tabel" harus ditetapkan ke bidang "mg_virtual". Lihat "Tabel Virtual Ajaib"
bagian di bawah. Argumen "bagaimana" juga disimpan di bidang "mg_type". Nilai dari
"bagaimana" harus dipilih dari kumpulan makro "PERL_MAGIC_foo" yang ditemukan di perl.h. Catat itu
sebelum makro ini ditambahkan, internal Perl digunakan untuk langsung menggunakan literal karakter, jadi
Anda mungkin kadang-kadang menemukan kode atau dokumentasi lama yang mengacu pada sihir 'U'
dari "PERL_MAGIC_uvar" misalnya.

Argumen "obj" disimpan di bidang "mg_obj" dari struktur "MAGIC". Jika tidak
sama dengan argumen "sv", jumlah referensi objek "obj" bertambah. Jika
itu sama, atau jika argumen "bagaimana" adalah "PERL_MAGIC_arylen", atau jika itu NULL
pointer, maka "obj" hanya disimpan, tanpa jumlah referensi bertambah.

Lihat juga "sv_magicext" di perlapi untuk cara yang lebih fleksibel untuk menambahkan keajaiban ke SV.

Ada juga fungsi untuk menambahkan keajaiban ke "HV":

void hv_magic(HV *hv, GV *gv, int bagaimana);

Ini hanya memanggil "sv_magic" dan memaksa argumen "gv" menjadi "SV".

Untuk menghapus keajaiban dari SV, panggil fungsi sv_unmagic:

int sv_unmagic(SV *sv, tipe int);

Argumen "type" harus sama dengan nilai "how" ketika "SV" awalnya dibuat
gaib.

Namun, perhatikan bahwa "sv_unmagic" menghapus semua keajaiban dari "tipe" tertentu dari "SV". Jika
Anda hanya ingin menghapus sihir tertentu dari "tipe" berdasarkan tabel virtual ajaib, gunakan
"sv_unmagicext" sebagai gantinya:

int sv_unmagicext(SV *sv, tipe int, MGVTBL *vtbl);

Sihir maya Meja
Bidang "mg_virtual" dalam struktur "MAGIC" adalah penunjuk ke "MGVTBL", yang merupakan
struktur pointer fungsi dan singkatan dari "Magic Virtual Table" untuk menangani berbagai
operasi yang mungkin diterapkan pada variabel tersebut.

"MGVTBL" memiliki lima (atau terkadang delapan) pointer ke tipe rutin berikut:

int (*svt_get)(SV* sv, AJAIB* mg);
int (*svt_set)(SV* sv, AJAIB* mg);
U32 (*svt_len)(SV* sv, AJAIB* mg);
int (*svt_clear)(SV* sv, AJAIB* mg);
int (*svt_free)(SV* sv, AJAIB* mg);

int (*svt_copy)(SV *sv, AJAIB* mg, SV *nsv,
const char *nama, nama I32);
int (*svt_dup)(MAGIC *mg, CLONE_PARAMS *param);
int (*svt_local)(SV *nsv, AJAIB *mg);

Struktur MGVTBL ini diatur pada waktu kompilasi di perl.h dan saat ini ada 32 jenis.
Struktur yang berbeda ini berisi petunjuk ke berbagai rutinitas yang melakukan tambahan
tindakan tergantung pada fungsi yang dipanggil.

Penunjuk fungsi Tindakan yang diambil
---------------- ------------
svt_get Lakukan sesuatu sebelum nilai SV adalah
diambil.
svt_set Lakukan sesuatu setelah SV diberi nilai.
svt_len Laporkan panjang SV.
svt_clear Hapus sesuatu yang diwakili SV.
svt_free Membebaskan penyimpanan ekstra apa pun yang terkait dengan SV.

svt_copy menyalin sihir variabel terikat ke elemen terikat
svt_dup menduplikasi struktur ajaib selama kloning utas
svt_local salin sihir ke nilai lokal selama 'lokal'

Misalnya, struktur MGVTBL yang disebut "vtbl_sv" (yang sesuai dengan "mg_type" dari
"PERL_MAGIC_sv") berisi:

{ dapatkan_ajaib, set_ajaib, len_ajaib, 0, 0 }

Jadi, ketika SV ditentukan menjadi magis dan bertipe "PERL_MAGIC_sv", jika get
operasi sedang dilakukan, rutin "magic_get" dipanggil. Semua berbagai rutinitas
untuk berbagai jenis magis dimulai dengan "magic_". CATATAN: rutinitas ajaib tidak
dianggap sebagai bagian dari Perl API, dan tidak boleh diekspor oleh perpustakaan Perl.

Tiga slot terakhir adalah tambahan terbaru, dan untuk kompatibilitas kode sumber adalah
hanya diperiksa jika salah satu dari tiga flag MGf_COPY, MGf_DUP atau MGf_LOCAL diatur
mg_flags. Ini berarti bahwa sebagian besar kode dapat terus mendeklarasikan vtable sebagai nilai 5 elemen.
Ketiganya saat ini digunakan secara eksklusif oleh kode threading, dan sangat tunduk
berubah.

Jenis Tabel Virtual Ajaib saat ini adalah:

mg_type
(char dan makro gaya lama) MGVTBL Jenis sihir
-------------------------- ------ -------------
\0 PERL_MAGIC_sv vtbl_sv Variabel skalar khusus
# PERL_MAGIC_arylen vtbl_arylen Panjang larik ($#ary)
% PERL_MAGIC_rhash (tidak ada) Data ekstra untuk dibatasi
hash
* PERL_MAGIC_debugvar vtbl_debugvar $DB::tunggal, sinyal, lacak
vars
. PERL_MAGIC_pos vtbl_pos pos() nilai
: PERL_MAGIC_symtab (none) Data tambahan untuk simbol
tabel
< PERL_MAGIC_backref vtbl_backref Untuk data ref yang lemah
@ PERL_MAGIC_arylen_p (tidak ada) Untuk mengeluarkan arylen dari XPVAV
B PERL_MAGIC_bm vtbl_regexp Boyer-Moore
(pencarian string cepat)
c PERL_MAGIC_overload_table vtbl_ovrld Memegang tabel kelebihan beban
(AMT) di simpanan
D PERL_MAGIC_regdata vtbl_regdata Data posisi kecocokan Regex
(@+ dan @- vars)
d PERL_MAGIC_regdatum vtbl_regdatum Data posisi kecocokan Regex
elemen
E PERL_MAGIC_env vtbl_env %ENV hash
e PERL_MAGIC_envelem vtbl_envelem %ENV elemen hash
f PERL_MAGIC_fm vtbl_regexp Garis Bentuk
(format 'dikompilasi')
g target PERL_MAGIC_regex_global vtbl_mglob m//g
H PERL_MAGIC_hints vtbl_hints %^H hash
h PERL_MAGIC_hintselem vtbl_hintselem %^H elemen hash
Saya PERL_MAGIC_isa vtbl_isa @ISA array
saya PERL_MAGIC_isaelem vtbl_isaelem @ISA elemen array
k PERL_MAGIC_nkeys vtbl_nkeys scalar(keys()) nilai
L PERL_MAGIC_dbfile (tidak ada) Debugger %_
l PERL_MAGIC_dbline vtbl_dbline Debugger %_
elemen
N PERL_MAGIC_shared (tidak ada) Dibagi antar utas
n PERL_MAGIC_shared_scalar (tidak ada) Dibagi antar utas
o PERL_MAGIC_collxfrm vtbl_collxfrm Transformasi lokal
P PERL_MAGIC_tied vtbl_pack Terikat array atau hash
p PERL_MAGIC_tiedelem vtbl_packelem Array terikat atau elemen hash
q PERL_MAGIC_tiedscalar vtbl_packelem Skalar atau pegangan terikat
r PERL_MAGIC_qr vtbl_regexp Dikompilasi sebelumnya qr// regex
S PERL_MAGIC_sig (tidak ada) %SIG hash
s PERL_MAGIC_sigelem vtbl_sigelem %SIG elemen hash
t PERL_MAGIC_taint vtbl_taint Kecemaran
U PERL_MAGIC_uvar vtbl_uvar Tersedia untuk digunakan oleh
ekstensi
u PERL_MAGIC_uvar_elem (none) Dicadangkan untuk digunakan oleh
ekstensi
V PERL_MAGIC_vstring (tidak ada) SV adalah vstring literal
v PERL_MAGIC_vec vtbl_vec vec() nilai
w PERL_MAGIC_utf8 vtbl_utf8 informasi UTF-8 yang di-cache
x PERL_MAGIC_substr vtbl_substr substr() nilai
y PERL_MAGIC_defelem vtbl_defelem Shadow "foreach" iterator
variabel / parameter cerdas
penghidupan kembali
\ PERL_MAGIC_lvref vtbl_lvref Lnilai referensi
pembina
] PERL_MAGIC_checkcall vtbl_checkcall Inlining/mutasi panggilan
ke CV ini
~ PERL_MAGIC_ext (tidak ada) Tersedia untuk digunakan oleh
ekstensi

Ketika huruf besar dan huruf kecil keduanya ada di tabel, maka huruf besar
biasanya digunakan untuk mewakili beberapa jenis tipe komposit (daftar atau hash), dan
huruf kecil digunakan untuk mewakili elemen dari tipe komposit itu. Beberapa internal
kode memanfaatkan hubungan kasus ini. Namun, 'v' dan 'V' (vec dan v-string) ada di
tidak ada hubungannya.

Jenis sihir "PERL_MAGIC_ext" dan "PERL_MAGIC_uvar" didefinisikan secara khusus untuk digunakan oleh
ekstensi dan tidak akan digunakan oleh Perl itu sendiri. Ekstensi dapat menggunakan sihir "PERL_MAGIC_ext"
untuk 'melampirkan' informasi pribadi ke variabel (biasanya objek). Ini terutama
berguna karena tidak ada cara bagi kode perl normal untuk merusak informasi pribadi ini
(tidak seperti menggunakan elemen tambahan dari objek hash).

Demikian pula, sihir "PERL_MAGIC_uvar" dapat digunakan seperti mengikat() untuk memanggil fungsi C sembarang
waktu nilai skalar digunakan atau diubah. Kolom "mg_ptr" "MAGIC" menunjuk ke a
struktur "ufuncs":

struktur ufunc {
I32 (*uf_val)(pTHX_IV, SV*);
I32 (*uf_set)(pTHX_IV, SV*);
IV uf_indeks;
};

Ketika SV dibaca dari atau ditulis, fungsi "uf_val" atau "uf_set" akan dipanggil
dengan "uf_index" sebagai argumen pertama dan penunjuk ke SV sebagai argumen kedua. Contoh sederhana
cara menambahkan sihir "PERL_MAGIC_uvar" ditunjukkan di bawah ini. Perhatikan bahwa struktur ufuncs adalah
disalin oleh sv_magic, sehingga Anda dapat mengalokasikannya dengan aman di tumpukan.

membatalkan
Umagic(sv)
SV *sv;
PRINIT:
struktur ufuncs uf;
KODE:
uf.uf_val = &my_get_fn;
uf.uf_set = &my_set_fn;
uf.uf_index = 0;
sv_magic(sv, 0, PERL_MAGIC_uvar, (char*)&uf, sizeof(uf));

Melampirkan "PERL_MAGIC_uvar" ke array diperbolehkan tetapi tidak berpengaruh.

Untuk hash ada pengait khusus yang memberikan kontrol atas kunci hash (tetapi bukan nilai).
Kait ini memanggil sihir "PERL_MAGIC_uvar" 'dapatkan' jika fungsi "set" di "ufuncs"
struktur adalah NULL. Kait diaktifkan setiap kali hash diakses dengan kunci
ditentukan sebagai "SV" melalui fungsi "hv_store_ent", "hv_fetch_ent",
"hv_delete_ent", dan "hv_exists_ent". Mengakses kunci sebagai string melalui fungsi
tanpa akhiran "..._ent" menghindari hook. Lihat "GUTS" di Hash::Util::FieldHash
untuk deskripsi rinci.

Perhatikan bahwa karena beberapa ekstensi mungkin menggunakan "PERL_MAGIC_ext" atau "PERL_MAGIC_uvar"
sihir, penting bagi ekstensi untuk berhati-hati untuk menghindari konflik. Khas
hanya menggunakan sihir pada objek yang diberkati ke dalam kelas yang sama dengan ekstensinya
memadai. Untuk sihir "PERL_MAGIC_ext", biasanya ide yang baik untuk mendefinisikan "MGVTBL",
bahkan jika semua bidangnya akan menjadi 0, sehingga pointer "MAGIC" individu dapat diidentifikasi sebagai
jenis sihir tertentu menggunakan tabel virtual ajaib mereka. "mg_findext" memberikan kemudahan
cara melakukannya:

MGVTBL STATIS my_vtbl = { 0, 0, 0, 0, 0, 0, 0, 0 };

AJAIB *mg;
if ((mg = mg_findext(sv, PERL_MAGIC_ext, &my_vtbl))) {
/* ini benar-benar milik kita, bukan PERL_MAGIC_ext modul lain */
my_priv_data_t *priv = (my_priv_data_t *)mg->mg_ptr;
...
}

Perhatikan juga bahwa fungsi "sv_set*()" dan "sv_cat*()" yang dijelaskan sebelumnya tidak tidak memohon
'mengatur' sihir pada target mereka. Ini harus dilakukan oleh pengguna baik dengan memanggil
Makro "SvSETMAGIC()" setelah memanggil fungsi ini, atau dengan menggunakan salah satu dari "sv_set*_mg()"
atau fungsi "sv_cat*_mg()". Demikian pula, kode C generik harus memanggil makro "SvGETMAGIC()"
untuk memanggil sihir 'dapatkan' apa pun jika mereka menggunakan SV yang diperoleh dari sumber eksternal dalam fungsi
yang tidak menangani sihir. Lihat perlapi untuk penjelasan fungsi-fungsi ini. Sebagai contoh,
panggilan ke fungsi "sv_cat*()" biasanya harus diikuti oleh "SvSETMAGIC()", tetapi
mereka tidak memerlukan "SvGETMAGIC()" sebelumnya karena implementasinya menangani keajaiban 'dapatkan'.

Temuan Sihir
MAGIC *mg_find(SV *sv, tipe int); /* Menemukan penunjuk ajaib itu
* Tipe */

Rutin ini mengembalikan pointer ke struktur "MAGIC" yang disimpan di SV. Jika SV melakukannya
tidak memiliki fitur ajaib itu, "NULL" dikembalikan. Jika SV memiliki beberapa instance dari
fitur ajaib itu, yang pertama akan dikembalikan. "mg_findext" dapat digunakan untuk menemukan
Struktur "MAGIC" dari SV berdasarkan tipe sihirnya dan tabel virtual ajaibnya:

MAGIC *mg_findext(SV *sv, tipe int, MGVTBL *vtbl);

Juga, jika SV yang diteruskan ke "mg_find" atau "mg_findext" bukan tipe SVt_PVMG, Perl mungkin core
membuang.

int mg_copy(SV* sv, SV* nsv, kunci const char*, STRLEN klen);

Pemeriksaan rutin ini untuk melihat jenis sihir "sv" apa yang dimiliki. Jika bidang mg_type adalah
huruf besar, maka mg_obj disalin ke "nsv", tetapi bidang mg_type diubah menjadi
menjadi huruf kecil.

Memahami itu Sihir of Terjalin Hash dan Array
Terikat hash dan array adalah binatang ajaib dari jenis sihir "PERL_MAGIC_tied".

PERINGATAN: Pada rilis 5.004, penggunaan yang tepat dari array dan fungsi akses hash
membutuhkan pemahaman beberapa peringatan. Beberapa peringatan ini sebenarnya dianggap sebagai bug
di API, untuk diperbaiki di rilis selanjutnya, dan dikurung dengan [MAYCHANGE] di bawah. Jika
Anda menemukan diri Anda benar-benar menerapkan informasi tersebut di bagian ini, ketahuilah bahwa:
perilaku dapat berubah di masa depan, umm, tanpa peringatan.

Fungsi perl tie mengasosiasikan variabel dengan objek yang mengimplementasikan berbagai
GET, SET, dll metode. Untuk melakukan yang setara dengan fungsi perl tie dari XSUB,
Anda harus meniru perilaku ini. Kode di bawah ini melakukan langkah-langkah yang diperlukan -- pertama
itu menciptakan hash baru, dan kemudian membuat hash kedua yang diberkati ke dalam kelas
yang akan menerapkan metode dasi. Terakhir itu mengikat dua hash bersama-sama, dan mengembalikan
referensi ke hash terikat baru. Perhatikan bahwa kode di bawah ini TIDAK memanggil TIEHASH
metode di kelas MyTie - lihat "Memanggil Rutinitas Perl dari dalam Program C" untuk detailnya
tentang cara melakukan ini.

SV*
mytie()
PRINIT:
HV *has;
HV * simpanan;
SV *dasi;
KODE:
hash = newHV();
dasi = newRV_noinc((SV*)newHV());
simpanan = gv_stashpv("MyTie", GV_ADD);
sv_bless(dasi, simpanan);
hv_magic(hash, (GV*)seri, PERL_MAGIC_tied);
RETVAL = newRV_noinc(hash);
KELUARAN:
PENGEMBALIAN

Fungsi "av_store", ketika diberikan argumen array terikat, hanya menyalin keajaiban dari
array ke nilai yang akan "disimpan", menggunakan "mg_copy". Itu juga dapat mengembalikan NULL, menunjukkan
bahwa nilainya sebenarnya tidak perlu disimpan dalam array. [MUNGKIN] Setelah panggilan
ke "av_store" pada larik terikat, pemanggil biasanya perlu memanggil "mg_set(val)" ke
sebenarnya memanggil metode "STORE" tingkat perl pada objek TIEARRAY. Jika "av_store" melakukannya
return NULL, panggilan ke "SvREFCNT_dec(val)" biasanya juga diperlukan untuk menghindari
kebocoran memori. [/MUNGKIN BERUBAH]

Paragraf sebelumnya berlaku kata demi kata untuk akses hash terikat menggunakan "hv_store" dan
"hv_store_ent" juga berfungsi.

"av_fetch" dan fungsi hash yang sesuai "hv_fetch" dan "hv_fetch_ent" sebenarnya
mengembalikan nilai fana yang tidak ditentukan yang sihirnya telah diinisialisasi menggunakan "mg_copy". Catatan
nilai yang dikembalikan tidak perlu dialokasikan, karena sudah fana.
[MUNGKIN] Tetapi Anda perlu memanggil "mg_get()" pada nilai yang dikembalikan untuk
sebenarnya memanggil metode "FETCH" tingkat Perl pada objek TIE yang mendasarinya. Demikian pula,
anda juga dapat memanggil "mg_set()" pada nilai kembalian setelah mungkin menetapkan nilai yang sesuai
untuk itu menggunakan "sv_setsv", yang akan memanggil metode "STORE" pada objek TIE.
[/MUNGKIN BERUBAH]

[MAYCHANGE] Dengan kata lain, array atau fungsi pengambilan/penyimpanan hash tidak benar-benar mengambil dan
menyimpan nilai aktual dalam kasus array dan hash terikat. Mereka hanya memanggil "mg_copy" untuk
melampirkan sihir ke nilai-nilai yang dimaksudkan untuk "disimpan" atau "diambil". Nanti telepon ke
"mg_get" dan "mg_set" benar-benar melakukan tugas menerapkan metode TIE pada dasarnya
objek. Jadi mekanisme ajaib saat ini mengimplementasikan semacam akses malas ke array
dan hash.

Saat ini (pada versi Perl 5.004), penggunaan fungsi akses hash dan array memerlukan
pengguna untuk mengetahui apakah mereka beroperasi pada hash dan array "normal", atau pada
varian terikat mereka. API dapat diubah untuk memberikan akses yang lebih transparan ke keduanya
tipe data terikat dan normal di versi mendatang. [/MUNGKIN BERUBAH]

Anda sebaiknya memahami bahwa antarmuka TIEARRAY dan TIEHASH hanyalah gula untuk
aktifkan beberapa panggilan metode Perl saat menggunakan sintaks hash dan array yang seragam. penggunaan dari
gula ini membebankan beberapa overhead (biasanya sekitar dua hingga empat opcode tambahan per
Operasi FETCH/STORE, selain pembuatan semua variabel fana yang diperlukan untuk
memanggil metode). Overhead ini akan relatif kecil jika metode TIE adalah:
sendiri substansial, tetapi jika hanya beberapa pernyataan, overhead tidak akan
menjadi tidak signifikan.

Lokalisasi perubahan
Perl memiliki konstruksi yang sangat berguna

{
lokal $var = 2;
...
}

Konstruksi ini adalah sekitar setara dengan

{
$oldvar saya = $var;
$var = 2;
...
$var = $var lama;
}

Perbedaan terbesar adalah bahwa konstruksi pertama akan mengembalikan nilai awal
$var, terlepas dari bagaimana kontrol keluar dari blok: "goto", "return", "die"/"eval", dll.
Ini juga sedikit lebih efisien.

Ada cara untuk mencapai tugas serupa dari C melalui Perl API: buat a pseudo-blok, dan
mengatur agar beberapa perubahan dibatalkan secara otomatis pada akhirnya, baik eksplisit, atau
melalui pintu keluar non-lokal (melalui mati ()). Itu blok-seperti konstruksi dibuat oleh sepasang
Makro "ENTER"/"LEAVE" (lihat "Mengembalikan Skalar" di perlcall). Konstruksi seperti itu mungkin
dibuat khusus untuk beberapa tugas lokal yang penting, atau yang sudah ada (seperti batas
dari melampirkan subrutin/blok Perl, atau pasangan yang ada untuk membebaskan TMP) dapat digunakan.
(Dalam kasus kedua, overhead lokalisasi tambahan harus hampir dapat diabaikan.)
Perhatikan bahwa setiap XSUB secara otomatis diapit oleh pasangan "ENTER"/"LEAVE".

Di dalam seperti itu pseudo-blok layanan berikut tersedia:

"HEMAT(int i)"
"SAVEIV(IV i)"
"SAVEI32(I32 i)"
"SAVELONG(panjang i)"
Makro ini mengatur hal-hal untuk mengembalikan nilai variabel integer "i" di akhir
melampirkan pseudo-blok.

SAVESPTR
SIMPANPPTR(p)
Makro ini mengatur hal-hal untuk mengembalikan nilai pointer "s" dan "p". "s" harus
pointer dari tipe yang bertahan dari konversi ke "SV*" dan sebaliknya, "p" harus dapat
selamat dari konversi ke "char*" dan kembali.

"SAVEFREESV(SV *sv)"
Penghitungan ulang "sv" akan dikurangi di akhir pseudo-blok. Ini mirip
ke "sv_2mortal" karena ini juga merupakan mekanisme untuk melakukan "SvREFCNT_dec" yang tertunda.
Namun, sementara "sv_2mortal" memperpanjang masa pakai "sv" hingga awal
pernyataan berikutnya, "SAVEFREESV" memperpanjangnya hingga akhir cakupan terlampir. Ini
kehidupan bisa sangat berbeda.

Bandingkan juga "SAVEMORTALIZESV".

"SAVEMORTALIZESV(SV *sv)"
Sama seperti "SAVEFREESV", tetapi mematikan "sv" di akhir cakupan saat ini alih-alih
mengurangi jumlah referensinya. Ini biasanya memiliki efek menjaga "sv" tetap hidup
sampai pernyataan yang memanggil lingkup live saat ini telah selesai dieksekusi.

"SAVEFREEOP(OP *op)"
"OP *" adalah op_bebas()ed di akhir pseudo-blok.

HEMAT,GRATISPV(p)
Potongan memori yang ditunjuk oleh "p" adalah Bebas Aman()ed di akhir semu
blok.

"SAVECLEARSV(SV *sv)"
Menghapus slot di papan gosok saat ini yang sesuai dengan "sv" di akhir
pseudo-blok.

"SAVEDELETE(HV *hv, char *key, panjang I32)"
Kunci "kunci" dari "hv" dihapus di akhir pseudo-blok. Tali yang ditunjuk oleh
"kunci" adalah Bebas Aman()ed. Jika seseorang memiliki kunci dalam penyimpanan berumur pendek, yang sesuai
string dapat dialokasikan kembali seperti ini:

SAVEDELETE(PL_defstash, savepv(tmpbuf), strlen(tmpbuf));

"SAVEDESTRUCTOR(DESTRUCTORFUNC_NOCONTEXT_t f, batal *p)"
Pada akhir pseudo-blok fungsi "f" dipanggil dengan satu-satunya argumen "p".

"SAVEDESTRUCTOR_X(DESTRUCTORFUNC_t f, batal *p)"
Pada akhir pseudo-blok fungsi "f" dipanggil dengan konteks implisit
argumen (jika ada), dan "p".

"SAVESTACK_POS()"
Offset saat ini pada tumpukan internal Perl (lih. "SP") dipulihkan pada akhir
pseudo-blok.

Daftar API berikut berisi fungsi, jadi seseorang perlu memberikan pointer ke
data yang dapat dimodifikasi secara eksplisit (baik pointer C, atau Perlish "GV *"s). Dimana di atas
makro mengambil "int", fungsi serupa mengambil "int *".

"SV* save_scalar(GV *gv)"
Setara dengan kode Perl "$gv lokal".

"AV* save_ary(GV *gv)"
"HV* save_hash(GV *gv)"
Mirip dengan "save_scalar", tetapi lokalkan @gv dan %gv.

"void save_item(SV *item)"
Menggandakan nilai "SV" saat ini, saat keluar dari "ENTER"/"LEAVE" saat ini
pseudo-blok akan mengembalikan nilai "SV" menggunakan nilai yang disimpan. Itu tidak menangani
sihir. Gunakan "save_scalar" jika sihir terpengaruh.

"void save_list(SV **sarg, I32 maxsarg)"
Varian "save_item" yang mengambil banyak argumen melalui array "sarg" dari "SV*"
panjang "maxsarg".

"SV* save_svref(SV **sptr)"
Mirip dengan "save_scalar", tetapi akan mengembalikan "SV *".

"void save_aptr(AV **aptr)"
"void save_hptr(HV **hptr)"
Mirip dengan "save_svref", tetapi melokalkan "AV *" dan "HV *".

Modul "Alias" mengimplementasikan pelokalan tipe dasar dalam penelepon cakupan.
Orang yang tertarik dengan cara melokalisasi hal-hal dalam ruang lingkup yang berisi harus mengambil a
lihat di sana juga.

Subrutin


XSUB dan itu Argumen Tumpukan
Mekanisme XSUB adalah cara sederhana bagi program Perl untuk mengakses subrutin C. Sebuah XSUB
rutin akan memiliki tumpukan yang berisi argumen dari program Perl, dan cara untuk
memetakan dari struktur data Perl ke C yang setara.

Argumen tumpukan dapat diakses melalui makro ST(n), yang mengembalikan tumpukan "n"'
argumen. Argumen 0 adalah argumen pertama yang diteruskan dalam panggilan subrutin Perl. Ini
argumen adalah "SV*", dan dapat digunakan di mana saja "SV*" digunakan.

Sebagian besar waktu, output dari rutinitas C dapat ditangani melalui penggunaan RETVAL dan
arahan OUTPUT. Namun, ada beberapa kasus di mana tumpukan argumen belum ada
cukup lama untuk menangani semua nilai kembalian. Contohnya adalah POSIX tznama() panggilan, yang
tidak mengambil argumen, tetapi mengembalikan dua, standar zona waktu lokal dan waktu musim panas
singkatan

Untuk menangani situasi ini, arahan PPCODE digunakan dan tumpukan diperluas menggunakan
makro:

MEMPERPANJANG(SP, angka);

di mana "SP" adalah makro yang mewakili salinan lokal penunjuk tumpukan, dan "num" adalah
jumlah elemen tumpukan harus diperpanjang.

Sekarang setelah ada ruang di tumpukan, nilai dapat didorong di atasnya menggunakan makro "PUSH". Itu
nilai yang didorong sering kali harus "fana" (Lihat "Jumlah Referensi dan Kematian"):

PUSH(sv_2mortal(newSViv(an_integer)))
PUSH(sv_2mortal(newSVuv(an_unsigned_integer)))
PUSH(sv_2mortal(newSVnv(a_double)))
PUSHs(sv_2mortal(newSVpv("Some String",0)))
/* Meskipun contoh terakhir lebih baik ditulis lebih
* efisien: */
PUSHs(newSVpvs_flags("Some String", SVs_TEMP))

Dan sekarang program Perl memanggil "tzname", dua nilai akan diberikan seperti pada:

($standard_abbrev, $summer_abbrev) = POSIX::tzname;

Metode alternatif (dan mungkin lebih sederhana) untuk mendorong nilai pada tumpukan adalah dengan menggunakan
makro:

XPUSH (SV*)

Makro ini secara otomatis menyesuaikan tumpukan untuk Anda, jika diperlukan. Dengan demikian, Anda tidak perlu
panggil "EXTEND" untuk memperpanjang tumpukan.

Terlepas dari saran mereka di versi sebelumnya dari dokumen ini, makro "(X)PUSH[iunp]"
adalah tidak cocok untuk XSUB yang mengembalikan banyak hasil. Untuk itu, tetap berpegang pada
Makro "(X)PUSHs" yang ditampilkan di atas, atau gunakan makro "m(X)PUSH[iunp]" yang baru sebagai gantinya; melihat
"Menempatkan nilai C pada tumpukan Perl".

Untuk informasi lebih lanjut, lihat perlxs dan perlxstut.

Pemuatan otomatis dengan XSUB
Jika rutinitas AUTOLOAD adalah XSUB, seperti halnya subrutin Perl, Perl menempatkan
nama subrutin yang dimuat secara otomatis dalam variabel $AUTOLOAD dari paket XSUB.

Tetapi itu juga menempatkan informasi yang sama di bidang tertentu dari XSUB itu sendiri:

HV *simpanan = CvSTASH(cv);
const char *subnama = SvPVX(cv);
STRLEN nama_panjang = SvCUR(cv); /* dalam byte */
U32 is_utf8 = SvUTF8(cv);

"SvPVX(cv)" hanya berisi sub nama itu sendiri, tidak termasuk paket. Untuk AUTOLOAD
rutin di UNIVERSAL atau salah satu superclassnya, "CvSTASH(cv)" mengembalikan NULL selama
pemanggilan metode pada paket yang tidak ada.

Note: Pengaturan $AUTOLOAD berhenti bekerja di 5.6.1, yang tidak mendukung XS AUTOLOAD subs
sama sekali. Perl 5.8.0 memperkenalkan penggunaan bidang di XSUB itu sendiri. Perl 5.16.0 dipulihkan
pengaturan $AUTOLOAD. Jika Anda perlu mendukung 5.8-5.14, gunakan bidang XSUB.

panggilan Perl Rutinitas dari dalam C program
Ada empat rutin yang dapat digunakan untuk memanggil subrutin Perl dari dalam C
program. Empat ini adalah:

I32 panggilan_sv(SV*, I32);
I32 panggilan_pv(konstan karakter*, I32);
I32 metode_panggilan(const char*, I32);
I32 call_argv(const char*, I32, char**);

Rutin yang paling sering digunakan adalah "call_sv". Argumen "SV*" berisi salah satu nama dari
subrutin Perl yang akan dipanggil, atau referensi ke subrutin. Argumen kedua
terdiri dari flag-flag yang mengontrol konteks di mana subrutin dipanggil, apakah atau
bukan subrutin yang sedang melewati argumen, bagaimana kesalahan harus dijebak, dan bagaimana
memperlakukan nilai kembali.

Keempat rutinitas mengembalikan jumlah argumen yang dikembalikan subrutin pada Perl
tumpukan.

Rutinitas ini dulu disebut "perl_call_sv", dll., sebelum Perl v5.6.0, tetapi nama-nama itu
sekarang tidak digunakan lagi; makro dengan nama yang sama disediakan untuk kompatibilitas.

Saat menggunakan rutinitas ini (kecuali "call_argv"), programmer harus memanipulasi
tumpukan Perl. Ini termasuk makro dan fungsi berikut:

dSP
SP
TANDA TOLONG()
TARUH KEMBALI
SPANYOL
ENTER
SIMPAN
GRATISTMPS
MENINGGALKAN
XPUSH*()
POP*()

Untuk penjelasan rinci tentang konvensi pemanggilan dari C ke Perl, lihat perlcall.

Puting a C nilai on Perl tumpukan
Banyak opcode (ini adalah operasi dasar di mesin perl stack internal) yang dimasukkan
sebuah SV* pada tumpukan. Namun, sebagai optimasi, SV yang sesuai (biasanya) tidak
dibuat ulang setiap kali. Opcode menggunakan kembali SV yang ditugaskan secara khusus (targets) yang (sebagai
wajar) tidak terus-menerus dibebaskan/diciptakan.

Masing-masing target dibuat hanya sekali (tetapi lihat "Scratchpads dan rekursi" di bawah), dan
ketika opcode perlu meletakkan integer, double, atau string pada stack, itu hanya mengatur
bagian yang sesuai darinya target dan menempatkan target di tumpukan.

Makro untuk menempatkan target ini di tumpukan adalah "PUSHTARG", dan langsung digunakan di beberapa
opcode, serta secara tidak langsung dalam jutaan lainnya, yang menggunakannya melalui "(X)PUSH[iunp]".

Karena target digunakan kembali, Anda harus berhati-hati saat mendorong beberapa nilai pada
tumpukan. Kode berikut tidak akan melakukan apa yang Anda pikirkan:

XPUSHai(10);
XPUSHai(20);

Ini diterjemahkan sebagai "setel "TARG" ke 10, dorong pointer ke "TARG" ke tumpukan; setel "TARG"
ke 20, tekan pointer ke "TARG" ke tumpukan". Di akhir operasi, tumpukan
tidak berisi nilai 10 dan 20, tetapi sebenarnya berisi dua petunjuk ke "TARG", yang
kami telah menetapkan ke 20.

Jika Anda perlu mendorong beberapa nilai yang berbeda maka Anda harus menggunakan "(X)PUSHs"
makro, atau gunakan makro "m(X)PUSH[iunp]" baru, tidak ada yang menggunakan "TARG".
Makro "(X)PUSHs" cukup mendorong SV* pada tumpukan, yang, seperti disebutkan di bawah "XSUBs dan
Argument Stack", seringkali harus "mortal". Makro baru "m(X)PUSH[iunp]" membuat
ini sedikit lebih mudah untuk dicapai dengan membuat manusia baru untuk Anda (melalui "(X)PUSHmortal"),
mendorongnya ke tumpukan (memperpanjangnya jika perlu dalam kasus "mXPUSH[iunp]"
makro), dan kemudian mengatur nilainya. Jadi, alih-alih menulis ini untuk "memperbaiki" contoh
di atas:

XPUSH(sv_2mortal(baruSViv(10)))
XPUSH(sv_2mortal(baruSViv(20)))

Anda cukup menulis:

mXPUSHI(10)
mXPUSHI(20)

Pada catatan terkait, jika Anda menggunakan "(X)PUSH[iunp]", maka Anda akan memerlukan "dTARG" di
deklarasi variabel Anda sehingga makro "*PUSH*" dapat menggunakan variabel lokal
"TARG". Lihat juga "dTARGET" dan "dXSTARG".

Bantalan gores
Pertanyaannya tetap pada kapan SV yang targets untuk opcode dibuat. Itu
jawabannya adalah bahwa mereka dibuat ketika unit saat ini--subrutin atau file (untuk opcodes
untuk pernyataan di luar subrutin)--dikompilasi. Selama waktu ini anonim khusus
Array Perl dibuat, yang disebut scratchpad untuk unit saat ini.

Papan penggores menyimpan SV yang merupakan leksikal untuk unit saat ini dan merupakan target untuk
opcode. Versi sebelumnya dari dokumen ini menyatakan bahwa seseorang dapat menyimpulkan bahwa seorang SV hidup
pada papan gores dengan melihat benderanya: leksikal memiliki set "SVs_PADMY", dan targetsudah
"SVs_PADTMP" disetel. Tapi ini tidak pernah sepenuhnya benar. "SVs_PADMY" dapat disetel pada
variabel yang tidak lagi berada di pad mana pun. Ketika targets memang memiliki set "SVs_PADTMP", itu
juga dapat diatur pada variabel yang tidak pernah berada di pad, tetapi tetap bertindak seperti
targetS. Pada Perl 5.21.5, bendera "SVs_PADMY" tidak lagi digunakan dan didefinisikan sebagai 0.
"SvPADMY()" sekarang mengembalikan true untuk apa pun tanpa "SVs_PADTMP".

Korespondensi antara OP dan targets tidak 1-1. OP berbeda dalam kompilasi
pohon unit dapat menggunakan target yang sama, jika ini tidak bertentangan dengan yang diharapkan
hidup yang sementara.

Bantalan gores dan pengulangan
Sebenarnya tidak 100% benar bahwa unit yang dikompilasi berisi pointer ke AV papan gosok.
Sebenarnya ini berisi pointer ke AV dari (awalnya) satu elemen, dan elemen ini adalah
papan gores AV. Mengapa kita membutuhkan tingkat tipuan ekstra?

Jawabannya adalah pengulangan, dan mungkin benang. Keduanya dapat membuat beberapa eksekusi
pointer masuk ke subrutin yang sama. Untuk subrutin-anak tidak menulis di atas
sementara untuk subrutin-orang tua (masa hidup yang mencakup panggilan ke anak),
orang tua dan anak harus memiliki bantalan gores yang berbeda. (Dan leksikalnya harus
terpisah pula!)

Jadi setiap subrutin dilahirkan dengan sebuah array dari scratchpads (panjang 1). Pada setiap entri ke
subrutin diperiksa bahwa kedalaman rekursi saat ini tidak lebih dari
panjang larik ini, dan jika ya, papan gores baru dibuat dan dimasukkan ke dalam larik.

The targets pada papan gosok ini adalah "undef", tetapi sudah ditandai dengan benar
bendera.

Memori Alokasi


Alokasi
Semua memori yang dimaksudkan untuk digunakan dengan fungsi Perl API harus dimanipulasi menggunakan
makro yang dijelaskan di bagian ini. Makro memberikan transparansi yang diperlukan antara
perbedaan dalam implementasi malloc aktual yang digunakan dalam Perl.

Disarankan agar Anda mengaktifkan versi malloc yang didistribusikan dengan Perl. Dia
menyimpan kumpulan berbagai ukuran memori yang tidak terisi untuk memenuhi permintaan alokasi
lebih cepat. Namun, pada beberapa platform, ini dapat menyebabkan malloc palsu atau kesalahan gratis.

Tiga makro berikut digunakan untuk mengalokasikan memori pada awalnya:

Newx(penunjuk, angka, jenis);
Newxc(penunjuk, angka, tipe, pemeran);
Newxz(penunjuk, angka, jenis);

Argumen pertama "pointer" harus berupa nama variabel yang akan menunjuk ke yang baru
memori yang dialokasikan.

Argumen kedua dan ketiga "angka" dan "tipe" menentukan berapa banyak dari tipe yang ditentukan
struktur data harus dialokasikan. Argumen "type" diteruskan ke "sizeof". Itu
argumen terakhir untuk "Newxc", "cast", harus digunakan jika argumen "pointer" berbeda
dari argumen "tipe".

Tidak seperti makro "Newx" dan "Newxc", makro "Newxz" memanggil "memzero" untuk menghilangkan semua
memori yang baru dialokasikan.

Realokasi
Perbarui (penunjuk, angka, jenis);
Renewc(pointer, nomor, jenis, cast);
Bebas Aman (penunjuk)

Ketiga makro ini digunakan untuk mengubah ukuran buffer memori atau untuk mengosongkan sebagian memori no
lebih lama dibutuhkan. Argumen untuk "Renew" dan "Renewc" cocok dengan argumen "New" dan "Newc" dengan
pengecualian tidak memerlukan argumen "kue ajaib".

Pindah
Pindah (sumber, tujuan, nomor, jenis);
Salin (sumber, tujuan, nomor, jenis);
Nol(tujuan, nomor, jenis);

Ketiga makro ini digunakan untuk memindahkan, menyalin, atau menghilangkan memori yang dialokasikan sebelumnya. Itu
Argumen "sumber" dan "tujuan" menunjuk ke titik awal sumber dan tujuan. Perl
akan memindahkan, menyalin, atau menghilangkan contoh "nomor" dari ukuran struktur data "tipe"
(menggunakan fungsi "sizeof").

Perlio


Rilis pengembangan terbaru Perl telah bereksperimen dengan menghapus Perl's
ketergantungan pada suite I/O standar "normal" dan mengizinkan implementasi stdio lainnya untuk
digunakan. Ini melibatkan pembuatan lapisan abstraksi baru yang kemudian memanggil mana saja
implementasi stdio Perl dikompilasi dengan. Semua XSUB sekarang harus menggunakan fungsi di
lapisan abstraksi PerlIO dan tidak membuat asumsi tentang jenis stdio itu
sedang digunakan.

Untuk deskripsi lengkap tentang abstraksi PerlIO, lihat perlapio.

Disusun kode


Kode pohon
Di sini kami menjelaskan bentuk internal kode Anda diubah oleh Perl. Mulailah dengan yang sederhana
contoh:

$a = $b + $c;

Ini diubah menjadi pohon yang mirip dengan yang ini:

menetapkan ke
/\
+ $a
/\
$b $c

(tapi sedikit lebih rumit). Pohon ini mencerminkan cara Perl menguraikan kode Anda, tetapi
tidak ada hubungannya dengan perintah eksekusi. Ada "utas" tambahan yang melalui
node pohon yang menunjukkan urutan eksekusi node. Dalam kami yang disederhanakan
contoh di atas terlihat seperti:

$b ---> $c ---> + ---> $a ---> assign-to

Tetapi dengan pohon kompilasi yang sebenarnya untuk "$a = $b + $c" itu berbeda: beberapa node dioptimalkan
jauh. Sebagai akibat wajar, meskipun pohon sebenarnya berisi lebih banyak node daripada yang disederhanakan
contoh, urutan eksekusi sama seperti pada contoh kita.

Memeriksa itu pohon
Jika Anda memiliki perl yang dikompilasi untuk debugging (biasanya dilakukan dengan "-DDEBUGGING" di
baris perintah "Konfigurasi"), Anda dapat memeriksa pohon yang dikompilasi dengan menentukan "-Dx" di
Baris perintah Perl. Outputnya membutuhkan beberapa baris per node, dan untuk "$b+$c" sepertinya
ini:

5 JENIS = tambahkan ===> 6
TAR = 1
BENDERA = (SKALA, ANAK-ANAK)
{
JENIS = null ===> (4)
(adalah rv2sv)
BENDERA = (SKALA, ANAK-ANAK)
{
3 JENIS = gvsv ===> 4
BENDERA = (SKALAR)
GV = utama::b
}
}
{
JENIS = null ===> (5)
(adalah rv2sv)
BENDERA = (SKALA, ANAK-ANAK)
{
4 JENIS = gvsv ===> 5
BENDERA = (SKALAR)
GV = utama::c
}
}

Pohon ini memiliki 5 simpul (satu per penentu "JENIS"), hanya 3 di antaranya yang tidak dioptimalkan
(satu per nomor di kolom kiri). Anak-anak langsung dari simpul yang diberikan sesuai
untuk memasangkan "{}" pada tingkat lekukan yang sama, dengan demikian cantuman ini sesuai dengan pohonnya:

menambahkan
/\
nol nol
| |
gvsv gvsv

Perintah eksekusi ditunjukkan oleh tanda "===>", jadi "3 4 5 6" (simpul 6 tidak
termasuk ke dalam daftar di atas), yaitu, "gvsv gvsv tambahkan apa pun".

Masing-masing node ini mewakili op, operasi fundamental di dalam inti Perl. Itu
kode yang mengimplementasikan setiap operasi dapat ditemukan di hal*.c file; fungsi yang
mengimplementasikan op dengan tipe "gvsv" adalah "pp_gvsv", dan seterusnya. Seperti yang ditunjukkan oleh pohon di atas,
operasi yang berbeda memiliki jumlah anak yang berbeda: "tambah" adalah operator biner, seperti yang akan dilakukan
mengharapkan, dan memiliki dua anak. Untuk mengakomodasi berbagai nomor yang berbeda dari
anak-anak, ada berbagai jenis struktur data op, dan mereka saling terhubung dalam
cara yang berbeda.

Jenis struktur op yang paling sederhana adalah "OP": ini tidak memiliki anak. operator unary,
"UNOP", punya satu anak, dan ini ditunjukkan oleh bidang "op_first". Operator biner
("BINOP") tidak hanya memiliki bidang "op_first" tetapi juga bidang "op_last". Yang paling
jenis kompleks op adalah "LISTOP", yang memiliki sejumlah anak. Dalam hal ini,
anak pertama ditunjuk oleh "op_first" dan anak terakhir oleh "op_last". Anak-anak di
antara dapat ditemukan dengan iteratif mengikuti penunjuk "OpSIBLING" dari anak pertama
sampai yang terakhir (tapi lihat di bawah).

Ada juga beberapa jenis op lainnya: "PMOP" memiliki ekspresi reguler, dan tidak memiliki
anak-anak, dan "LOOP" mungkin atau mungkin tidak memiliki anak. Jika bidang "op_children" bukan
nol, itu berperilaku seperti "LISTOP". Untuk memperumit masalah, jika "UNOP" sebenarnya adalah "null"
op setelah optimasi (lihat "Kompilasi pass 2: propagasi konteks") itu akan tetap ada
anak sesuai dengan tipe sebelumnya.

Akhirnya, ada "LOGOP", atau logika op. Seperti "LISTOP", ini memiliki satu atau lebih anak,
tetapi tidak memiliki bidang "op_last": jadi Anda harus mengikuti "op_first" dan kemudian
Rantai "OpSIBLING" itu sendiri untuk menemukan anak terakhir. Sebaliknya ia memiliki bidang "op_other", yang
sebanding dengan bidang "op_next" yang dijelaskan di bawah, dan mewakili alternatif
jalur eksekusi. Operator seperti "dan", "atau" dan "?" adalah "LOGOP". Perhatikan bahwa secara umum,
"op_other" tidak boleh menunjuk ke salah satu turunan langsung dari "LOGOP".

Mulai versi 5.21.2, perl yang dibuat dengan definisi eksperimental "-DPERL_OP_PARENT"
tambahkan flag boolean ekstra untuk setiap operasi, "op_moresib". Bila tidak disetel, ini menunjukkan bahwa
ini adalah operasi terakhir dalam rantai "OpSIBLING". Ini membebaskan bidang "op_sibling" di
saudara terakhir yang menunjuk kembali ke operasi induk. Di bawah build ini, bidang itu juga diganti namanya
"op_sibparent" untuk mencerminkan peran bersamanya. Makro OpSIBLING(o) membungkus spesial ini
perilaku, dan selalu mengembalikan NULL pada saudara terakhir. Dengan ini membangun op_parent(o)
fungsi dapat digunakan untuk menemukan induk dari setiap op. Jadi untuk kompatibilitas ke depan, Anda
harus selalu menggunakan makro OpSIBLING(o) daripada mengakses "op_sibling" secara langsung.

Cara lain untuk memeriksa pohon adalah dengan menggunakan modul back-end compiler, seperti B::Concise.

Menyusun lulus 1: memeriksa rutinitas
Pohon dibuat oleh kompiler sementara yacc kode memberinya makan konstruksi itu
mengakui. Sejak yacc bekerja dari bawah ke atas, begitu juga pass pertama dari kompilasi Perl.

Apa yang membuat pass ini menarik bagi pengembang Perl adalah bahwa beberapa pengoptimalan mungkin
dilakukan pada pass ini. Ini adalah optimasi dengan apa yang disebut "periksa rutin". Itu
korespondensi antara nama node dan rutinitas pemeriksaan yang sesuai dijelaskan dalam
opcode.pl (jangan lupa untuk menjalankan "make regen_headers" jika Anda memodifikasi file ini).

Sebuah rutin pemeriksaan dipanggil ketika node sepenuhnya dibangun kecuali untuk eksekusi-
urutan benang. Karena saat ini tidak ada tautan balik ke bangunan yang sedang dibangun
node, seseorang dapat melakukan hampir semua operasi ke node tingkat atas, termasuk membebaskannya dan/atau
membuat node baru di atas/di bawahnya.

Rutin pemeriksaan mengembalikan node yang harus dimasukkan ke dalam pohon (jika top-
node level tidak dimodifikasi, periksa rutin mengembalikan argumennya).

Dengan konvensi, rutinitas periksa memiliki nama "ck_*". Mereka biasanya dipanggil dari "new*OP"
subrutin (atau "mengubah") (yang pada gilirannya disebut dari perly.y).

Menyusun lulus 1a: konstan lipat
Segera setelah pemeriksaan rutin dipanggil, simpul yang dikembalikan diperiksa keberadaannya
waktu kompilasi dapat dieksekusi. Jika ya (nilainya dianggap konstan) maka segera
dieksekusi, dan konstan simpul dengan "nilai kembalian" dari subpohon yang sesuai adalah
diganti sebagai gantinya. Subpohon dihapus.

Jika pelipatan konstan tidak dilakukan, utas perintah eksekusi dibuat.

Menyusun lulus 2: konteks perambatan
Ketika konteks untuk bagian dari pohon kompilasi diketahui, itu disebarkan ke bawah melalui
pohon. Saat ini konteks dapat memiliki 5 nilai (bukan 2 untuk konteks runtime):
void, boolean, skalar, daftar, dan nilai. Berbeda dengan pass 1 pass ini adalah
diproses dari atas ke bawah: konteks simpul menentukan konteks untuk anak-anaknya.

Pengoptimalan bergantung konteks tambahan dilakukan saat ini. Sejak saat ini
saat pohon kompilasi berisi referensi-balik (melalui pointer "utas"), node tidak dapat
Gratis()sekarang. Untuk memungkinkan node yang jauh dioptimalkan pada tahap ini, node tersebut adalah batal()bersatu
alih-alih Gratis()ing (yaitu tipenya diubah menjadi OP_NULL).

Menyusun lulus 3: lubang pengintip optimasi
Setelah pohon kompilasi untuk subrutin (atau untuk "eval" atau file) dibuat, dan
tambahan melewati kode dilakukan. Pass ini tidak top-down atau bottom-up,
tetapi dalam urutan eksekusi (dengan komplikasi tambahan untuk persyaratan).
Pengoptimalan yang dilakukan pada tahap ini tunduk pada batasan yang sama seperti pada pass
2.

Optimalisasi lubang intip dilakukan dengan memanggil fungsi yang ditunjuk oleh variabel global
"PL_peepp". Secara default, "PL_peepp" hanya memanggil fungsi yang ditunjuk oleh global
variabel "PL_rpeepp". Secara default, itu melakukan beberapa perbaikan dan optimisasi op dasar
di sepanjang rantai operasi perintah-eksekusi, dan secara rekursif memanggil "PL_rpeepp" untuk setiap rantai samping
dari ops (dihasilkan dari conditional). Ekstensi dapat memberikan pengoptimalan tambahan atau
fixups, menghubungkan ke tahap per-subrutin atau rekursif, seperti ini:

peep_t statis prev_peepp;
statis batal my_peep(pTHX_ OP *o)
{
/* optimasi kustom per-subrutin ada di sini */
prev_peepp(aTHX_o);
/* optimasi per-subrutin kustom juga dapat dilakukan di sini */
}
SEPATU:
prev_peepp = PL_peepp;
PL_peepp = my_peep;

peep_t statis prev_rpeepp;
statis batal my_rpeep(pTHX_ OP *o)
{
OP *asal_o = o;
untuk(; o; o = o->op_next) {
/* optimasi per operasi kustom ada di sini */
}
prev_rpeepp(aTHX_orig_o);
}
SEPATU:
sebelumnya_rpeepp = PL_rpeepp;
PL_rpeepp = my_rpeep;

Pluggable runop
Pohon kompilasi dijalankan dalam fungsi runops. Ada dua fungsi runop, di
lari.c dan dalam dump.c. "Perl_runops_debug" digunakan dengan DEBUGGING dan
"Perl_runops_standard" digunakan sebaliknya. Untuk kontrol yang baik atas pelaksanaan
kompilasi pohon dimungkinkan untuk menyediakan fungsi runops Anda sendiri.

Mungkin yang terbaik adalah menyalin salah satu fungsi runop yang ada dan mengubahnya agar sesuai dengan Anda
kebutuhan. Kemudian, di bagian BOOT file XS Anda, tambahkan baris:

PL_runops = my_runops;

Fungsi ini harus seefisien mungkin agar program Anda berjalan secepat
mungkin.

Waktu kompilasi cakupan kait
Pada Perl 5.14 dimungkinkan untuk menghubungkan ke mekanisme ruang lingkup leksikal waktu kompilasi menggunakan
"Perl_blockhook_register". Ini digunakan seperti ini:

STATIC void my_start_hook(pTHX_ int penuh);
STATIS BHK my_hooks;

SEPATU:
BhkENTRY_set(&my_hooks, bhk_start, my_start_hook);
Perl_blockhook_register(aTHX_ &my_hooks);

Ini akan mengatur agar "my_start_hook" dipanggil pada awal kompilasi setiap leksikal
cakupan. Kait yang tersedia adalah:

"void bhk_start(pTHX_ int penuh)"
Ini disebut tepat setelah memulai lingkup leksikal baru. Perhatikan bahwa kode Perl seperti

jika ($x) { ... }

membuat dua cakupan: yang pertama dimulai pada "(" dan memiliki "penuh == 1", yang kedua dimulai
di "{" dan memiliki "penuh == 0". Keduanya berakhir di "}", jadi panggilan ke "mulai" dan
"pre/post_end" akan cocok. Apa pun yang didorong ke save stack dengan hook ini akan menjadi
muncul tepat sebelum ruang lingkup berakhir (di antara kait "pre_" dan "post_end", sebenarnya).

"void bhk_pre_end(pTHX_ OP **o)"
Ini disebut di akhir lingkup leksikal, tepat sebelum melepas tumpukan. o is
akar dari optree yang mewakili ruang lingkup; itu adalah penunjuk ganda sehingga Anda bisa
ganti OP jika perlu.

"void bhk_post_end(pTHX_ OP **o)"
Ini disebut di akhir lingkup leksikal, tepat setelah melepas tumpukan. o adalah sebagai
di atas. Perhatikan bahwa panggilan ke "pre_" dan "post_end" dimungkinkan untuk bersarang, jika ada
adalah sesuatu di save stack yang memanggil string eval.

"void bhk_eval(pTHX_ OP *const o)"
Ini dipanggil tepat sebelum mulai mengkompilasi "eval STRING", "do FILE", "require"
atau "gunakan", setelah eval diatur. o adalah OP yang meminta evaluasi, dan
biasanya berupa "OP_ENTEREVAL", "OP_DOFILE" atau "OP_REQUIRE".

Setelah Anda memiliki fungsi kait, Anda memerlukan struktur "BHK" untuk memasangnya. Ini yang terbaik
untuk mengalokasikannya secara statis, karena tidak ada cara untuk membebaskannya setelah didaftarkan. Itu
pointer fungsi harus dimasukkan ke dalam struktur ini menggunakan makro "BhkENTRY_set",
yang juga akan menyetel tanda yang menunjukkan entri mana yang valid. Jika Anda perlu mengalokasikan
"BHK" Anda secara dinamis untuk beberapa alasan, pastikan untuk nol sebelum Anda mulai.

Setelah terdaftar, tidak ada mekanisme untuk mematikan pengait ini, jadi jika itu perlu
Anda akan perlu melakukan ini sendiri. Entri di "%^H" mungkin adalah cara terbaik, jadi
efek dicakup secara leksikal; namun juga dimungkinkan untuk menggunakan "BhkDISABLE" dan
Makro "BhkENABLE" untuk mengaktifkan dan menonaktifkan entri untuk sementara. Anda juga harus sadar
bahwa secara umum setidaknya satu ruang lingkup akan dibuka sebelum ekstensi Anda
dimuat, jadi Anda akan melihat beberapa pasangan "pre/post_end" yang tidak memiliki "start" yang cocok.

Memeriksa intern data struktur dengan itu "membuang" fungsi


Untuk membantu debugging, file sumber dump.c mengandung sejumlah fungsi yang menghasilkan
keluaran terformat dari struktur data internal.

Yang paling umum digunakan dari fungsi ini adalah "Perl_sv_dump"; ini digunakan untuk membuang SV,
AV, HV, dan CV. Modul "Devel::Peek" memanggil "sv_dump" untuk menghasilkan output debugging
dari Perl-space, jadi pengguna modul itu seharusnya sudah terbiasa dengan formatnya.

"Perl_op_dump" dapat digunakan untuk membuang struktur "OP" atau turunannya, dan
menghasilkan keluaran yang mirip dengan "perl -Dx"; sebenarnya, "Perl_dump_eval" akan membuang root utama
kode yang sedang dievaluasi, persis seperti "-Dx".

Fungsi berguna lainnya adalah "Perl_dump_sub", yang mengubah "GV" menjadi pohon op,
"Perl_dump_packsubs" yang memanggil "Perl_dump_sub" pada semua subrutin dalam satu paket seperti
jadi: (Untungnya, ini semua xsubs, jadi tidak ada pohon op)

(gdb) cetak Perl_dump_packsubs(PL_defstash)

Atribut SUB::bootstrap = (xsub 0x811fedc 0)

SUB UNIVERSAL::bisa = (xsub 0x811f50c 0)

SUB UNIVERSAL::isa = (xsub 0x811f304 0)

SUB UNIVERSAL::VERSI = (xsub 0x811f7ac 0)

SUB DynaLoader::boot_DynaLoader = (xsub 0x805b188 0)

dan "Perl_dump_all", yang membuang semua subrutin di simpanan dan pohon op dari
akar utama.

Seterpercayaapakah Olymp Trade? Kesimpulan beberapa juru bahasa dan konkurensi adalah didukung


Latar Belakang dan PERL_IMPLICIT_CONTEXT
Penerjemah Perl dapat dianggap sebagai kotak tertutup: ia memiliki API untuk memasukkan kode atau
jika tidak membuatnya melakukan sesuatu, tetapi juga memiliki fungsi untuk digunakan sendiri. Ini bau a
banyak seperti objek, dan ada cara bagi Anda untuk membangun Perl sehingga Anda dapat memiliki banyak
interpreter, dengan satu interpreter direpresentasikan sebagai struktur C, atau di dalam a
struktur khusus benang. Struktur ini mengandung semua konteks, keadaan itu
penerjemah.

Satu makro mengontrol rasa build Perl utama: MULTIPLICITY. Build MULTIPLICITY memiliki
struktur C yang mengemas semua status juru bahasa. Dengan perl berkemampuan multiplisitas,
PERL_IMPLICIT_CONTEXT juga didefinisikan secara normal, dan memungkinkan dukungan untuk meneruskan a
argumen pertama "tersembunyi" yang mewakili ketiga struktur data. MULTIPLISITAS membuat
kemungkinan multi-threaded perls (dengan model threading itthreads, terkait dengan makro
GUNAKAN_ITHREADS.)

Dua makro "enkapsulasi" lainnya adalah PERL_GLOBAL_STRUCT dan PERL_GLOBAL_STRUCT_PRIVATE
(yang terakhir menyalakan yang pertama, dan yang pertama menyalakan MULTIPLICITY.) The
PERL_GLOBAL_STRUCT menyebabkan semua variabel internal Perl dibungkus menjadi satu
struct global, struct perl_vars, dapat diakses sebagai (global) &PL_Vars atau PL_VarsPtr atau
fungsi Perl_GetVars(). PERL_GLOBAL_STRUCT_PRIVATE melangkah lebih jauh, ada
masih satu struct (dialokasikan dalam utama() baik dari heap atau dari stack) tetapi ada
tidak ada simbol data global yang menunjuk ke sana. Dalam kedua kasus, struktur global harus
diinisialisasi sebagai hal pertama di utama() menggunakan Perl_init_global_struct() dan
dengan demikian meruntuhkannya setelah perl_gratis() menggunakan Perl_free_global_struct(), tolong lihat
miniperlmain.c untuk detail penggunaan. Anda mungkin juga perlu menggunakan "dVAR" dalam pengkodean Anda untuk
"deklarasikan variabel global" saat Anda menggunakannya. dTHX melakukan ini untuk Anda
otomatis.

Untuk melihat apakah Anda memiliki data non-const, Anda dapat menggunakan "nm" yang kompatibel dengan BSD (atau GNU):

nm libperl.a | grep -v ' [TURtr] '

Jika ini menampilkan simbol "D" atau "d" (atau mungkin "C" atau "c"), Anda memiliki data non-const.
Simbol yang "grep" dihapus adalah sebagai berikut: "Tt" adalah teks, atau kode, "Rr" adalah Baca-
hanya (const) data, dan "U" adalah , simbol eksternal yang dirujuk.

Ujian t/porting/libperl.t melakukan pemeriksaan kewarasan simbol semacam ini pada "libperl.a".

Untuk alasan kompatibilitas mundur mendefinisikan hanya PERL_GLOBAL_STRUCT tidak benar-benar menyembunyikan
semua simbol di dalam struct global besar: beberapa vtables PerlIO_xxx dibiarkan terlihat. Itu
PERL_GLOBAL_STRUCT_PRIVATE kemudian menyembunyikan semuanya (lihat bagaimana PERLIO_FUNCS_DECL digunakan).

Semua ini jelas membutuhkan cara agar fungsi internal Perl menjadi subrutin
mengambil semacam struktur sebagai argumen pertama, atau subrutin tidak mengambil apa pun sebagai
argumen pertama. Untuk mengaktifkan dua cara yang sangat berbeda ini dalam membangun juru bahasa,
Sumber Perl (seperti halnya dalam banyak situasi lain) banyak menggunakan makro dan
konvensi penamaan subrutin.

Masalah pertama: memutuskan fungsi mana yang akan menjadi fungsi API publik dan mana yang akan menjadi
pribadi. Semua fungsi yang namanya dimulai "S_" bersifat pribadi (pikirkan "S" untuk "rahasia" atau
"statis"). Semua fungsi lainnya dimulai dengan "Perl_", tetapi hanya karena suatu fungsi dimulai
dengan "Perl_" tidak berarti itu adalah bagian dari API. (Lihat "Fungsi Internal".)
cara termudah untuk menjadi yakin sebuah fungsi yang merupakan bagian dari API adalah mencari entrinya di perlapi. Jika
itu ada di perlapi, itu bagian dari API. Jika tidak, dan menurut Anda seharusnya begitu
(yaitu, Anda memerlukannya untuk ekstensi Anda), kirim email melalui perlbug menjelaskan mengapa Anda berpikir demikian
seharusnya.

Masalah kedua: harus ada sintaks sehingga deklarasi dan panggilan subrutin yang sama
dapat melewati struktur sebagai argumen pertama mereka, atau tidak melewatkan apa pun. Untuk mengatasi ini,
subrutin diberi nama dan dideklarasikan dengan cara tertentu. Inilah awal yang khas dari a
fungsi statis yang digunakan dalam nyali Perl:

kekosongan STATIS
S_kemiringan(pTHX_ char *s)

STATIC menjadi "statis" di C, dan mungkin #define'd apa-apa dalam beberapa konfigurasi di
masa depan.

Fungsi publik (yaitu bagian dari API internal, tetapi tidak harus disetujui untuk digunakan
di ekstensi) dimulai seperti ini:

membatalkan
Perl_sv_setiv(pTHX_ SV* dsv, nomor IV)

"pTHX_" adalah salah satu dari sejumlah makro (dalam perl.h) yang menyembunyikan detail dari
konteks penafsir. THX adalah singkatan dari "utas", "ini", atau "benda", tergantung kasusnya.
(Dan tidak, George Lucas tidak terlibat. :-) Karakter pertama bisa jadi 'p' untuk a
prototipe, 'a' untuk argument, atau 'd' untuk dpernyataan, jadi kami memiliki "pTHX", "aTHX" dan "dTHX",
dan variannya.

Ketika Perl dibangun tanpa opsi yang mengatur PERL_IMPLICIT_CONTEXT, tidak ada yang pertama
argumen yang mengandung konteks penafsir. Garis bawah tambahan di makro pTHX_
menunjukkan bahwa ekspansi makro memerlukan koma setelah argumen konteks karena lainnya
argumen mengikutinya. Jika PERL_IMPLICIT_CONTEXT tidak ditentukan, pTHX_ akan diabaikan, dan
subrutin tidak dibuat prototipe untuk mengambil argumen tambahan. Bentuk makronya
tanpa garis bawah tambahan digunakan ketika tidak ada argumen eksplisit tambahan.

Ketika fungsi inti memanggil yang lain, itu harus melewati konteks. Ini biasanya disembunyikan melalui
makro. Pertimbangkan "sv_setiv". Ini berkembang menjadi sesuatu seperti ini:

#ifdef PERL_IMPLICIT_CONTEXT
#define sv_setiv(a,b) Perl_sv_setiv(aTHX_a, b)
/* tidak dapat melakukan ini untuk fungsi vararg, lihat di bawah */
#lain
#define sv_setiv Perl_sv_setiv
#berakhir jika

Ini berfungsi dengan baik, dan berarti penulis XS dapat dengan senang hati menulis:

sv_setiv(foo, bilah);

dan masih berfungsi di bawah semua mode yang dapat dikompilasi dengan Perl.

Ini tidak berfungsi dengan baik untuk fungsi varargs, karena makro menyiratkan bahwa
jumlah argumen diketahui sebelumnya. Sebaliknya kita juga perlu mengejanya sepenuhnya,
meneruskan "aTHX_" sebagai argumen pertama (inti Perl cenderung melakukan ini dengan fungsi seperti
Perl_warner), atau gunakan versi bebas konteks.

Versi bebas konteks dari Perl_warner disebut Perl_warner_nocontext, dan tidak menggunakan
argumen tambahan. Sebaliknya ia melakukan dTHX; untuk mendapatkan konteks dari penyimpanan lokal-utas.
Kami "#define warner Perl_warner_nocontext" sehingga ekstensi mendapatkan kompatibilitas sumber di
biaya kinerja. (Melewati arg lebih murah daripada mengambilnya dari thread-local
penyimpanan.)

Anda dapat mengabaikan [pad]THXx saat menelusuri header/sumber Perl. Itu hanya untuk
gunakan di dalam inti. Ekstensi dan penyemat hanya perlu mengetahui [pad]THX.

So apa terjadi untuk dTHR?
"dTHR" diperkenalkan di Perl 5.005 untuk mendukung model utas yang lebih lama. Utas yang lebih tua
model sekarang menggunakan mekanisme "THX" untuk meneruskan pointer konteks, jadi "dTHR" tidak
berguna lagi. Perl 5.6.0 dan yang lebih baru masih memilikinya untuk kompatibilitas sumber mundur,
tapi itu didefinisikan sebagai no-op.

Seterpercayaapakah Olymp Trade? Kesimpulan do I menggunakan semua ini in ekstensi?
Saat Perl dibuat dengan PERL_IMPLICIT_CONTEXT, ekstensi yang memanggil fungsi apa pun di
Perl API harus melewati argumen konteks awal. Penendangnya adalah kamu
perlu menulisnya sedemikian rupa sehingga ekstensi masih dapat dikompilasi ketika Perl belum
telah dibangun dengan PERL_IMPLICIT_CONTEXT diaktifkan.

Ada tiga cara untuk melakukan ini. Pertama, cara yang mudah namun tidak efisien, yang juga merupakan
default, untuk menjaga kompatibilitas sumber dengan ekstensi: kapanpun XSUB.h is
#include, ini mendefinisikan ulang makro aTHX dan aTHX_ untuk memanggil fungsi yang akan mengembalikan
konteks. Jadi, sesuatu seperti:

sv_setiv(sv, angka);

di ekstensi Anda akan diterjemahkan menjadi ini ketika PERL_IMPLICIT_CONTEXT berlaku:

Perl_sv_setiv(Perl_get_context(), sv, angka);

atau sebaliknya:

Perl_sv_setiv(sv, angka);

Anda tidak perlu melakukan sesuatu yang baru di ekstensi Anda untuk mendapatkan ini; sejak perpustakaan Perl
menyediakan Perl_get_konteks(), itu semua hanya akan bekerja.

Cara kedua yang lebih efisien adalah dengan menggunakan template berikut untuk Foo.xs Anda:

#define PERL_NO_GET_CONTEXT /* kita ingin efisiensi */
#sertakan "EKSTERN.h"
#sertakan "perl.h"
#sertakan "XSUB.h"

STATIS membatalkan my_private_function(int arg1, int arg2);

kekosongan STATIS
fungsi_pribadi saya(int arg1, int arg2)
{
dTHX; /* mengambil konteks */
... memanggil banyak fungsi Perl API ...
}

[... dll ...]

MODUL = FOO PAKET = FOO

/* tipikal XSUB */

membatalkan
my_xsub(arg)
ke dalam argumen
KODE:
fungsi_pribadi saya(arg, 10);

Perhatikan bahwa hanya dua perubahan dari cara normal menulis ekstensi adalah penambahan
dari "#define PERL_NO_GET_CONTEXT" sebelum menyertakan header Perl, diikuti oleh
"dTHX;" deklarasi di awal setiap fungsi yang akan memanggil Perl API. (Anda akan
tahu fungsi mana yang membutuhkan ini, karena kompiler C akan mengeluh bahwa ada
pengidentifikasi tidak dideklarasikan dalam fungsi-fungsi itu.) Tidak ada perubahan yang diperlukan untuk XSUBs
sendiri, karena XS() makro didefinisikan dengan benar untuk lulus dalam konteks implisit jika
dibutuhkan.

Cara ketiga, yang bahkan lebih efisien adalah dengan meniru bagaimana hal itu dilakukan dalam nyali Perl:

#define PERL_NO_GET_CONTEXT /* kita ingin efisiensi */
#sertakan "EKSTERN.h"
#sertakan "perl.h"
#sertakan "XSUB.h"

/* pTHX_ hanya diperlukan untuk fungsi yang memanggil Perl API */
STATIS membatalkan my_private_function(pTHX_ int arg1, int arg2);

kekosongan STATIS
fungsi_pribadi saya(pTHX_ int arg1, int arg2)
{
/* dTHX; tidak diperlukan di sini, karena THX adalah argumen */
... memanggil fungsi Perl API ...
}

[... dll ...]

MODUL = FOO PAKET = FOO

/* tipikal XSUB */

membatalkan
my_xsub(arg)
ke dalam argumen
KODE:
my_private_function(aTHX_arg, 10);

Implementasi ini tidak perlu mengambil konteks menggunakan pemanggilan fungsi, karena ini
selalu lulus sebagai argumen tambahan. Tergantung pada kebutuhan Anda akan kesederhanaan atau efisiensi,
Anda dapat mencampur dua pendekatan sebelumnya secara bebas.

Jangan pernah menambahkan koma setelah "pTHX" sendiri--selalu gunakan bentuk makro dengan
garis bawah untuk fungsi yang mengambil argumen eksplisit, atau bentuk tanpa argumen
untuk fungsi tanpa argumen eksplisit.

Jika seseorang mengkompilasi Perl dengan "-DPERL_GLOBAL_STRUCT", definisi "dVAR" diperlukan
jika variabel global Perl (lihat perlvars.h or globvar.sym) diakses dalam fungsi
dan "dTHX" tidak digunakan ("dTHX" termasuk "dVAR" jika perlu). Seseorang memperhatikan
kebutuhan untuk "dVAR" hanya dengan definisi waktu kompilasi tersebut, karena jika tidak, Perl global
variabel terlihat apa adanya.

Harus I do apa saja khusus if I panggilan perl dari beberapa benang?
Jika Anda membuat juru bahasa di satu utas dan kemudian melanjutkan untuk memanggil mereka di utas lain, Anda
perlu memastikan slot Thread Local Storage (TLS) milik Perl diinisialisasi dengan benar di
masing-masing benang tersebut.

Fungsi API "perl_alloc" dan "perl_clone" akan secara otomatis menyetel slot TLS ke
penerjemah yang mereka buat, sehingga tidak perlu melakukan sesuatu yang istimewa jika
penerjemah selalu diakses di utas yang sama yang membuatnya, dan utas itu tidak
buat atau panggil juru bahasa lain setelahnya. Jika bukan itu masalahnya, Anda harus
atur slot TLS dari utas sebelum memanggil fungsi apa pun di Perl API pada itu
penerjemah tertentu. Ini dilakukan dengan memanggil makro "PERL_SET_CONTEXT" di dalamnya
utas sebagai hal pertama yang Anda lakukan:

/* lakukan ini sebelum melakukan hal lain dengan some_perl */
PERL_SET_CONTEXT(beberapa_perl);

... panggilan API Perl lainnya di some_perl buka di sini ...

Masa depan rencana dan PERL_IMPLICIT_SYS
Sama seperti PERL_IMPLICIT_CONTEXT menyediakan cara untuk menggabungkan segala sesuatu yang penerjemah
tahu tentang dirinya sendiri dan menyebarkannya, demikian juga apakah ada rencana untuk mengizinkan penerjemah untuk
menggabungkan semua yang ia ketahui tentang lingkungan tempat ia berjalan. Ini diaktifkan dengan
makro PERL_IMPLICIT_SYS. Saat ini hanya bekerja dengan USE_ITHREADS di Windows.

Ini memungkinkan kemampuan untuk memberikan pointer tambahan (disebut lingkungan "host") untuk
semua panggilan sistem. Ini memungkinkan semua hal sistem untuk mempertahankan
negara sendiri, dipecah menjadi tujuh struktur C. Ini adalah pembungkus tipis di sekitar yang biasa
panggilan sistem (lihat win32/perllib.c) untuk perl default yang dapat dieksekusi, tetapi untuk lebih
tuan rumah yang ambisius (seperti yang akan dilakukan garpu() emulasi) semua pekerjaan ekstra yang diperlukan untuk
berpura-pura bahwa penafsir yang berbeda sebenarnya adalah "proses" yang berbeda, akan dilakukan
sini.

Mesin/interpreter Perl dan host adalah entitas ortogonal. Mungkin ada satu atau
lebih banyak penafsir dalam suatu proses, dan satu atau lebih "host", dengan asosiasi bebas antara
Mereka.

Intern Fungsi


Semua fungsi internal Perl yang akan diekspos ke dunia luar diberi awalan
oleh "Perl_" sehingga tidak akan bertentangan dengan fungsi XS atau fungsi yang digunakan dalam suatu program
di mana Perl tertanam. Demikian pula, semua variabel global dimulai dengan "PL_". (Oleh
konvensi, fungsi statis dimulai dengan "S_".)

Di dalam inti Perl ("PERL_CORE" didefinisikan), Anda bisa mendapatkan fungsi baik dengan atau
tanpa awalan "Perl_", berkat sekumpulan definisi yang ada di sematkan.h. Catat itu
kode ekstensi harus tidak setel "PERL_CORE"; ini mengekspos internal Perl penuh, dan adalah
cenderung menyebabkan kerusakan XS di setiap rilis Perl baru.

File sematkan.h dihasilkan secara otomatis dari semat.pl dan semat.fnc. semat.pl juga
membuat file header prototipe untuk fungsi internal, menghasilkan
dokumentasi dan banyak bagian lainnya. Sangat penting bahwa ketika Anda menambahkan yang baru
berfungsi ke inti atau mengubah yang sudah ada, Anda mengubah data dalam tabel di
semat.fnc demikian juga. Berikut adalah contoh entri dari tabel itu:

Apd |SV** |av_fetch |AV* ar|Kunci I32|I32 lval

Kolom kedua adalah tipe pengembalian, kolom ketiga adalah nama. Kolom setelah itu adalah
argumen. Kolom pertama adalah satu set bendera:

A Fungsi ini adalah bagian dari API publik. Semua fungsi tersebut juga harus memiliki 'd',
sangat sedikit yang tidak.

p Fungsi ini memiliki awalan "Perl_"; yaitu didefinisikan sebagai "Perl_av_fetch".

d Fungsi ini memiliki dokumentasi menggunakan fitur "apidoc" yang akan kita lihat di a
kedua. Beberapa fungsi memiliki 'd' tetapi tidak memiliki 'A'; dokumen baik.

Bendera lain yang tersedia adalah:

s Ini adalah fungsi statis dan didefinisikan sebagai "STATIC S_whatever", dan biasanya disebut
dalam sumber sebagai "apa pun (...)".

n Ini tidak memerlukan konteks penerjemah, jadi definisinya tidak memiliki "pTHX", dan itu
berikut bahwa penelepon tidak menggunakan "aTHX". (Lihat "Latar Belakang dan PERL_IMPLICIT_CONTEXT".)

r Fungsi ini tidak pernah kembali; "croak", "keluar" dan teman-teman.

f Fungsi ini mengambil sejumlah variabel argumen, gaya "printf". Daftar argumen
harus diakhiri dengan "...", seperti ini:

Afprd |void |parau |const char* tepuk|...

M Fungsi ini adalah bagian dari API pengembangan eksperimental, dan dapat berubah atau menghilang
tanpa pemberitahuan.

o Fungsi ini seharusnya tidak memiliki makro kompatibilitas untuk mendefinisikan, misalnya, "Perl_parse" ke
"mengurai". Itu harus disebut sebagai "Perl_parse".

x Fungsi ini tidak diekspor dari inti Perl.

m Ini diimplementasikan sebagai makro.

X Fungsi ini diekspor secara eksplisit.

E Fungsi ini terlihat oleh ekstensi yang termasuk dalam inti Perl.

b Kompatibilitas mundur biner; fungsi ini adalah makro tetapi juga memiliki "Perl_"
implementasi (yang diekspor).

orang lain
Lihat komentar di bagian atas "embed.fnc" untuk orang lain.

Jika Anda mengedit semat.pl or semat.fnc, Anda harus menjalankan "make regen_headers" untuk memaksa a
membangun kembali sematkan.h dan file yang dibuat secara otomatis lainnya.

Diformat Pencetakan of infus, UV, dan NV
Jika Anda mencetak IV, UV, atau NVS alih-alih tempat tinggal(3) kode pemformatan gaya seperti
%d, %ld, %f, Anda harus menggunakan makro berikut untuk portabilitas

IVdf IV dalam desimal
UVuf UV dalam desimal
UV dari UV dalam oktal
UVxf UV dalam heksadesimal
NVef NV %e-suka
NVff NV %f-suka
NVgf NV %g-suka

Ini akan menangani bilangan bulat 64-bit dan ganda panjang. Sebagai contoh:

printf("IV adalah %"IVdf"\n", iv);

IVdf akan diperluas ke format apa pun yang benar untuk infus.

Perhatikan bahwa ada "ganda panjang" yang berbeda: Perl akan menggunakan apa pun yang dimiliki kompiler.

Jika Anda mencetak alamat pointer, gunakan UVxf yang dikombinasikan dengan PTR2UV(), jangan gunakan %lx
atau %p.

Pointer-Ke-Integer dan Integer-Ke-Pointer
Karena ukuran pointer tidak selalu sama dengan ukuran integer, gunakan makro berikut untuk melakukannya:
itu benar.

PTR2UV (penunjuk)
PTR2IV (penunjuk)
PTR2NV (penunjuk)
INT2PTR(pointertotipe, bilangan bulat)

Sebagai contoh:

IV-iv = ...;
SV *sv = INT2PTR(SV*, iv);

dan

AV *av = ...;
UV uv = PTR2UV(av);

Pengecualian Penanganan
Ada beberapa makro untuk melakukan penanganan pengecualian yang sangat mendasar dalam modul XS. Kamu punya
untuk mendefinisikan "NO_XSLOCKS" sebelum memasukkan XSUB.h untuk dapat menggunakan makro ini:

#tentukan NO_XSLOCKS
#sertakan "XSUB.h"

Anda dapat menggunakan makro ini jika Anda memanggil kode yang mungkin serak, tetapi Anda perlu melakukan pembersihan
sebelum memberikan kontrol kembali ke Perl. Sebagai contoh:

dXCPT; /* mengatur variabel yang diperlukan */

XCPT_TRY_START {
kode_itu_may_croak();
} XCPT_TRY_END

XCPT_CATCH
{
/* lakukan pembersihan di sini */
XCPT_RETHROW;
}

Perhatikan bahwa Anda selalu harus mengulang pengecualian yang telah ditangkap. Menggunakan ini
makro, tidak mungkin hanya menangkap pengecualian dan mengabaikannya. Jika Anda harus
abaikan pengecualian, Anda harus menggunakan fungsi "call_*".

Keuntungan menggunakan makro di atas adalah Anda tidak perlu menyiapkan fungsi tambahan
untuk "call_*", dan menggunakan makro ini lebih cepat daripada menggunakan "call_*".

sumber Dokumentasi
Ada upaya yang dilakukan untuk mendokumentasikan fungsi internal dan secara otomatis menghasilkan
manual referensi dari mereka -- perlapi adalah salah satu manual yang merinci semua fungsi
yang tersedia untuk penulis XS. perlintern adalah manual yang dibuat secara otomatis untuk
fungsi yang bukan bagian dari API dan seharusnya hanya untuk penggunaan internal.

Dokumentasi sumber dibuat dengan memasukkan komentar POD ke dalam sumber C, seperti ini:

/*
=untuk apidoc sv_setiv

Menyalin bilangan bulat ke dalam SV yang diberikan. Tidak menangani sihir 'set'. Melihat
C .

= potong
*/

Silakan coba dan berikan beberapa dokumentasi jika Anda menambahkan fungsi ke inti Perl.

Terbalik kesesuaian
Perl API berubah seiring waktu. Fungsi baru ditambahkan atau antarmuka yang sudah ada
fungsi diubah. Modul "Devel::PPPort" mencoba memberikan kode kompatibilitas untuk
beberapa perubahan ini, jadi penulis XS tidak perlu mengkodekannya sendiri saat mendukung
beberapa versi Perl.

"Devel::PPPort" menghasilkan file header C ppport.h yang juga dapat dijalankan sebagai skrip Perl.
Untuk menghasilkan ppport.h, jalankan:

perl -MDevel::PPPort -eDevel::PPPort::WriteFile

Selain memeriksa kode XS yang ada, skrip juga dapat digunakan untuk mengambil kompatibilitas
informasi untuk berbagai panggilan API menggunakan sakelar baris perintah "--api-info". Untuk
contoh:

% perl ppport.h --api-info=sv_magicext

Untuk detailnya, lihat "perldoc ppport.h".

Unicode Bantuan


Perl 5.6.0 memperkenalkan dukungan Unicode. Penting bagi porter dan penulis XS untuk
pahami dukungan ini dan pastikan kode yang mereka tulis tidak merusak Unicode
Data.

Apa is Unikode, bagaimanapun?
Di masa lalu, kurang tercerahkan, kita semua digunakan untuk menggunakan ASCII. Sebagian besar dari kita melakukannya.
Masalah besar dengan ASCII adalah bahwa itu Amerika. Yah, tidak, itu sebenarnya bukan
masalah; masalahnya adalah itu tidak terlalu berguna untuk orang yang tidak menggunakan
alfabet Romawi. Apa yang biasa terjadi adalah bahwa bahasa tertentu akan melekat pada bahasa mereka sendiri
alfabet di kisaran atas urutan, antara 128 dan 255. Tentu saja, kami kemudian
berakhir dengan banyak varian yang tidak cukup ASCII, dan intinya adalah
sebuah standar hilang.

Lebih buruk lagi, jika Anda memiliki bahasa seperti Cina atau Jepang yang memiliki ratusan atau
ribuan karakter, maka Anda benar-benar tidak dapat memasukkannya ke dalam 256 hanya, jadi mereka harus
lupakan ASCII sama sekali, dan bangun sistem mereka sendiri menggunakan pasangan angka untuk referensi
ke satu karakter.

Untuk memperbaikinya, beberapa orang membentuk Unicode, Inc. dan menghasilkan set karakter baru yang berisi
semua karakter yang mungkin dapat Anda pikirkan dan banyak lagi. Ada beberapa cara untuk
mewakili karakter ini, dan yang digunakan Perl disebut UTF-8. UTF-8 menggunakan a
variabel jumlah byte untuk mewakili karakter. Anda dapat mempelajari lebih lanjut tentang Unicode dan
Model Unicode Perl di perlunicode.

(Pada platform EBCDIC, Perl menggunakan UTF-EBCDIC, yang merupakan bentuk UTF-8 yang diadaptasi untuk
platform EBCDIC. Di bawah ini, kita hanya berbicara tentang UTF-8. UTF-EBCDIC seperti UTF-8, tetapi
detailnya berbeda. Makro menyembunyikan perbedaan dari Anda, ingatlah bahwa
angka dan pola bit tertentu yang disajikan di bawah ini akan berbeda dalam UTF-EBCDIC.)

Seterpercayaapakah Olymp Trade? Kesimpulan bisa I mengakui a UTF-8 rangkaian?
Anda tidak bisa. Ini karena data UTF-8 disimpan dalam byte seperti halnya data non-UTF-8. Itu
Karakter Unicode 200, (0xC8 untuk Anda tipe hex) kapital E dengan aksen serius, adalah
diwakili oleh dua byte "v196.172". Sayangnya, string non-Unicode
"chr(196).chr(172)" memiliki urutan byte itu juga. Jadi Anda tidak dapat mengetahuinya hanya dengan melihat --
inilah yang membuat input Unicode menjadi masalah yang menarik.

Secara umum, Anda harus tahu apa yang Anda hadapi, atau Anda harus menebak. Itu
Fungsi API "is_utf8_string" dapat membantu; itu akan memberi tahu Anda jika string hanya berisi valid
karakter UTF-8, dan kemungkinan string non-UTF-8 terlihat seperti UTF-8 yang valid menjadi
sangat kecil sangat cepat dengan meningkatnya panjang string. Berdasarkan karakter demi karakter,
"isUTF8_CHAR" akan memberi tahu Anda apakah karakter saat ini dalam string adalah UTF-8 yang valid.

Seterpercayaapakah Olymp Trade? Kesimpulan tidak UTF-8 mewakili Unicode karakter?
Seperti disebutkan di atas, UTF-8 menggunakan sejumlah variabel byte untuk menyimpan karakter.
Karakter dengan nilai 0...127 disimpan dalam satu byte, sama seperti ASCII lama.
Karakter 128 disimpan sebagai "v194.128"; ini berlanjut hingga karakter 191, yaitu
"v194.191". Sekarang kita sudah kehabisan bit (191 adalah biner 10111111) jadi kita lanjutkan; karakter
192 adalah "v195.128". Dan begitu seterusnya, pindah ke tiga byte pada karakter 2048. "Unicode
Encodings" di perlunicode memiliki gambar tentang cara kerjanya.

Dengan asumsi Anda tahu Anda berurusan dengan string UTF-8, Anda dapat mengetahui berapa lama string pertama
karakter di dalamnya dengan makro "UTF8SKIP":

char *utf = "\305\233\340\240\201";
len I32;

len = UTF8SKIP(utf); /* len adalah 2 di sini */
utf += len;
len = UTF8SKIP(utf); /* len adalah 3 di sini */

Cara lain untuk melewati karakter dalam string UTF-8 adalah dengan menggunakan "utf8_hop", yang membutuhkan
string dan sejumlah karakter untuk dilewati. Anda sendirian tentang pemeriksaan batas,
meskipun, jadi jangan menggunakannya dengan enteng.

Semua byte dalam karakter UTF-8 multi-byte akan memiliki set bit tinggi, sehingga Anda dapat menguji apakah
anda perlu melakukan sesuatu yang istimewa dengan karakter ini seperti ini ("UTF8_IS_INVARIANT()"
adalah makro yang menguji apakah byte dikodekan sebagai satu byte bahkan dalam UTF-8):

U8 *utf;
U8 *utf_end; /* 1 di luar buffer yang ditunjuk oleh utf */
sinar UV; /* Catatan: UV, bukan U8, bukan char */
STRLEN len; /* panjang karakter dalam byte */

jika (!UTF8_IS_INVARIANT(*utf))
/* Harus memperlakukan ini sebagai UTF-8 */
uv = utf8_to_uvchr_buf(utf, utf_end, &len);
lain
/* OK untuk memperlakukan karakter ini sebagai byte */
uv = *utf;

Anda juga dapat melihat dalam contoh itu bahwa kami menggunakan "utf8_to_uvchr_buf" untuk mendapatkan nilai
karakter; fungsi kebalikan "uvchr_to_utf8" tersedia untuk memasukkan UV ke dalam UTF-8:

jika (!UVCHR_IS_INVARIANT(uv))
/* Harus memperlakukan ini sebagai UTF8 */
utf8 = uvchr_to_utf8(utf8, uv);
lain
/* OK untuk memperlakukan karakter ini sebagai byte */
*utf8++ = uv;

Kamu harus mengonversi karakter menjadi UV menggunakan fungsi di atas jika Anda pernah berada dalam situasi
di mana Anda harus mencocokkan karakter UTF-8 dan non-UTF-8. Anda tidak boleh melewatkan UTF-8
karakter dalam hal ini. Jika Anda melakukan ini, Anda akan kehilangan kemampuan untuk mencocokkan hi-bit
karakter non-UTF-8; misalnya, jika string UTF-8 Anda berisi "v196.172", dan Anda melewati
karakter itu, Anda tidak akan pernah bisa menandingi "chr(200)" dalam string non-UTF-8. Jadi jangan lakukan itu!

(Perhatikan bahwa kita tidak perlu menguji karakter invarian dalam contoh di atas
fungsi bekerja pada input UTF-8 yang terbentuk dengan baik. Hanya saja lebih cepat untuk menghindari
fungsi overhead saat tidak diperlukan.)

Seterpercayaapakah Olymp Trade? Kesimpulan tidak Perl menyimpan UTF-8 string?
Saat ini, Perl menangani string UTF-8 dan string non-UTF-8 sedikit berbeda. SEBUAH
flag di SV, "SVf_UTF8", menunjukkan bahwa string dikodekan secara internal sebagai UTF-8.
Tanpa itu, nilai byte adalah nomor codepoint dan sebaliknya. Bendera ini hanya
bermakna jika SV adalah "SvPOK" atau segera setelah stringifikasi melalui "SvPV" atau a
makro serupa. Anda dapat memeriksa dan memanipulasi tanda ini dengan makro berikut:

SvUTF8(sv)
SvUTF8_on(sv)
SvUTF8_mati(sv)

Bendera ini memiliki efek penting pada perlakuan Perl terhadap string: jika data UTF-8 tidak
dibedakan dengan benar, ekspresi reguler, "panjang", "substr" dan penanganan string lainnya
operasi akan memiliki hasil yang tidak diinginkan (salah).

Masalahnya muncul ketika Anda memiliki, misalnya, string yang tidak ditandai sebagai UTF-8, dan
berisi urutan byte yang bisa berupa UTF-8 -- terutama saat menggabungkan non-UTF-8 dan
string UTF-8.

Jangan pernah lupa bahwa bendera "SVf_UTF8" terpisah dari nilai PV; kamu harus yakin
Anda tidak secara tidak sengaja menjatuhkannya saat Anda memanipulasi SV. Lebih tepatnya, kamu
tidak bisa berharap untuk melakukan ini:

SV *sv;
SV *nsv;
STRLEN;
karakter *p;

p = SvPV(sv,len);
frabnicate(p);
nsv = newSVpvn(p, len);

String "char*" tidak menceritakan keseluruhan cerita, dan Anda tidak dapat menyalin atau merekonstruksi
SV hanya dengan menyalin nilai string. Periksa apakah SV lama memiliki set bendera UTF8 (setelah itu
panggilan "SvPV"), dan bertindak sesuai:

p = SvPV(sv,len);
is_utf8 = SvUTF8(sv);
frabnicate(p, is_utf8);
nsv = newSVpvn(p, len);
jika (is_utf8)
SvUTF8_on(nsv);

Di atas, fungsi "frobnicate" Anda telah diubah untuk mengetahui apakah atau
bukan itu berurusan dengan data UTF-8, sehingga dapat menangani string dengan tepat.

Karena hanya meneruskan SV ke fungsi XS dan menyalin data SV tidak cukup untuk
salin flag UTF8, apalagi hanya meneruskan "char *" ke fungsi XS.

Untuk generalisasi penuh, gunakan "DO_UTF8" di makro perlapi untuk melihat apakah string dalam SV
menjadi diperlakukan sebagai UTF-8. Ini memperhitungkan jika panggilan ke fungsi XS sedang
dibuat dari dalam lingkup "gunakan byte". Jika demikian, byte yang mendasari yang terdiri dari
String UTF-8 harus diekspos, bukan karakter yang diwakilinya. Tapi pragma ini
seharusnya hanya benar-benar digunakan untuk debugging dan mungkin pengujian tingkat rendah pada tingkat byte.
Oleh karena itu sebagian besar kode XS tidak perlu memperhatikan hal ini, tetapi berbagai area inti perl
perlu mendukungnya.

Dan ini bukan keseluruhan cerita. Mulai dari Perl v5.12, string yang tidak dikodekan dalam
UTF-8 juga dapat diperlakukan sebagai Unicode dalam berbagai kondisi (lihat "Aturan ASCII versus
Unicode Rules" dalam perlunicode). Ini hanya masalah untuk karakter yang
ordinal antara 128 dan 255, dan perilakunya bervariasi di bawah ASCII versus Unicode
aturan dengan cara yang penting bagi kode Anda (lihat "Bug Unicode"" di perlunicode). Di sana
tidak ada API yang diterbitkan untuk menangani ini, karena dapat berubah, tetapi Anda dapat melihatnya
kode untuk "pp_lc" di hal.c untuk contoh bagaimana hal itu dilakukan saat ini.

Seterpercayaapakah Olymp Trade? Kesimpulan do I mengubah a string untuk UTF-8?
Jika Anda mencampur string UTF-8 dan non-UTF-8, perlu untuk meningkatkan versi non-UTF-8
string ke UTF-8. Jika Anda memiliki SV, cara termudah untuk melakukannya adalah:

sv_utf8_upgrade(sv);

Namun, Anda tidak boleh melakukan ini, misalnya:

jika (!SvUTF8(kiri))
sv_utf8_upgrade(kiri);

Jika Anda melakukan ini di operator biner, Anda benar-benar akan mengubah salah satu string yang datang
ke operator, dan, meskipun tidak terlihat oleh pengguna akhir, itu dapat menyebabkan
masalah dalam kode yang kurang.

Sebagai gantinya, "bytes_to_utf8" akan memberi Anda kode UTF-8 salinan argumen string-nya. Ini
berguna untuk memiliki data yang tersedia untuk perbandingan dan sebagainya, tanpa merusak
SV asli Ada juga "utf8_to_bytes" untuk sebaliknya, tetapi tentu saja, ini akan
gagal jika string berisi karakter apa pun di atas 255 yang tidak dapat direpresentasikan dalam satu karakter
byte.

Seterpercayaapakah Olymp Trade? Kesimpulan do I membandingkan string?
"sv_cmp" di perlapi dan "sv_cmp_flags" di perlapi melakukan perbandingan leksigrafis dari dua SV,
dan menangani UTF-8ness dengan benar. Namun, perhatikan bahwa Unicode menentukan yang jauh lebih menarik
mekanisme untuk pemeriksaan, tersedia melalui modul Unicode::Collate.

Untuk membandingkan dua string untuk kesetaraan/non-kesetaraan, Anda bisa menggunakan "memEQ()" dan
"memNE()" seperti biasa, kecuali string harus berupa UTF-8 atau bukan UTF-8.

Untuk membandingkan dua string yang tidak peka huruf besar/kecil, gunakan "foldEQ_utf8()" (string tidak harus
memiliki UTF-8ness yang sama).

Is sana apa saja lain I perlu untuk tahu?
Tidak juga. Ingat saja hal-hal ini:

· Tidak ada cara untuk mengetahui apakah string "char *" atau "U8 *" adalah UTF-8 atau bukan. Tapi kamu bisa
beri tahu apakah SV akan diperlakukan sebagai UTF-8 dengan memanggil "DO_UTF8" di atasnya, setelah merangkai
dengan "SvPV" atau makro serupa. Dan, Anda dapat mengetahui apakah SV sebenarnya adalah UTF-8 (walaupun
itu tidak diperlakukan seperti itu) dengan melihat bendera "SvUTF8" (sekali lagi setelah
merangkainya). Jangan lupa untuk mengatur bendera jika sesuatu harus UTF-8. Merawat
bendera sebagai bagian dari PV, meskipun bukan -- jika Anda meneruskan PV ke suatu tempat,
mengibarkan bendera juga.

· Jika sebuah string adalah UTF-8, selalu gunakan "utf8_to_uvchr_buf" untuk mendapatkan nilainya, kecuali
"UTF8_IS_INVARIANT(*s)" dalam hal ini Anda dapat menggunakan *s.

· Saat menulis karakter UV ke string UTF-8, selalu gunakan "uvchr_to_utf8", kecuali
"UVCHR_IS_INVARIANT(uv))" dalam hal ini Anda dapat menggunakan "*s = uv".

· Mencampur string UTF-8 dan non-UTF-8 itu rumit. Gunakan "bytes_to_utf8" untuk mendapatkan string baru
yang dikodekan UTF-8, dan kemudian menggabungkannya.

Kustom Operator


Dukungan operator khusus adalah fitur eksperimental yang memungkinkan Anda menentukan operasi Anda sendiri.
Hal ini terutama untuk memungkinkan pembangunan juru bahasa untuk bahasa lain di Perl
inti, tetapi juga memungkinkan pengoptimalan melalui pembuatan "makro-ops" (ops yang
melakukan fungsi beberapa operasi yang biasanya dijalankan bersama-sama, seperti "gvsv,
gvsv, tambahkan".)

Fitur ini diimplementasikan sebagai jenis operasi baru, "OP_CUSTOM". Inti Perl tidak "tahu"
sesuatu yang istimewa tentang jenis op ini, dan karenanya tidak akan terlibat dalam pengoptimalan apa pun.
Ini juga berarti bahwa Anda dapat menentukan operasi khusus Anda menjadi struktur operasi apa pun -- unary,
biner, daftar, dan seterusnya -- Anda suka.

Penting untuk mengetahui apa yang tidak akan dilakukan operator khusus untuk Anda. Mereka tidak akan membiarkan Anda menambahkan yang baru
sintaks ke Perl, secara langsung. Mereka bahkan tidak mengizinkan Anda menambahkan kata kunci baru secara langsung. Faktanya,
mereka tidak akan mengubah cara Perl mengkompilasi program sama sekali. Anda harus melakukan perubahan itu
sendiri, setelah Perl mengkompilasi program. Anda melakukan ini dengan memanipulasi op
pohon menggunakan blok "CHECK" dan modul "B::Generate", atau dengan menambahkan lubang intip khusus
pengoptimal dengan modul "optimalkan".

Ketika Anda melakukan ini, Anda mengganti ops Perl biasa dengan ops kustom dengan membuat ops dengan
ketik "OP_CUSTOM" dan "op_ppaddr" dari fungsi PP Anda sendiri. Ini harus didefinisikan dalam
kode XS, dan akan terlihat seperti operasi PP di "pp_*.c". Anda bertanggung jawab untuk memastikan
bahwa op Anda mengambil jumlah nilai yang sesuai dari tumpukan, dan Anda
bertanggung jawab untuk menambahkan tanda tumpukan jika perlu.

Anda juga harus "mendaftarkan" operasi Anda dengan juru bahasa Perl sehingga dapat menghasilkan
pesan kesalahan dan peringatan yang masuk akal. Karena dimungkinkan untuk memiliki beberapa operasi khusus
dalam satu jenis operasi "logis" "OP_CUSTOM", Perl menggunakan nilai "o->op_ppaddr" untuk
menentukan operasi kustom mana yang dihadapinya. Anda harus membuat struktur "XOP" untuk
setiap ppaddr yang Anda gunakan, atur properti operasi kustom dengan "XopENTRY_set", dan daftar
struktur terhadap ppaddr menggunakan "Perl_custom_op_register". Contoh sepele mungkin
terlihat seperti:

XOP statis my_xop;
OP statis *my_pp(pTHX);

SEPATU:
XopENTRY_set(&my_xop, xop_name, "myxop");
XopENTRY_set(&my_xop, xop_desc, "Operasi khusus yang tidak berguna");
Perl_custom_op_register(aTHX_ my_pp, &my_xop);

Bidang yang tersedia dalam struktur adalah:

xop_nama
Nama pendek untuk operasi Anda. Ini akan disertakan dalam beberapa pesan kesalahan, dan juga akan
dikembalikan sebagai "$op->name" oleh modul B, sehingga akan muncul di output modul
seperti B::Ringkas.

xop_desc
Deskripsi singkat tentang fungsi op.

xop_kelas
Manakah dari berbagai struktur *OP yang digunakan op ini. Ini harus menjadi salah satu dari "OA_*"
konstanta dari op.h, Yaitu

OA_BASEOP
OA_UNOP
OA_BINOP
OA_LOGOP
OA_LISTOP
OA_PMOP
OA_SVOP
OA_PADOP
OA_PVOP_OR_SVOP
Ini harus ditafsirkan sebagai '"PVOP"' saja. "_OR_SVOP" adalah karena satu-satunya
inti "PVOP", "OP_TRANS", terkadang bisa menjadi "SVOP".

OA_LOOP
OA_COP

Konstanta "OA_*" lainnya tidak boleh digunakan.

xop_mengintip
Anggota ini bertipe "Perl_cpeep_t", yang diperluas menjadi "void (*Perl_cpeep_t)(aTHX_ OP
*o, OP *oldop)". Jika diset, fungsi ini akan dipanggil dari "Perl_rpeep" ketika
ops jenis ini ditemui oleh pengoptimal lubang intip. o adalah OP yang membutuhkan
mengoptimalkan; tua adalah OP sebelumnya yang dioptimalkan, yang "op_next"-nya menunjuk ke o.

"B::Generate" secara langsung mendukung pembuatan operasi kustom berdasarkan nama.

PENULIS


Hingga Mei 1997, dokumen ini dikelola oleh Jeff Okamoto[email dilindungi]>. Dia
sekarang dipertahankan sebagai bagian dari Perl sendiri oleh Perl 5 Porter[email dilindungi]>.

Dengan banyak bantuan dan saran dari Dean Roehrich, Malcolm Beattie, Andreas Koenig,
Paul Hudson, Ilya Zakharevich, Paul Marquess, Neil Bowers, Matthew Green, Tim Bunce,
Spider Boardman, Ulrich Pfeifer, Stephen McCamant, dan Gurusamy Sarathy.

Gunakan perlguts online menggunakan layanan onworks.net


Server & Workstation Gratis

Unduh aplikasi Windows & Linux

Perintah Linux

Ad




×
iklan
❤️Berbelanja, pesan, atau beli di sini — tanpa biaya, membantu menjaga layanan tetap gratis.