perlxs - Dalam talian dalam Awan

Ini ialah perintah perlxs yang boleh dijalankan dalam penyedia pengehosan percuma OnWorks menggunakan salah satu daripada berbilang stesen kerja dalam talian percuma kami seperti Ubuntu Online, Fedora Online, emulator dalam talian Windows atau emulator dalam talian MAC OS.

JADUAL:

NAMA


perlxs - Manual rujukan bahasa XS

DESCRIPTION


Pengenalan
XS ialah format fail penerangan antara muka yang digunakan untuk mencipta antara muka sambungan antara
Kod Perl dan C (atau perpustakaan C) yang ingin digunakan dengan Perl. Antara muka XS ialah
digabungkan dengan perpustakaan untuk mencipta perpustakaan baharu yang kemudiannya boleh sama ada secara dinamik
dimuatkan atau dipautkan secara statik ke dalam perl. Penerangan antara muka XS ditulis dalam XS
bahasa dan merupakan komponen teras antara muka sambungan Perl.

Sebelum menulis XS, baca bahagian "CAVEATS" di bawah.

An XSUB membentuk unit asas antara muka XS. Selepas disusun oleh xsubpp
pengkompil, setiap XSUB berjumlah definisi fungsi C yang akan menyediakan gam antara
Konvensyen panggilan Perl dan konvensyen panggilan C.

Kod gam menarik argumen daripada timbunan Perl, menukar nilai Perl ini kepada
format yang dijangkakan oleh fungsi C, panggil fungsi C ini, pindahkan nilai pulangan bagi
C berfungsi kembali ke Perl. Nilai pulangan di sini mungkin nilai pulangan C konvensional atau mana-mana C
argumen fungsi yang mungkin berfungsi sebagai parameter output. Nilai pulangan ini mungkin diluluskan
kembali ke Perl sama ada dengan meletakkannya pada timbunan Perl, atau dengan mengubah suai hujah
dibekalkan dari pihak Perl.

Di atas adalah pandangan yang agak ringkas tentang apa yang sebenarnya berlaku. Memandangkan Perl membenarkan lebih banyak lagi
konvensyen panggilan fleksibel daripada C, XSUB mungkin melakukan lebih banyak lagi dalam amalan, seperti menyemak
parameter input untuk kesahan, membuang pengecualian (atau mengembalikan senarai undef/kosong) jika
nilai pulangan daripada fungsi C menunjukkan kegagalan, memanggil fungsi C yang berbeza berdasarkan
nombor dan jenis hujah, menyediakan antara muka berorientasikan objek, dsb.

Sudah tentu, seseorang boleh menulis kod gam sedemikian terus dalam C. Walau bagaimanapun, ini akan menjadi membosankan
tugas, terutamanya jika seseorang perlu menulis gam untuk berbilang fungsi C, dan/atau satu tidak
cukup biasa dengan disiplin timbunan Perl dan arcana yang lain. XS datang ke
selamatkan di sini: daripada menulis kod gam C ini dalam tangan panjang, seseorang boleh menulis lebih banyak lagi
ringkas ringkas Penerangan daripada apa yang perlu dilakukan oleh gam, dan biarkan pengkompil XS
xsubpp mengendalikan selebihnya.

Bahasa XS membolehkan seseorang menerangkan pemetaan antara cara rutin C digunakan, dan
bagaimana rutin Perl yang sepadan digunakan. Ia juga membenarkan penciptaan rutin Perl
yang diterjemahkan terus kepada kod C dan yang tidak berkaitan dengan C yang sedia ada
fungsi. Dalam kes apabila antara muka C bertepatan dengan antara muka Perl, XSUB
pengisytiharan hampir sama dengan pengisytiharan fungsi C (dalam gaya K&R). Dalam apa-apa
Dalam keadaan tertentu, terdapat alat lain yang dipanggil "h2xs" yang mampu menterjemah keseluruhan C
fail header ke dalam fail XS yang sepadan yang akan memberikan gam kepada fungsi/makro
diterangkan dalam fail pengepala.

Pengkompil XS dipanggil xsubpp. Pengkompil ini mencipta binaan yang diperlukan untuk membiarkan
XSUB memanipulasi nilai Perl, dan mencipta gam yang diperlukan untuk membenarkan Perl memanggil XSUB.
Pengkompil menggunakan peta taip untuk menentukan cara memetakan parameter fungsi C dan nilai output
kepada nilai Perl dan kembali. Peta taip lalai (yang disertakan dengan Perl) mengendalikan banyak perkara biasa
jenis C. Peta taip tambahan juga mungkin diperlukan untuk mengendalikan sebarang struktur khas dan
jenis untuk perpustakaan yang dipautkan. Untuk maklumat lanjut tentang peta taip, lihat peta taip perlx.

Fail dalam format XS bermula dengan bahagian bahasa C yang pergi sehingga "MODULE =" yang pertama
arahan. Arahan XS lain dan takrifan XSUB mungkin mengikut baris ini. Bahasa"
yang digunakan dalam bahagian fail ini biasanya dirujuk sebagai bahasa XS. xsubpp
mengecam dan melangkau POD (lihat perlpod) dalam kedua-dua bahagian bahasa C dan XS, yang
membenarkan fail XS mengandungi dokumentasi terbenam.

Lihat perlxstut untuk tutorial tentang keseluruhan proses penciptaan sambungan.

Nota: Untuk sesetengah sambungan, sistem SWIG Dave Beazley mungkin menyediakan lebih banyak lagi
mekanisme mudah untuk mencipta kod gam sambungan. Lihat <http://www.swig.org/> untuk
maklumat lanjut.

On . Jalan
Banyak contoh yang berikut akan menumpukan pada mencipta antara muka antara Perl
dan fungsi perpustakaan ONC+ RPC mengikat. The rpcb_gettime() fungsi digunakan untuk
menunjukkan banyak ciri bahasa XS. Fungsi ini mempunyai dua parameter; yang pertama
ialah parameter input dan yang kedua ialah parameter output. Fungsi ini juga mengembalikan a
nilai status.

bool_t rpcb_gettime(const char *host, time_t *timep);

Dari C fungsi ini akan dipanggil dengan pernyataan berikut.

#include
status bool_t;
masa_t masa;
status = rpcb_gettime( "localhost", &timep );

Jika XSUB dicipta untuk menawarkan terjemahan langsung antara fungsi ini dan Perl, maka
XSUB ini akan digunakan daripada Perl dengan kod berikut. $status dan $timep
pembolehubah akan mengandungi output fungsi.

gunakan RPC;
$status = rpcb_gettime( "localhost", $timep );

Fail XS berikut menunjukkan subrutin XS, atau XSUB, yang menunjukkan satu kemungkinan
antara muka kepada rpcb_gettime() fungsi. XSUB ini mewakili terjemahan langsung
antara C dan Perl dan seterusnya mengekalkan antara muka walaupun dari Perl. XSUB ini akan menjadi
dipanggil daripada Perl dengan penggunaan yang ditunjukkan di atas. Ambil perhatian bahawa tiga yang pertama #termasuk
penyata, untuk "EXTERN.h", "perl.h", dan "XSUB.h", akan sentiasa ada di
permulaan fail XS. Pendekatan ini dan lain-lain akan diperluaskan kemudian dalam hal ini
dokumen. #define untuk "PERL_NO_GET_CONTEXT" harus ada untuk mengambil penterjemah
konteks dengan lebih cekap, lihat perlguts untuk butiran.

#define PERL_NO_GET_CONTEXT
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include

MODUL = PAKEJ RPC = RPC

bool_t
rpcb_gettime(host,timep)
char *tuan rumah
masa_t &masa
PENGELUARAN:
masa

Sebarang sambungan kepada Perl, termasuk yang mengandungi XSUB, harus mempunyai modul Perl untuk
berfungsi sebagai bootstrap yang menarik sambungan ke Perl. Modul ini akan mengeksport
fungsi dan pembolehubah sambungan kepada program Perl dan akan menyebabkan sambungan itu
XSUB untuk dipautkan ke Perl. Modul berikut akan digunakan untuk kebanyakan contoh
dalam dokumen ini dan harus digunakan daripada Perl dengan arahan "use" seperti yang ditunjukkan sebelum ini.
Modul Perl diterangkan dengan lebih terperinci kemudian dalam dokumen ini.

pakej RPC;

memerlukan Pengeksport;
memerlukan DynaLoader;
@ISA = qw(Pengeksport DynaLoader);
@EXPORT = qw( rpcb_gettime );

RPC bootstrap;
1;

Sepanjang dokumen ini pelbagai antara muka kepada rpcb_gettime() XSUB akan menjadi
diterokai. XSUB akan mengambil parameter mereka dalam susunan yang berbeza atau akan mengambil yang berbeza
bilangan parameter. Dalam setiap kes, XSUB ialah abstraksi antara Perl dan yang sebenar
C rpcb_gettime() fungsi, dan XSUB mesti sentiasa memastikan bahawa yang sebenar rpcb_gettime()
fungsi dipanggil dengan parameter yang betul. Abstraksi ini akan membolehkan
pengaturcara untuk mencipta antara muka yang lebih seperti Perl kepada fungsi C.

. Anatomi of an XSUB
XSUB yang paling mudah terdiri daripada 3 bahagian: penerangan tentang nilai pulangan, nama
Rutin XSUB dan nama hujahnya, dan penerangan jenis atau format
hujah-hujah.

XSUB berikut membenarkan program Perl untuk mengakses fungsi perpustakaan C yang dipanggil dosa(). Yang
XSUB akan meniru fungsi C yang mengambil satu hujah dan mengembalikan satu nilai.

dua kali ganda
dosa (x)
ganda x

Secara pilihan, seseorang boleh menggabungkan perihalan jenis dan senarai nama argumen,
menulis semula ini sebagai

dua kali ganda
dosa(x ganda)

Ini menjadikan XSUB ini kelihatan serupa dengan perisytiharan ANSI C. Titik bertitik pilihan ialah
dibenarkan selepas senarai hujah, seperti dalam

dua kali ganda
dosa(x ganda);

Parameter dengan jenis penuding C boleh mempunyai semantik yang berbeza: C berfungsi dengan yang serupa
pengisytiharan

bool string_looks_as_a_number(char *s);
bool make_char_huruf besar(char *c);

digunakan dengan cara yang sama sekali tidak serasi. Parameter untuk fungsi ini boleh jadi
digambarkan xsubpp seperti ini:

char * s
char &c

Kedua-dua pengisytiharan XS ini sepadan dengan jenis C "char*", tetapi ia berbeza
semantik, lihat "The & Unary Operator".

Adalah mudah untuk berfikir bahawa pengendali arahan "*" harus dipertimbangkan sebagai sebahagian
jenis dan pengendali alamat "&" harus dianggap sebagai sebahagian daripada pembolehubah. Lihat
perlxstypemap untuk mendapatkan maklumat lanjut tentang pengendalian kelayakan dan operator unary dalam jenis C.

Nama fungsi dan jenis pemulangan mesti diletakkan pada baris yang berasingan dan hendaklah disiram
dilaraskan ke kiri.

BETUL BETUL

double sin(x) double
ganda x dosa(x)
ganda x

Perihalan fungsi yang selebihnya mungkin diinden atau dilaraskan ke kiri. Yang berikut
contoh menunjukkan fungsi dengan badannya dilaraskan ke kiri. Kebanyakan contoh dalam dokumen ini akan
inden badan untuk kebolehbacaan yang lebih baik.

BETUL

dua kali ganda
dosa (x)
ganda x

XSUB yang lebih rumit mungkin mengandungi banyak bahagian lain. Setiap bahagian XSUB bermula
dengan kata kunci yang sepadan, seperti INIT: atau CLEANUP:. Walau bagaimanapun, dua baris pertama
XSUB sentiasa mengandungi data yang sama: perihalan jenis pulangan dan nama
fungsi dan parameternya. Apa sahaja yang mengikuti ini dianggap sebagai
bahagian INPUT: melainkan ditandakan dengan kata kunci lain secara eksplisit. (Lihat "INPUT:
Kata kunci".)

Bahagian XSUB diteruskan sehingga kata kunci permulaan bahagian lain ditemui.

. Hujah Menumpukkan
Timbunan argumen Perl digunakan untuk menyimpan nilai yang dihantar sebagai parameter kepada
XSUB dan untuk menyimpan nilai pulangan XSUB. Sebenarnya semua fungsi Perl (termasuk
bukan XSUB) mengekalkan nilai mereka pada tindanan ini pada masa yang sama, setiap satu terhad kepada nilainya sendiri
julat kedudukan pada timbunan. Dalam dokumen ini kedudukan pertama pada timbunan itu yang
tergolong dalam fungsi aktif akan dirujuk sebagai kedudukan 0 untuk fungsi tersebut.

XSUB merujuk kepada hujah tindanan mereka dengan makro ST(x), Di mana x merujuk kepada kedudukan dalam
bahagian tindanan XSUB ini. Kedudukan 0 untuk fungsi itu akan diketahui oleh XSUB sebagai
ST(0). Parameter masuk dan nilai pulangan keluar XSUB sentiasa bermula pada ST(0).
Untuk banyak kes mudah xsubpp pengkompil akan menjana kod yang diperlukan untuk mengendalikan
timbunan hujah dengan membenamkan serpihan kod yang terdapat dalam peta taip. Dalam kes yang lebih kompleks
pengaturcara mesti membekalkan kod.

. RETVAL Pembolehubah
Pembolehubah RETVAL ialah pembolehubah C khas yang diisytiharkan secara automatik untuk anda. C
jenis RETVAL sepadan dengan jenis pemulangan fungsi perpustakaan C. The xsubpp pengkompil
akan mengisytiharkan pembolehubah ini dalam setiap XSUB dengan jenis pulangan bukan "kosong". Secara lalainya
fungsi C yang dihasilkan akan menggunakan RETVAL untuk memegang nilai pulangan fungsi perpustakaan C
sedang dipanggil. Dalam kes yang mudah, nilai RETVAL akan diletakkan dalam ST(0) daripada hujah
tindanan di mana ia boleh diterima oleh Perl sebagai nilai pulangan XSUB.

Jika XSUB mempunyai jenis pulangan "void" maka pengkompil tidak akan mengisytiharkan RETVAL
pembolehubah untuk fungsi itu. Apabila menggunakan PPCODE: bahagian tiada manipulasi RETVAL
pembolehubah diperlukan, bahagian itu boleh menggunakan manipulasi tindanan langsung untuk meletakkan nilai output
pada timbunan.

Jika arahan PPCODE: tidak digunakan, nilai pulangan "kosong" hendaklah digunakan hanya untuk subrutin
yang tidak mengembalikan nilai, walaupun if KOD: arahan digunakan yang menetapkan ST(0) secara eksplisit.

Versi lama dokumen ini disyorkan untuk menggunakan nilai pulangan "kosong" dalam kes sedemikian. Ia
didapati bahawa ini boleh membawa kepada segfault dalam kes apabila XSUB adalah benar-benar "kosong". ini
amalan kini ditamatkan dan mungkin tidak disokong pada beberapa versi masa hadapan. Menggunakan
pulangkan nilai "SV *" dalam kes sedemikian. (Pada masa ini "xsubpp" mengandungi beberapa kod heuristik yang
cuba menyahkekaburan antara fungsi "benar-benar-tidak sah" dan "amalan-lama-diisytiharkan-sebagai-tidak sah".
Oleh itu kod anda bergantung pada heuristik ini melainkan anda menggunakan "SV *" sebagai nilai pulangan.)

Kembali SV, AV and HV melalui RETVAL
Apabila anda menggunakan RETVAL untuk mengembalikan "SV *", terdapat beberapa keajaiban berlaku di belakangnya
adegan yang patut disebut. Apabila anda memanipulasi timbunan hujah menggunakan
ST(x) makro, sebagai contoh, anda biasanya perlu memberi perhatian khusus kepada kiraan rujukan.
(Untuk lebih lanjut tentang kiraan rujukan, lihat perlguts.) Untuk menjadikan hidup anda lebih mudah, peta taip
fail secara automatik menjadikan "RETVAL" mati apabila anda mengembalikan "SV *". Oleh itu,
berikut dua XSUB adalah lebih kurang sama:

membatalkan
alfa()
PPCODE:
ST(0) = newSVpv("Hello World",0);
sv_2mortal(ST(0));
XSRETURN(1);

SV *
beta()
KOD:
RETVAL = newSVpv("Hello World",0);
PENGELUARAN:
RETVAL

Ini agak berguna kerana ia biasanya meningkatkan kebolehbacaan. Walaupun ini berfungsi dengan baik untuk "SV
*", malangnya tidak semudah untuk mempunyai "AV *" atau "HV *" sebagai nilai pulangan. Anda Sekiranya
boleh menulis:

AV *
tatasusunan()
KOD:
RETVAL = newAV();
/* lakukan sesuatu dengan RETVAL */
PENGELUARAN:
RETVAL

Tetapi disebabkan pepijat yang tidak boleh dibetulkan (membetulkannya akan memecahkan banyak modul CPAN sedia ada) dalam
fail peta taip, kiraan rujukan "AV *" tidak dikurangkan dengan betul. Oleh itu,
di atas XSUB akan membocorkan memori apabila ia dipanggil. Masalah yang sama wujud untuk "HV
*", "CV *", dan "SVREF" (yang menunjukkan rujukan skalar, bukan "SV *" umum). Dalam XS
kod pada perl bermula dengan perl 5.16, anda boleh mengatasi peta taip untuk mana-mana daripada ini
jenis dengan versi yang mempunyai pengendalian pengiraan semula yang betul. Dalam bahagian "MAP TAIP" anda, lakukan

AV* T_AVREF_REFCOUNT_FIXED

untuk mendapatkan varian yang dibaiki. Untuk keserasian ke belakang dengan versi lama perl, anda
sebaliknya boleh mengurangkan kiraan rujukan secara manual apabila anda mengembalikan salah satu daripada
jenis yang disebutkan di atas menggunakan "sv_2mortal":

AV *
tatasusunan()
KOD:
RETVAL = newAV();
sv_2mortal((SV*)RETVAL);
/* lakukan sesuatu dengan RETVAL */
PENGELUARAN:
RETVAL

Ingat bahawa anda tidak perlu melakukan ini untuk "SV *". Dokumentasi rujukan untuk semua
peta taip teras boleh didapati dalam perlxstypemap.

. MODULE Kata kunci
Kata kunci MODULE digunakan untuk memulakan kod XS dan untuk menentukan pakej
fungsi yang ditakrifkan. Semua teks sebelum kata kunci MODUL pertama ialah
dianggap kod C dan dihantar ke output dengan POD dilucutkan, tetapi sebaliknya
tidak disentuh. Setiap modul XS akan mempunyai fungsi bootstrap yang digunakan untuk mengaitkan XSUB
ke dalam Perl. Nama pakej fungsi bootstrap ini akan sepadan dengan nilai yang terakhir
Kenyataan MODULE dalam fail sumber XS. Nilai MODUL hendaklah sentiasa kekal
tetap dalam fail XS yang sama, walaupun ini tidak diperlukan.

Contoh berikut akan memulakan kod XS dan akan meletakkan semua fungsi dalam pakej
bernama RPC.

MODUL = RPC

. PAKEJ Kata kunci
Apabila fungsi dalam fail sumber XS mesti dipisahkan ke dalam pakej PACKAGE
kata kunci harus digunakan. Kata kunci ini digunakan dengan kata kunci MODUL dan mesti diikuti
serta-merta selepas ia apabila digunakan.

MODUL = PAKEJ RPC = RPC

[ Kod XS dalam pakej RPC ]

MODUL = PAKEJ RPC = RPCB

[ Kod XS dalam pakej RPCB ]

MODUL = PAKEJ RPC = RPC

[ Kod XS dalam pakej RPC ]

Nama pakej yang sama boleh digunakan lebih daripada sekali, membenarkan kod tidak bersebelahan. ini
berguna jika anda mempunyai prinsip pesanan yang lebih kukuh daripada nama pakej.

Walaupun kata kunci ini adalah pilihan dan dalam beberapa kes memberikan maklumat berlebihan ia
hendaklah sentiasa digunakan. Kata kunci ini akan memastikan bahawa XSUB muncul dalam yang dikehendaki
pakej.

. PERMULAAN Kata kunci
Kata kunci PREFIX menetapkan awalan yang harus dialih keluar daripada fungsi Perl
nama. Jika fungsi C ialah "rpcb_gettime()" dan nilai PREFIX ialah "rpcb_" maka Perl
akan melihat fungsi ini sebagai "gettime()".

Kata kunci ini hendaklah mengikut kata kunci PACKAGE apabila digunakan. Jika PAKEJ tidak digunakan maka
PREFIX hendaklah mengikut kata kunci MODUL.

MODUL = AWAL RPC = rpc_

MODUL = PAKEJ RPC = RPCB PREFIX = rpcb_

. PENGELUARAN: Kata kunci
Kata kunci OUTPUT: menunjukkan bahawa parameter fungsi tertentu harus dikemas kini (baru
nilai yang dilihat kepada Perl) apabila XSUB ditamatkan atau nilai tertentu sepatutnya
kembali ke fungsi Perl memanggil. Untuk fungsi mudah yang tidak mempunyai KOD: atau
PPCODE: bahagian, seperti bahagian dosa() fungsi di atas, pembolehubah RETVAL adalah secara automatik
ditetapkan sebagai nilai keluaran. Untuk fungsi yang lebih kompleks xsubpp pengkompil akan memerlukan
membantu untuk menentukan pembolehubah yang mana pembolehubah keluaran.

Kata kunci ini biasanya akan digunakan untuk melengkapkan kata kunci KOD:. Pembolehubah RETVAL
tidak diiktiraf sebagai pembolehubah keluaran apabila kata kunci KOD: hadir. OUTPUT:
kata kunci digunakan dalam situasi ini untuk memberitahu pengkompil bahawa RETVAL benar-benar adalah output
berubah-ubah.

Kata kunci OUTPUT: juga boleh digunakan untuk menunjukkan bahawa parameter fungsi adalah output
pembolehubah. Ini mungkin perlu apabila parameter telah diubah suai dalam fungsi
dan pengaturcara ingin kemas kini itu dilihat oleh Perl.

bool_t
rpcb_gettime(host,timep)
char *tuan rumah
masa_t &masa
PENGELUARAN:
masa

Kata kunci OUTPUT: juga akan membenarkan parameter output dipetakan ke bahagian yang sepadan
kod dan bukannya peta taip.

bool_t
rpcb_gettime(host,timep)
char *tuan rumah
masa_t &masa
PENGELUARAN:
timep sv_setnv(ST(1), (berganda)masa);

xsubpp mengeluarkan "SvSETMAGIC()" automatik untuk semua parameter dalam bahagian OUTPUT
XSUB, kecuali RETVAL. Ini adalah tingkah laku yang biasanya diingini, kerana ia dijaga dengan betul
menggunakan sihir 'set' pada parameter output (diperlukan untuk parameter elemen cincang atau tatasusunan
yang mesti dibuat jika ia tidak wujud). Jika atas sebab tertentu, tingkah laku ini tidak
dikehendaki, bahagian OUTPUT mungkin mengandungi baris "SETMAGIC: DISABLE" untuk melumpuhkannya untuk
baki parameter dalam bahagian OUTPUT. Begitu juga, "SETMAGIC: ENABLE" boleh
digunakan untuk mendayakannya semula untuk baki bahagian OUTPUT. Lihat perlguts untuk lebih lanjut
butiran tentang sihir 'set'.

. NO_OUTPUT Kata kunci
NO_OUTPUT boleh diletakkan sebagai token pertama XSUB. Kata kunci ini menunjukkan bahawa
manakala subrutin C yang kami sediakan antara muka mempunyai jenis pulangan bukan "kosong", pulangan
nilai subrutin C ini tidak boleh dikembalikan daripada subrutin Perl yang dihasilkan.

Dengan kata kunci ini hadir "Pembolehubah RETVAL" dicipta dan dalam panggilan yang dijana ke
subrutin pembolehubah ini ditugaskan, tetapi nilai pembolehubah ini tidak berjalan
untuk digunakan dalam kod yang dijana secara automatik.

Kata kunci ini masuk akal hanya jika "RETVAL" akan diakses oleh pengguna yang dibekalkan
kod. Ia amat berguna untuk menjadikan antara muka fungsi lebih seperti Perl, terutamanya
apabila nilai pulangan C hanyalah penunjuk keadaan ralat. Sebagai contoh,

NO_OUTPUT int
delete_file(char *nama)
POSTCALL:
jika (RETVAL != 0)
croak("Ralat %d semasa memadam fail '%s'", RETVAL, nama);

Di sini fungsi XS yang dijana tidak mengembalikan apa-apa pada kejayaan, dan akan mati () dengan
mesej ralat bermakna pada ralat.

. KOD: Kata kunci
Kata kunci ini digunakan dalam XSUB yang lebih rumit yang memerlukan pengendalian khas untuk C
fungsi. Pembolehubah RETVAL masih diisytiharkan, tetapi ia tidak akan dikembalikan melainkan ianya
dinyatakan dalam bahagian OUTPUT:.

XSUB berikut adalah untuk fungsi C yang memerlukan pengendalian khas parameternya.
Penggunaan Perl diberikan dahulu.

$status = rpcb_gettime( "localhost", $timep );

XSUB mengikuti.

bool_t
rpcb_gettime(host,timep)
char *tuan rumah
masa_t masa
KOD:
RETVAL = rpcb_gettime( hos, &timep );
PENGELUARAN:
masa
RETVAL

. DI DALAMNYA: Kata kunci
Kata kunci INIT: membenarkan pemulaan untuk dimasukkan ke dalam XSUB sebelum pengkompil
menjana panggilan ke fungsi C. Tidak seperti KOD: kata kunci di atas, kata kunci ini begitu
tidak menjejaskan cara pengkompil mengendalikan RETVAL.

bool_t
rpcb_gettime(host,timep)
char *tuan rumah
masa_t &masa
DI DALAMNYA:
printf("# Hos ialah %s\n", hos );
PENGELUARAN:
masa

Penggunaan lain untuk bahagian INIT: adalah untuk menyemak prasyarat sebelum membuat panggilan ke
fungsi C:

panjang lama
lldiv(a,b)
panjang panjang a
panjang panjang b
DI DALAMNYA:
jika (a == 0 && b == 0)
XSRETURN_UNDEF;
jika (b == 0)
croak("lldiv: tidak boleh bahagi dengan 0");

. NO_INIT Kata kunci
Kata kunci NO_INIT digunakan untuk menunjukkan bahawa parameter fungsi digunakan hanya sebagai
nilai keluaran. The xsubpp pengkompil biasanya akan menjana kod untuk membaca nilai semua
parameter fungsi daripada timbunan hujah dan berikannya kepada pembolehubah C apabila masuk ke
fungsinya. NO_INIT akan memberitahu pengkompil bahawa beberapa parameter akan digunakan untuk output
bukannya untuk input dan ia akan dikendalikan sebelum fungsi ditamatkan.

Contoh berikut menunjukkan variasi bagi rpcb_gettime() fungsi. Fungsi ini
menggunakan pembolehubah masa hanya sebagai pembolehubah keluaran dan tidak mengambil berat tentang permulaannya
kandungan.

bool_t
rpcb_gettime(host,timep)
char *tuan rumah
time_t &timep = NO_INIT
PENGELUARAN:
masa

. PETA JENIS: Kata kunci
Bermula dengan Perl 5.16, anda boleh membenamkan peta taip ke dalam kod XS anda dan bukannya atau masuk
tambahan kepada peta taip dalam fail berasingan. Berbilang peta taip terbenam sedemikian akan menjadi
diproses mengikut susunan penampilan dalam kod XS dan seperti yang diambil oleh fail peta taip tempatan
keutamaan berbanding peta taip lalai, peta taip terbenam mungkin menimpa sebelumnya
takrifan rangkap TYPEMAP, INPUT dan OUTPUT. Sintaks untuk peta taip terbenam ialah

PETA JENIS: <
... kod peta taip anda di sini ...
SINI

di mana kata kunci "MAP TAIP" mesti muncul dalam lajur pertama baris baharu.

Rujuk perlxstypemap untuk butiran tentang menulis peta taip.

Memulakan fungsi Parameter
Parameter fungsi C biasanya dimulakan dengan nilainya daripada timbunan argumen
(yang seterusnya mengandungi parameter yang dihantar ke XSUB daripada Perl). The
peta taip mengandungi segmen kod yang digunakan untuk menterjemah nilai Perl kepada C
parameter. Pengaturcara, bagaimanapun, dibenarkan untuk mengatasi peta taip dan bekalan
kod permulaan ganti (atau tambahan). Kod permulaan bermula dengan yang pertama
"=", ";" atau "+" pada baris dalam bahagian INPUT:. Satu-satunya pengecualian berlaku jika ini ";"
menamatkan baris, maka ini ";" diabaikan secara senyap-senyap.

Kod berikut menunjukkan cara membekalkan kod permulaan untuk parameter fungsi.
Kod permulaan dinilai dalam petikan berganda oleh pengkompil sebelum ia ditambah
kepada output jadi apa sahaja yang harus ditafsirkan secara literal [terutamanya "$", "@", atau "\\"]
mesti dilindungi dengan garis miring ke belakang. Pembolehubah $var, $arg, dan $type boleh digunakan seperti dalam
peta taip.

bool_t
rpcb_gettime(host,timep)
char *host = (char *)SvPV_nolen($arg);
time_t &timep = 0;
PENGELUARAN:
masa

Ini tidak boleh digunakan untuk membekalkan nilai lalai untuk parameter. Seseorang biasanya akan menggunakan
ini apabila parameter fungsi mesti diproses oleh fungsi perpustakaan lain sebelum ia boleh
digunakan. Parameter lalai diliputi dalam bahagian seterusnya.

Jika permulaan bermula dengan "=", maka ia adalah output dalam pengisytiharan untuk input
pembolehubah, menggantikan permulaan yang dibekalkan oleh peta taip. Jika permulaan
bermula dengan ";" atau "+", kemudian ia dilakukan selepas semua pembolehubah input telah
diisytiharkan. Di dalam ";" kes inisialisasi yang biasanya dibekalkan oleh peta taip tidak
dilakukan. Untuk kes "+", pengisytiharan untuk pembolehubah akan termasuk
permulaan daripada peta taip. Pembolehubah global, %v, tersedia untuk yang benar-benar jarang berlaku
kes di mana maklumat daripada satu permulaan diperlukan dalam satu permulaan yang lain.

Berikut ialah contoh yang benar-benar tidak jelas:

bool_t
rpcb_gettime(host,timep)
time_t &timep; /* \$v{timep}=@{[$v{timep}=$arg]} */
char *host + SvOK($v{timep}) ? SvPV_nolen($arg): NULL;
PENGELUARAN:
masa

Konstruk "\$v{timep}=@{[$v{timep}=$arg]}" yang digunakan dalam contoh di atas mempunyai dua rangkap
tujuan: pertama, apabila baris ini diproses oleh xsubpp, coretan Perl "$v{timep}=$arg"
dinilai. Kedua, teks coretan yang dinilai dikeluarkan ke dalam C yang dijana
fail (di dalam ulasan C)! Semasa pemprosesan baris "char *host", $arg akan menilai
kepada ST(0), dan $v{timep} akan menilai ke ST(1).

Lalai Parameter Nilai-nilai
Nilai lalai untuk argumen XSUB boleh ditentukan dengan meletakkan pernyataan tugasan dalam
senarai parameter. Nilai lalai mungkin nombor, rentetan atau rentetan khas
"NO_INIT". Lalai hendaklah sentiasa digunakan pada parameter paling kanan sahaja.

Untuk membenarkan XSUB untuk rpcb_gettime() untuk mempunyai nilai hos lalai parameter kepada
XSUB boleh disusun semula. XSUB kemudiannya akan memanggil yang sebenar rpcb_gettime() berfungsi dengan
parameter dalam susunan yang betul. XSUB ini boleh dipanggil dari Perl dengan salah satu daripada
pernyataan berikut:

$status = rpcb_gettime( $timep, $host );

$status = rpcb_gettime( $timep );

XSUB akan kelihatan seperti kod yang berikut. KOD: blok digunakan untuk memanggil
sebenar rpcb_gettime() berfungsi dengan parameter dalam susunan yang betul untuk fungsi itu.

bool_t
rpcb_gettime(timep,host="localhost")
char *tuan rumah
masa_t masa = TIADA_INIT
KOD:
RETVAL = rpcb_gettime( hos, &timep );
PENGELUARAN:
masa
RETVAL

. PREINIT: Kata kunci
Kata kunci PREINIT: membenarkan pembolehubah tambahan diisytiharkan serta-merta sebelum atau selepas
pengisytiharan parameter daripada bahagian INPUT: dipancarkan.

Jika pembolehubah diisytiharkan di dalam bahagian KOD: ia akan mengikut mana-mana kod peta taip itu
dipancarkan untuk parameter input. Ini boleh menyebabkan pengisytiharan berakhir selepas C
kod, iaitu ralat sintaks C. Ralat serupa mungkin berlaku dengan ";"-type atau
"+"-jenis inisialisasi parameter digunakan (lihat "Memulakan Parameter Fungsi").
Mengisytiharkan pembolehubah ini dalam bahagian INIT: tidak akan membantu.

Dalam kes sedemikian, untuk memaksa pembolehubah tambahan diisytiharkan bersama dengan pengisytiharan
pembolehubah lain, letakkan pengisytiharan ke dalam bahagian PREINIT:. The PREINIT: kata kunci
boleh digunakan satu kali atau lebih dalam XSUB.

Contoh berikut adalah setara, tetapi jika kod menggunakan peta taip yang kompleks maka
contoh pertama adalah lebih selamat.

bool_t
rpcb_gettime(timep)
masa_t masa = TIADA_INIT
PREINIT:
char *host = "localhost";
KOD:
RETVAL = rpcb_gettime( hos, &timep );
PENGELUARAN:
masa
RETVAL

Untuk kes ini, kata kunci INIT: akan menghasilkan kod C yang sama seperti PREINIT:
kata kunci. Satu lagi contoh yang betul tetapi terdedah kepada ralat:

bool_t
rpcb_gettime(timep)
masa_t masa = TIADA_INIT
KOD:
char *host = "localhost";
RETVAL = rpcb_gettime( hos, &timep );
PENGELUARAN:
masa
RETVAL

Cara lain untuk mengisytiharkan "hos" ialah menggunakan blok C dalam bahagian KOD:

bool_t
rpcb_gettime(timep)
masa_t masa = TIADA_INIT
KOD:
{
char *host = "localhost";
RETVAL = rpcb_gettime( hos, &timep );
}
PENGELUARAN:
masa
RETVAL

Keupayaan untuk meletakkan pengisytiharan tambahan sebelum entri peta taip diproses adalah
sangat berguna dalam kes apabila penukaran peta taip memanipulasi beberapa keadaan global:

MyObject
mutasi(o)
PREINIT:
MyState st = global_state;
MASUKKAN:
MyObject o;
BERSIHKAN:
reset_to(global_state, st);

Di sini kami menganggap bahawa penukaran kepada "MyObject" dalam bahagian INPUT: dan dari MyObject apabila
pemprosesan RETVAL akan mengubah suai pembolehubah global "global_state". Selepas penukaran ini
dilakukan, kami memulihkan nilai lama "global_state" (untuk mengelakkan kebocoran memori, untuk
contoh).

Terdapat satu lagi cara untuk menukar kejelasan untuk kekompakan: Bahagian INPUT membenarkan pengisytiharan
Pembolehubah C yang tidak muncul dalam senarai parameter subrutin. Justeru perkara di atas
kod untuk mutasi() boleh ditulis semula sebagai

MyObject
mutasi(o)
MyState st = global_state;
MyObject o;
BERSIHKAN:
reset_to(global_state, st);

dan kod untuk rpcb_gettime() boleh ditulis semula sebagai

bool_t
rpcb_gettime(timep)
masa_t masa = TIADA_INIT
char *host = "localhost";
C_ARGS:
hos, &masa
PENGELUARAN:
masa
RETVAL

. SKOP: Kata kunci
SKOP: kata kunci membenarkan skop didayakan untuk XSUB tertentu. Jika didayakan,
XSUB akan memanggil ENTER dan LEAVE secara automatik.

Untuk menyokong pemetaan jenis yang mungkin kompleks, jika entri peta taip yang digunakan oleh XSUB mengandungi
komen seperti "/*skop*/" kemudian skop akan didayakan secara automatik untuk XSUB itu.

Untuk mendayakan skop:

SKOP: BOLEHKAN

Untuk melumpuhkan skop:

SKOP: LUMPUHKAN

. MASUKKAN: Kata kunci
Parameter XSUB biasanya dinilai serta-merta selepas memasuki XSUB. The
INPUT: kata kunci boleh digunakan untuk memaksa parameter tersebut dinilai sedikit kemudian. The
INPUT: kata kunci boleh digunakan beberapa kali dalam XSUB dan boleh digunakan untuk menyenaraikan satu atau
lebih banyak pembolehubah input. Kata kunci ini digunakan dengan kata kunci PREINIT:.

Contoh berikut menunjukkan cara parameter input "timep" boleh dinilai lewat, selepas a
PREINIT.

bool_t
rpcb_gettime(host,timep)
char *tuan rumah
PREINIT:
masa_t tt;
MASUKKAN:
masa_t masa
KOD:
RETVAL = rpcb_gettime( hos, &tt );
masa = tt;
PENGELUARAN:
masa
RETVAL

Contoh seterusnya menunjukkan setiap parameter input dinilai lewat.

bool_t
rpcb_gettime(host,timep)
PREINIT:
masa_t tt;
MASUKKAN:
char *tuan rumah
PREINIT:
char *h;
MASUKKAN:
masa_t masa
KOD:
h = tuan rumah;
RETVAL = rpcb_gettime( h, &tt );
masa = tt;
PENGELUARAN:
masa
RETVAL

Memandangkan bahagian INPUT membenarkan pengisytiharan pembolehubah C yang tidak muncul dalam parameter
senarai subrutin, ini boleh dipendekkan kepada:

bool_t
rpcb_gettime(host,timep)
masa_t tt;
char *tuan rumah;
char *h = hos;
masa_t masa;
KOD:
RETVAL = rpcb_gettime( h, &tt );
masa = tt;
PENGELUARAN:
masa
RETVAL

(Kami menggunakan pengetahuan kami bahawa penukaran input untuk "char *" adalah "mudah", oleh itu "hos"
dimulakan pada baris pengisytiharan, dan tugasan kami "h = hos" tidak dilakukan juga
awal. Jika tidak, seseorang perlu mempunyai tugasan "h = hos" dalam KOD: atau INIT:
bahagian.)

. IN/OUTLIST/IN_OUTLIST/OUT/IN_OUT kata kunci
Dalam senarai parameter untuk XSUB, seseorang boleh mendahului nama parameter dengan
Kata kunci "IN"/"OUTLIST"/"IN_OUTLIST"/"OUT"/"IN_OUT". Kata kunci "IN" ialah kata kunci lalai, iaitu
kata kunci lain menunjukkan bagaimana antara muka Perl harus berbeza daripada antara muka C.

Parameter yang didahului oleh kata kunci "OUTLIST"/"IN_OUTLIST"/"OUT"/"IN_OUT" dianggap sebagai
digunakan oleh subrutin C melalui petunjuk. Kata kunci "OUTLIST"/"OUT" menunjukkan bahawa C
subrutin tidak memeriksa memori yang ditunjukkan oleh parameter ini, tetapi akan menulis melalui
penunjuk ini untuk memberikan nilai pulangan tambahan.

Parameter yang didahului oleh kata kunci "OUTLIST" tidak muncul dalam tandatangan penggunaan
menjana fungsi Perl.

Parameter didahului oleh "IN_OUTLIST"/"IN_OUT"/"OUT" do muncul sebagai parameter kepada Perl
fungsi. Dengan pengecualian "OUT" -parameters, parameter ini ditukar kepada
jenis C yang sepadan, maka penunjuk kepada data ini diberikan sebagai hujah kepada C
fungsi. Dijangkakan bahawa fungsi C akan menulis melalui penunjuk ini.

Senarai pulangan bagi fungsi Perl yang dihasilkan terdiri daripada nilai pulangan C daripada
fungsi (melainkan XSUB adalah jenis pengembalian "kosong" atau "Kata kunci NO_OUTPUT" telah digunakan)
diikuti dengan semua parameter "OUTLIST" dan "IN_OUTLIST" (dalam susunan penampilan).
Pada pemulangan dari XSUB parameter Perl "IN_OUT"/"OUT" akan diubah suai untuk mempunyai
nilai yang ditulis oleh fungsi C.

Sebagai contoh, XSUB

membatalkan
day_month(OUTLIST day, IN unix_time, OUTLIST month)
hari int
int unix_time
bulan int

harus digunakan dari Perl sebagai

saya ($hari, $bulan) = hari_bulan(masa);

Tandatangan C bagi fungsi yang sepadan hendaklah

batal hari_bulan(int *hari, int unix_time, int *bulan);

Kata kunci "IN"/"OUTLIST"/"IN_OUTLIST"/"IN_OUT"/"OUT" boleh dicampur dengan gaya ANSI
pengisytiharan, seperti dalam

membatalkan
day_month(OUTLIST int day, int unix_time, OUTLIST int month)

(di sini kata kunci "IN" pilihan ditinggalkan).

Parameter "IN_OUT" adalah sama dengan parameter yang diperkenalkan dengan "The & Unary
Operator" dan masukkan ke dalam bahagian "OUTPUT:" (lihat "The OUTPUT: Keyword").
Parameter "IN_OUTLIST" sangat serupa, satu-satunya perbezaan ialah nilai C
fungsi menulis melalui penuding tidak akan mengubah suai parameter Perl, tetapi dimasukkan ke dalam
senarai keluaran.

Parameter "OUTLIST"/"OUT" berbeza daripada parameter "IN_OUTLIST"/"IN_OUT" hanya dengan
nilai awal parameter Perl tidak dibaca (dan tidak diberikan kepada fungsi C
- yang mendapat sedikit sampah sebaliknya). Sebagai contoh, fungsi C yang sama seperti di atas boleh
antara muka dengan sebagai

batal day_month(OUT int day, int unix_time, OUT int month);

or

membatalkan
hari_bulan(hari, masa_unix, bulan)
int &hari = NO_INIT
int unix_time
int &bulan = NO_INIT
PENGELUARAN:
hari
bulan

Walau bagaimanapun, fungsi Perl yang dihasilkan dipanggil dalam gaya yang sangat C-ish:

saya ($hari, $bulan);
hari_bulan($hari, masa, $bulan);

. "panjang(NAME)" Kata kunci
Jika salah satu argumen input kepada fungsi C ialah panjang argumen rentetan "NAME",
seseorang boleh menggantikan nama hujah panjang dengan "panjang(NAMA)" dalam XSUB
pengisytiharan. Argumen ini mesti ditinggalkan apabila fungsi Perl yang dihasilkan dipanggil.
Cth,

membatalkan
dump_chars(char *s, short l)
{
pendek n = 0;
manakala (n < l) {
printf("s[%d] = \"\\%#03o\"\n", n, (int)s[n]);
n++;
}
}

MODUL = x PAKEJ = x

void dump_chars(char *s, short length(s))

harus dipanggil sebagai "dump_chars($string)".

Arahan ini disokong dengan pengisytiharan fungsi jenis ANSI sahaja.

Pembolehubah-panjang Parameter senarai
XSUB boleh mempunyai senarai parameter panjang berubah-ubah dengan menyatakan elipsis "(...)" dalam
senarai parameter. Penggunaan elipsis ini adalah serupa dengan yang terdapat dalam ANSI C. The
pengaturcara dapat menentukan bilangan hujah yang dihantar kepada XSUB dengan memeriksa
pembolehubah "item" yang xsubpp bekalan penyusun untuk semua XSUB. Dengan menggunakan ini
mekanisme seseorang boleh mencipta XSUB yang menerima senarai parameter yang tidak diketahui panjangnya.

. tuan rumah parameter untuk rpcb_gettime() XSUB boleh menjadi pilihan supaya elipsis boleh digunakan
untuk menunjukkan bahawa XSUB akan mengambil bilangan parameter yang berubah-ubah. Perl sepatutnya boleh
untuk memanggil XSUB ini dengan salah satu daripada pernyataan berikut.

$status = rpcb_gettime( $timep, $host );

$status = rpcb_gettime( $timep );

Kod XS, dengan elipsis, berikut.

bool_t
rpcb_gettime(timep, ...)
masa_t masa = TIADA_INIT
PREINIT:
char *host = "localhost";
KOD:
jika (item > 1 )
hos = (char *)SvPV_nolen(ST(1));
RETVAL = rpcb_gettime( hos, &timep );
PENGELUARAN:
masa
RETVAL

. C_ARGS: Kata kunci
Kata kunci C_ARGS: membenarkan penciptaan XSUBS yang mempunyai urutan panggilan yang berbeza daripada
Perl daripada dari C, tanpa perlu menulis bahagian KOD: atau PPCODE:. Kandungan dalam
C_ARGS: perenggan diletakkan sebagai hujah kepada fungsi C yang dipanggil tanpa sebarang perubahan.

Sebagai contoh, katakan bahawa fungsi C diisytiharkan sebagai

nth_derivative simbolik(int n, fungsi simbolik, bendera int);

dan bahawa bendera lalai disimpan dalam pembolehubah C global "default_flags". Sepatutnya begitu
anda ingin mencipta antara muka yang dipanggil sebagai

$second_deriv = $fungsi->nth_derivative(2);

Untuk melakukan ini, isytiharkan XSUB sebagai

simbolik
nth_derivative(fungsi, n)
fungsi simbolik
int n
C_ARGS:
n, fungsi, default_flags

. PPCODE: Kata kunci
Kata kunci PPCODE: ialah bentuk ganti kata kunci KOD: dan digunakan untuk memberitahu
xsubpp pengkompil bahawa pengaturcara membekalkan kod untuk mengawal timbunan hujah
untuk nilai pulangan XSUB. Kadangkala seseorang akan mahu XSUB mengembalikan senarai
nilai dan bukannya satu nilai. Dalam kes ini seseorang mesti menggunakan PPCODE: dan kemudian
menolak senarai nilai pada tindanan secara eksplisit. Kata kunci PPCODE: dan KOD: sepatutnya
tidak boleh digunakan bersama dalam XSUB yang sama.

Perbezaan sebenar antara bahagian PPCODE: dan CODE: adalah dalam permulaan "SP"
makro (yang bermaksud semasa Penunjuk tindanan Perl), dan dalam pengendalian data pada
timbunan apabila kembali dari XSUB. Dalam KOD: bahagian SP mengekalkan nilai yang sebelumnya
pada kemasukan ke XSUB: SP berada pada penunjuk fungsi (yang mengikut parameter terakhir).
Dalam PPCODE: bahagian SP dialihkan ke belakang ke permulaan senarai parameter, yang
membenarkan makro "PUSH*()" untuk meletakkan nilai output di tempat Perl menjangkakan mereka berada apabila
XSUB kembali ke Perl.

Treler yang dijana untuk bahagian KOD: memastikan bilangan nilai pulangan Perl
akan lihat adalah sama ada 0 atau 1 (bergantung pada "kekosongan" nilai pulangan C
fungsi, dan heuristik yang disebut dalam "Pembolehubah RETVAL"). Treler yang dihasilkan untuk a
PPCODE: bahagian adalah berdasarkan bilangan nilai pulangan dan pada bilangan kali "SP"
telah dikemas kini oleh makro "[X]PUSH*()".

Ambil perhatian bahawa makro ST(i), "XST_m*()" dan "XSRETURN*()" berfungsi dengan baik dalam CODE: bahagian
dan PPCODE: bahagian.

XSUB berikut akan memanggil C rpcb_gettime() berfungsi dan akan mengembalikan dua outputnya
nilai, masa dan status, kepada Perl sebagai satu senarai.

membatalkan
rpcb_gettime(host)
char *tuan rumah
PREINIT:
masa_t masa;
status bool_t;
PPCODE:
status = rpcb_gettime( hos, &timep );
EXTEND(SP, 2);
PUSHs(sv_2mortal(newSViv(status)));
PUSHs(sv_2mortal(newSViv(timep)));

Perhatikan bahawa pengaturcara mesti membekalkan kod C yang diperlukan untuk mempunyai yang sebenar
rpcb_gettime() fungsi dipanggil dan supaya nilai pulangan diletakkan dengan betul pada
timbunan hujah.

Jenis pulangan "kosong" untuk fungsi ini memberitahu xsubpp pengkompil bahawa RETVAL
pembolehubah tidak diperlukan atau digunakan dan ia tidak sepatutnya dicipta. Dalam kebanyakan senario
jenis pengembalian void harus digunakan dengan arahan PPCODE:.

. EXTEND() makro digunakan untuk memberi ruang pada timbunan argumen untuk 2 nilai pulangan. The
PPCODE: arahan menyebabkan xsubpp pengkompil untuk mencipta penuding tindanan tersedia sebagai "SP",
dan penunjuk inilah yang digunakan dalam EXTEND() makro. Nilai itu kemudian
ditolak ke timbunan dengan PUSHs() makro.

Sekarang rpcb_gettime() fungsi boleh digunakan daripada Perl dengan pernyataan berikut.

($status, $timep) = rpcb_gettime("localhost");

Apabila mengendalikan parameter output dengan bahagian PPCODE, pastikan anda mengendalikan sihir 'set'
dengan betul. Lihat perlguts untuk butiran tentang sihir 'set'.

Kembali Undef dan Kosong senarai
Kadangkala pengaturcara akan mahu kembali hanya "undef" atau senarai kosong jika a
fungsi gagal dan bukannya nilai status yang berasingan. The rpcb_gettime() tawaran fungsi
hanya keadaan ini. Sekiranya fungsi itu berjaya, kami ingin ia mengembalikan masa
dan jika ia gagal kami ingin undef dikembalikan. Dalam kod Perl berikut
nilai $timep sama ada tidak ditentukan atau ia akan menjadi masa yang sah.

$timep = rpcb_gettime( "localhost" );

XSUB berikut menggunakan jenis pulangan "SV *" sebagai mnemonik sahaja dan menggunakan blok KOD:
untuk menunjukkan kepada pengkompil bahawa pengaturcara telah membekalkan semua kod yang diperlukan. The
sv_newmortal() panggilan akan memulakan nilai pulangan kepada undef, menjadikannya lalai
nilai pulangan.

SV *
rpcb_gettime(host)
char * hos
PREINIT:
masa_t masa;
bool_t x;
KOD:
ST(0) = sv_newmortal();
if( rpcb_gettime( hos, &timep ) )
sv_setnv( ST(0), (berganda)masa);

Contoh seterusnya menunjukkan bagaimana seseorang akan meletakkan undef eksplisit dalam nilai pulangan,
sekiranya keperluan itu timbul.

SV *
rpcb_gettime(host)
char * hos
PREINIT:
masa_t masa;
bool_t x;
KOD:
if( rpcb_gettime( hos, &timep ) ){
ST(0) = sv_newmortal();
sv_setnv( ST(0), (berganda)masa);
}
lain {
ST(0) = &PL_sv_undef;
}

Untuk mengembalikan senarai kosong seseorang mesti menggunakan blok PPCODE: dan kemudian tidak menekan nilai pulangan
timbunan.

membatalkan
rpcb_gettime(host)
char *tuan rumah
PREINIT:
masa_t masa;
PPCODE:
if( rpcb_gettime( hos, &timep ) )
PUSHs(sv_2mortal(newSViv(timep)));
lain {
/* Tiada apa-apa yang ditolak pada tindanan, jadi kosong
* senarai dikembalikan secara tersirat. */
}

Sesetengah orang mungkin cenderung untuk memasukkan "pulangan" yang jelas dalam XSUB di atas, bukannya
membiarkan kawalan jatuh ke akhir. Dalam situasi tersebut "XSRETURN_EMPTY" sepatutnya
digunakan, sebaliknya. Ini akan memastikan tindanan XSUB dilaraskan dengan betul. Rujuk
perlapi untuk makro "XSRETURN" yang lain.

Memandangkan makro "XSRETURN_*" boleh digunakan dengan blok KOD juga, seseorang boleh menulis semula ini
contoh sebagai:

int
rpcb_gettime(host)
char *tuan rumah
PREINIT:
masa_t masa;
KOD:
RETVAL = rpcb_gettime( hos, &timep );
jika (RETVAL == 0)
XSRETURN_UNDEF;
PENGELUARAN:
RETVAL

Malah, seseorang boleh meletakkan cek ini ke dalam bahagian POSTCALL: juga. Bersama-sama dengan PREINIT:
penyederhanaan, ini membawa kepada:

int
rpcb_gettime(host)
char *tuan rumah
masa_t masa;
POSTCALL:
jika (RETVAL == 0)
XSRETURN_UNDEF;

. MEMERLUKAN: Kata kunci
Kata kunci REQUIRE: digunakan untuk menunjukkan versi minimum xsubpp pengkompil diperlukan
untuk menyusun modul XS. Modul XS yang mengandungi pernyataan berikut akan
menyusun dengan sahaja xsubpp versi 1.922 atau lebih tinggi:

KEPERLUAN: 1.922

. BERSIHKAN: Kata kunci
Kata kunci ini boleh digunakan apabila XSUB memerlukan prosedur pembersihan khas sebelum itu
tamat. Apabila kata kunci CLEANUP: digunakan ia mesti mengikut mana-mana KOD:, atau OUTPUT:
blok yang terdapat dalam XSUB. Kod yang ditentukan untuk blok pembersihan ialah
ditambah sebagai pernyataan terakhir dalam XSUB.

. POSTCALL: Kata kunci
Kata kunci ini boleh digunakan apabila XSUB memerlukan prosedur khas yang dilaksanakan selepas C
panggilan subrutin dilakukan. Apabila kata kunci POSTCALL: digunakan ia mesti mendahului OUTPUT:
dan CLEANUP: blok yang terdapat dalam XSUB.

Lihat contoh dalam "Kata Kunci NO_OUTPUT" dan "Mengembalikan Senarai Tidak Tentu Dan Kosong".

POSTCALL: blok tidak masuk akal apabila panggilan subrutin C dibekalkan oleh
pengguna dengan menyediakan sama ada bahagian KOD: atau PPCODE:.

. BOOT: Kata kunci
Kata kunci BOOT: digunakan untuk menambah kod pada fungsi bootstrap sambungan. The
fungsi bootstrap dihasilkan oleh xsubpp pengkompil dan biasanya memegang kenyataan
diperlukan untuk mendaftarkan mana-mana XSUB dengan Perl. Dengan kata kunci BOOT: pengaturcara boleh memberitahu
pengkompil untuk menambah pernyataan tambahan pada fungsi bootstrap.

Kata kunci ini boleh digunakan pada bila-bila masa selepas kata kunci MODUL pertama dan sepatutnya muncul pada a
baris dengan sendirinya. Baris kosong pertama selepas kata kunci akan menamatkan blok kod.

BOOT:
# Mesej berikut akan dicetak apabila
# fungsi bootstrap dilaksanakan.
printf("Hello daripada bootstrap!\n");

. VERSIONCHECK: Kata kunci
VERSIONCHECK: kata kunci sepadan dengan xsubpp"-versioncheck" dan "-noversioncheck"
pilihan. Kata kunci ini mengatasi pilihan baris arahan. Semakan versi didayakan oleh
lalai. Apabila semakan versi didayakan, modul XS akan cuba mengesahkan bahawa ia
versi sepadan dengan versi modul PM.

Untuk mendayakan semakan versi:

VERSIONCHECK: DAYAKAN

Untuk melumpuhkan semakan versi:

VERSIONCHECK: LUMPUHKAN

Ambil perhatian bahawa jika versi modul PM ialah NV (nombor titik terapung), ia akan menjadi
bertali dengan kemungkinan kehilangan ketepatan (pada masa ini memotong kepada sembilan tempat perpuluhan)
supaya ia mungkin tidak sepadan dengan versi modul XS lagi. Memetik $VERSION
pengisytiharan untuk menjadikannya rentetan adalah disyorkan jika nombor versi panjang digunakan.

. PROTOTAIP: Kata kunci
PROTOTAIP: kata kunci sepadan dengan xsubppPilihan "-prototypes" dan "-noprototypes".
Kata kunci ini mengatasi pilihan baris arahan. Prototaip didayakan secara lalai. Bila
prototaip didayakan XSUB akan diberikan prototaip Perl. Kata kunci ini boleh digunakan
beberapa kali dalam modul XS untuk mendayakan dan melumpuhkan prototaip untuk bahagian yang berlainan
modul.

Untuk mendayakan prototaip:

PROTOTAIP: DAYAKAN

Untuk melumpuhkan prototaip:

PROTOTAIP: LUmpuhkan

. PROTOTAIP: Kata kunci
Kata kunci ini serupa dengan PROTOTYPES: kata kunci di atas tetapi boleh digunakan untuk memaksa xsubpp
untuk menggunakan prototaip khusus untuk XSUB. Kata kunci ini mengatasi semua prototaip lain
pilihan dan kata kunci tetapi hanya mempengaruhi XSUB semasa. Rujuk "Prototaip" dalam perlsub
untuk maklumat tentang prototaip Perl.

bool_t
rpcb_gettime(timep, ...)
masa_t masa = TIADA_INIT
PROTOTAIP: $;$
PREINIT:
char *host = "localhost";
KOD:
jika (item > 1 )
hos = (char *)SvPV_nolen(ST(1));
RETVAL = rpcb_gettime( hos, &timep );
PENGELUARAN:
masa
RETVAL

Jika prototaip didayakan, anda boleh melumpuhkannya secara setempat untuk XSUB tertentu seperti dalam
contoh berikut:

membatalkan
rpcb_gettime_noproto()
PROTOTAIP: LUmpuhkan
...

. ALIAS: Kata kunci
Kata kunci ALIAS: membenarkan XSUB mempunyai dua atau lebih nama Perl yang unik dan mengetahui yang mana
daripada nama tersebut telah digunakan apabila ia dipanggil. Nama Perl mungkin layak sepenuhnya dengan
nama pakej. Setiap alias diberi indeks. Pengkompil akan menyediakan pembolehubah yang dipanggil
"ix" yang mengandungi indeks alias yang digunakan. Apabila XSUB dipanggil dengan
nama yang diisytiharkan "ix" akan menjadi 0.

Contoh berikut akan mencipta alias "FOO::gettime()" dan "BAR::getit()" untuk ini
fungsi.

bool_t
rpcb_gettime(host,timep)
char *tuan rumah
masa_t &masa
ALIAS:
FOO::gettime = 1
BAR::getit = 2
DI DALAMNYA:
printf("# ix = %d\n", ix );
PENGELUARAN:
masa

. LEBIHAN BEBAN: Kata kunci
Daripada menulis antara muka yang terlebih beban menggunakan Perl tulen, anda juga boleh menggunakan OVERLOAD
kata kunci untuk menentukan nama Perl tambahan untuk fungsi anda (seperti ALIAS: kata kunci
atas). Walau bagaimanapun, fungsi terlebih beban mesti ditakrifkan dengan tiga parameter (kecuali
bagi nomethod() fungsi yang memerlukan empat parameter). Jika mana-mana fungsi mempunyai
LEBIHAN: kata kunci, beberapa baris tambahan akan ditakrifkan dalam fail c yang dijana oleh
xsubpp untuk mendaftar dengan sihir yang berlebihan.

Oleh kerana objek yang diberkati sebenarnya disimpan sebagai RV, adalah berguna untuk menggunakan peta taip
ciri untuk pramemproses parameter dan mengekstrak SV sebenar yang disimpan dalam RV yang diberkati.
Lihat sampel untuk T_PTROBJ_SPECIAL di bawah.

Untuk menggunakan kata kunci OVERLOAD:, buat fungsi XS yang mengambil tiga parameter input (
atau gunakan takrifan gaya c '...') seperti ini:

SV *
cmp (lobj, robj, swap)
My_Module_obj lobj
My_Module_obj robj
pertukaran IV
LEBIHAN BEBAN: cmp
{ /* fungsi ditakrifkan di sini */}

Dalam kes ini, fungsi akan membebankan kedua-dua operator perbandingan tiga hala. Untuk
semua operasi lebihan menggunakan aksara bukan alfa, anda mesti menaip parameter tanpa
memetik, memisahkan berbilang lebihan dengan ruang putih. Perhatikan bahawa "" (stringify
beban berlebihan) hendaklah dimasukkan sebagai \"\" (iaitu melarikan diri).

. KEMBALI: Kata kunci
Selain kata kunci OVERLOAD, jika anda perlu mengawal cara Perl autogenerate hilang
operator yang terlebih beban, anda boleh menetapkan kata kunci FALLBACK dalam bahagian pengepala modul, seperti
ini:

MODUL = PAKEJ RPC = RPC

KEMBALI: BENAR
...

di mana FALLBACK boleh mengambil mana-mana daripada tiga nilai TRUE, FALSE atau UNDEF. Jika anda tidak menetapkan
sebarang nilai FALLBACK apabila menggunakan OVERLOAD, ia lalai kepada UNDEF. FALLBACK tidak digunakan kecuali
apabila satu atau lebih fungsi menggunakan OVERLOAD telah ditakrifkan. Sila lihat "sandaran" dalam
terlebih beban untuk maklumat lanjut.

. INTERFACE: Kata kunci
Kata kunci ini mengisytiharkan XSUB semasa sebagai penyimpan tandatangan panggilan yang diberikan. Jika
beberapa teks mengikuti kata kunci ini, ia dianggap sebagai senarai fungsi yang mempunyai ini
tandatangan, dan harus dilampirkan pada XSUB semasa.

Sebagai contoh, jika anda mempunyai 4 fungsi C darab(), bahagikan(), Tambah(), tolak() semua mempunyai
tandatangan:

simbolik f(simbolik, simbolik);

anda boleh membuat mereka semua menggunakan XSUB yang sama menggunakan ini:

simbolik
antara muka_s_ss(arg1, arg2)
simbolik arg1
simbolik arg2
INTERFACE:
darab bahagi
tambah tolak

(Ini ialah kod XSUB lengkap untuk 4 fungsi Perl!) Empat bahagian fungsi Perl yang dijana
nama dengan fungsi C yang sepadan.

Kelebihan pendekatan ini berbanding dengan kata kunci ALIAS: ialah tidak perlu
kodkan pernyataan suis, setiap fungsi Perl (yang berkongsi XSUB yang sama) mengetahui C yang mana
fungsi ia harus memanggil. Selain itu, seseorang boleh melampirkan fungsi tambahan baki() at
runtime dengan menggunakan

CV *mycv = newXSproto("Simbolik::baki",
XS_Symbolic_interface_s_ss, __FILE__, "$$");
XSINTERFACE_FUNC_SET(mycv, baki);

katakan, dari XSUB yang lain. (Contoh ini mengandaikan bahawa tiada INTERFACE_MACRO:
bahagian, jika tidak, seseorang perlu menggunakan sesuatu yang lain dan bukannya "XSINTERFACE_FUNC_SET", lihat
bahagian seterusnya.)

. INTERFACE_MACRO: Kata kunci
Kata kunci ini membolehkan seseorang mentakrif ANTARA MUKA menggunakan cara yang berbeza untuk mengekstrak fungsi
penunjuk dari XSUB. Teks yang mengikuti kata kunci ini harus memberikan nama makro
yang akan mengekstrak/menetapkan penunjuk fungsi. Makro pengekstrak diberikan jenis pulangan,
"CV*", dan "XSANY.any_dptr" untuk "CV*" ini. Makro penetap diberikan cv, dan
penunjuk fungsi.

Nilai lalai ialah "XSINTERFACE_FUNC" dan "XSINTERFACE_FUNC_SET". Kata kunci ANTARAMUKA
dengan senarai kosong fungsi boleh ditinggalkan jika kata kunci INTERFACE_MACRO digunakan.

Katakan bahawa dalam contoh sebelumnya berfungsi penunjuk untuk darab(), bahagikan(), Tambah(),
tolak() disimpan dalam tatasusunan C global "fp[]" dengan offset ialah "multiply_off",
"divide_off", "add_off", "tolak_off". Kemudian seseorang boleh menggunakan

#define XSINTERFACE_FUNC_BYOFFSET(ret,cv,f)
((XSINTERFACE_CVT_ANON(ret))fp[CvXSUBANY(cv).any_i32])
#define XSINTERFACE_FUNC_BYOFFSET_set(cv,f)
CvXSUBANY(cv).any_i32 = CAT2( f, _off )

dalam bahagian C,

simbolik
antara muka_s_ss(arg1, arg2)
simbolik arg1
simbolik arg2
INTERFACE_MACRO:
XSINTERFACE_FUNC_BYOFFSET
XSINTERFACE_FUNC_BYOFFSET_set
INTERFACE:
darab bahagi
tambah tolak

dalam bahagian XSUB.

. TERMASUK: Kata kunci
Kata kunci ini boleh digunakan untuk menarik fail lain ke dalam modul XS. Fail lain mungkin ada
Kod XS. INCLUDE: juga boleh digunakan untuk menjalankan arahan untuk menjana kod XS untuk ditarik
ke dalam modul.

Fail Rpcb1.xsh mengandungi fungsi "rpcb_gettime()" kami:

bool_t
rpcb_gettime(host,timep)
char *tuan rumah
masa_t &masa
PENGELUARAN:
masa

Modul XS boleh menggunakan INCLUDE: untuk menarik fail itu ke dalamnya.

TERMASUK: Rpcb1.xsh

Jika parameter kepada kata kunci INCLUDE: diikuti oleh paip ("|") maka pengkompil
akan mentafsir parameter sebagai arahan. Ciri ini ditamatkan sedikit demi sedikit
arahan "INCLUDE_COMMAND:", seperti yang didokumenkan di bawah.

TERMASUK: kucing Rpcb1.xsh |

Jangan gunakan ini untuk menjalankan perl: "INCLUDE: perl |" akan menjalankan perl yang kebetulan adalah
pertama dalam laluan anda dan tidak semestinya perl yang sama yang digunakan untuk menjalankan "xsubpp". Lihat
"INCLUDE_COMMAND: Kata Kunci".

. INCLUDE_COMMAND: Kata kunci
Menjalankan arahan yang dibekalkan dan memasukkan outputnya ke dalam dokumen XS semasa.
"INCLUDE_COMMAND" memberikan makna istimewa kepada token $^X kerana ia menjalankan perl yang sama
penterjemah yang menjalankan "xsubpp":

INCLUDE_COMMAND: kucing Rpcb1.xsh

INCLUDE_COMMAND: $^X -e ...

. KES: Kata kunci
Kata kunci CASE: membenarkan XSUB mempunyai berbilang bahagian yang berbeza dengan setiap bahagian bertindak sebagai
XSUB maya. KES: adalah tamak dan jika ia digunakan maka semua kata kunci XS yang lain mestilah
terkandung dalam KES:. Ini bermakna tiada apa yang boleh mendahului KES pertama: dalam XSUB dan
apa-apa yang mengikuti KES terakhir: disertakan dalam kes itu.

KES: mungkin bertukar melalui parameter XSUB, melalui "ix" ALIAS: pembolehubah (lihat "The
ALIAS: Kata Kunci"), atau mungkin melalui pembolehubah "item" (lihat "Parameter panjang pembolehubah
Senarai"). KES terakhir: menjadi lalai kes jika ia tidak dikaitkan dengan a
bersyarat. Contoh berikut menunjukkan CASE ditukar melalui "ix" dengan fungsi
"rpcb_gettime()" mempunyai alias "x_gettime()". Apabila fungsi dipanggil sebagai
"rpcb_gettime()" parameternya adalah biasa "(char *host, time_t *timep)", tetapi apabila
fungsi dipanggil sebagai "x_gettime()" parameternya diterbalikkan, "(time_t *timep, char
*tuan rumah)".

lama
rpcb_gettime(a,b)
KES: ix == 1
ALIAS:
x_gettime = 1
MASUKKAN:
# 'a' ialah masa, 'b' ialah hos
aksara *b
masa_t a = TIDAK_INIT
KOD:
RETVAL = rpcb_gettime( b, &a );
PENGELUARAN:
a
RETVAL
KES:
# 'a' ialah hos, 'b' ialah masa
aksara *a
masa_t &b = TIDAK_INIT
PENGELUARAN:
b
RETVAL

Fungsi itu boleh dipanggil dengan salah satu daripada pernyataan berikut. Perhatikan yang berbeza
senarai hujah.

$status = rpcb_gettime( $host, $timep );

$status = x_gettime( $timep, $host );

. EXPORT_XSUB_SYMBOLS: Kata kunci
Kata kunci EXPORT_XSUB_SYMBOLS: berkemungkinan sesuatu yang anda tidak akan perlukan. Dalam perl
versi lebih awal daripada 5.16.0, kata kunci ini tidak melakukan apa-apa. Bermula dengan 5.16, simbol XSUB
tidak lagi dieksport secara lalai. Iaitu, ia adalah fungsi "statik". Jika anda termasuk

EXPORT_XSUB_SYMBOLS: DAYAKAN

dalam kod XS anda, XSUB yang mengikuti baris ini tidak akan diisytiharkan "statik". Awak boleh
kemudian lumpuhkan ini dengan

EXPORT_XSUB_SYMBOLS: LUmpuhkan

yang, sekali lagi, adalah lalai yang mungkin anda tidak boleh ubah. Anda tidak boleh menggunakan ini
kata kunci pada versi perl sebelum 5.16 untuk menjadikan XSUB "statik".

. & Tidak sedar operator
Operator unari "&" dalam bahagian INPUT: digunakan untuk memberitahu xsubpp bahawa ia harus menukar
nilai Perl ke/dari C menggunakan jenis C di sebelah kiri "&", tetapi berikan penunjuk kepada ini
nilai apabila fungsi C dipanggil.

Ini berguna untuk mengelakkan KOD: blok untuk fungsi C yang mengambil parameter oleh
rujukan. Lazimnya, parameter hendaklah bukan jenis penunjuk ("int" atau "panjang" tetapi
bukan "int*" atau "long*").

XSUB berikut akan menghasilkan kod C yang salah. The xsubpp pengkompil akan mengubah ini
ke dalam kod yang memanggil "rpcb_gettime()" dengan parameter "(char *host, time_t timep)", tetapi
"rpcb_gettime()" sebenar mahu parameter "timep" menjadi jenis "time_t*" dan bukannya
"masa_t".

bool_t
rpcb_gettime(host,timep)
char *tuan rumah
masa_t masa
PENGELUARAN:
masa

Masalah itu dibetulkan dengan menggunakan operator "&". The xsubpp pengkompil kini akan bertukar
ini ke dalam kod yang memanggil "rpcb_gettime()" dengan betul dengan parameter "(char *host, time_t
*timep)". Ia melakukan ini dengan membawa "&" melalui, jadi panggilan fungsi kelihatan seperti
"rpcb_gettime(host, &timep)".

bool_t
rpcb_gettime(host,timep)
char *tuan rumah
masa_t &masa
PENGELUARAN:
masa

Memasukkan Pod, Komen-komen and C Prapemproses Arahan
Arahan prapemproses C dibenarkan dalam BOOT:, PREINIT: INIT:, CODE:, PPCODE:,
POSTCALL:, dan CLEANUP: blok, serta di luar fungsi. Komen dibenarkan
mana-mana sahaja selepas kata kunci MODUL. Pengkompil akan lulus arahan prapemproses
melalui tidak disentuh dan akan mengalih keluar baris komen. Dokumentasi POD dibenarkan di mana-mana
titik, kedua-duanya dalam bahagian bahasa C dan XS. POD mesti ditamatkan dengan "=cut"
perintah; "xsubpp" akan keluar dengan ralat jika tidak. Sangat tidak mungkin manusia itu
kod C yang dihasilkan akan disalah anggap sebagai POD, kerana kebanyakan gaya inden menghasilkan ruang putih
di hadapan mana-mana baris bermula dengan "=". Fail XS yang dihasilkan oleh mesin mungkin jatuh ke dalam perangkap ini
melainkan jika penjagaan diambil untuk memastikan bahawa ruang memecahkan urutan "\n=".

Komen boleh ditambahkan pada XSUB dengan meletakkan "#" sebagai ruang bukan putih pertama baris.
Berhati-hati harus diambil untuk mengelakkan membuat ulasan kelihatan seperti arahan prapemproses C,
jangan sampai ditafsirkan begitu. Cara paling mudah untuk mencegah perkara ini adalah dengan meletakkan ruang putih
hadapan "#".

Jika anda menggunakan arahan prapemproses untuk memilih salah satu daripada dua versi fungsi, gunakan

#jika ... versi1
#else /* ... versi2 */
#endif

dan tidak

#jika ... versi1
#endif
#jika ... versi2
#endif

kerana sebaliknya xsubpp akan percaya bahawa anda membuat definisi pendua bagi
fungsi. Juga, letakkan baris kosong sebelum #else/#endif supaya ia tidak akan dilihat sebagai sebahagian
daripada badan fungsi.

Menggunakan XS Dengan C + +
Jika nama XSUB mengandungi "::", ia dianggap sebagai kaedah C++. Perl yang dihasilkan
fungsi akan menganggap bahawa hujah pertamanya ialah penunjuk objek. Penunjuk objek
akan disimpan dalam pembolehubah yang dipanggil INI. Objek sepatutnya telah dicipta oleh C++ dengan
yang baru() berfungsi dan harus diberkati oleh Perl dengan sv_setref_pv() makro. The
memberkati objek oleh Perl boleh dikendalikan oleh peta taip. Contoh peta taip ditunjukkan
pada akhir bahagian ini.

Jika jenis pulangan XSUB termasuk "statik", kaedah itu dianggap sebagai statik
kaedah. Ia akan memanggil fungsi C++ menggunakan kelas:: kaedah() sintaks. Jika kaedahnya
bukan statik fungsi akan dipanggil menggunakan THIS->kaedah() Sintaks.

Contoh seterusnya akan menggunakan kelas C++ berikut.

warna kelas {
awam:
warna();
~warna();
int biru();
void set_blue( int );

peribadi:
int c_blue;
};

XSUB untuk biru() and set_blue() kaedah ditakrifkan dengan nama kelas tetapi
parameter untuk objek (INI, atau "diri") adalah tersirat dan tidak disenaraikan.

int
warna::biru()

membatalkan
warna::set_blue( val )
int val

Kedua-dua fungsi Perl akan mengharapkan objek sebagai parameter pertama. Dalam C++ yang dihasilkan
kod objek dipanggil "INI", dan panggilan kaedah akan dilakukan pada objek ini.
Jadi dalam kod C++ itu biru() and set_blue() kaedah akan dipanggil seperti ini:

RETVAL = INI->biru();

INI->set_blue( val );

Anda juga boleh menulis kaedah get/set tunggal menggunakan hujah pilihan:

int
warna::biru( val = NO_INIT )
int val
PROTOTAIP $;$
KOD:
jika (item > 1)
INI->set_blue( val );
RETVAL = INI->biru();
PENGELUARAN:
RETVAL

Jika nama fungsi itu ialah Memusnahkan maka fungsi "delete" C++ akan dipanggil dan "INI"
akan diberikan sebagai parameternya. Kod C++ yang dihasilkan untuk

membatalkan
warna::DESTROY()

akan kelihatan seperti ini:

warna *INI = ...; // Dimulakan seperti dalam peta taip

padam INI;

Jika nama fungsi itu ialah baru maka fungsi "baru" C++ akan dipanggil untuk mencipta a
objek C++ dinamik. XSUB akan mengharapkan nama kelas, yang akan disimpan dalam pembolehubah
dipanggil "KELAS", untuk diberikan sebagai hujah pertama.

warna *
warna::baru()

Kod C++ yang dihasilkan akan memanggil "baru".

RETVAL = warna baharu();

Berikut ialah contoh peta taip yang boleh digunakan untuk contoh C++ ini.

PETA TAIP
warna * O_OBJECT

OUTPUT
# Objek Perl diberkati menjadi 'CLASS', yang sepatutnya a
# char* mempunyai nama pakej untuk berkat.
O_OBJECT
sv_setref_pv( $arg, CLASS, (void*)$var );

INPUT
O_OBJECT
if( sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG) )
$var = ($jenis)SvIV((SV*)SvRV( $arg ));
lain {
warn("${Pakej}::$func_name() -- " .
"$var bukan rujukan SV yang diberkati");
XSRETURN_UNDEF;
}

Antara muka Strategi
Apabila mereka bentuk antara muka antara Perl dan perpustakaan C terjemahan lurus dari C ke
XS (seperti yang dicipta oleh "h2xs -x") selalunya mencukupi. Walau bagaimanapun, kadang-kadang antara muka
akan kelihatan sangat seperti C dan kadangkala tidak intuitif, terutamanya apabila fungsi C
mengubah suai salah satu parameternya, atau mengembalikan kegagalan dalam jalur (seperti dalam "nilai pulangan negatif
bermakna kegagalan"). Dalam kes di mana pengaturcara ingin mencipta antara muka yang lebih seperti Perl
strategi berikut boleh membantu mengenal pasti bahagian antara muka yang lebih kritikal.

Kenal pasti fungsi C dengan parameter input/output atau output. XSUB untuk ini
fungsi mungkin boleh mengembalikan senarai kepada Perl.

Kenal pasti fungsi C yang menggunakan beberapa maklumat jalur dalam sebagai petunjuk kegagalan. Mereka mungkin
menjadi calon untuk kembali undef atau senarai kosong sekiranya gagal. Sekiranya kegagalan itu mungkin
dikesan tanpa panggilan ke fungsi C, anda mungkin mahu menggunakan bahagian INIT: untuk melaporkan
kegagalan. Untuk kegagalan yang dapat dikesan selepas fungsi C kembali, seseorang mungkin ingin menggunakan a
POSTCALL: bahagian untuk memproses kegagalan. Dalam kes yang lebih rumit gunakan CODE: atau PPCODE:
bahagian.

Jika banyak fungsi menggunakan petunjuk kegagalan yang sama berdasarkan nilai pulangan, anda mungkin mahu
untuk mencipta typedef khas untuk mengendalikan keadaan ini. Letak

typedef int negative_is_failure;

berhampiran permulaan fail XS, dan buat entri peta taip OUTPUT untuk
"negative_is_failure" yang menukar nilai negatif kepada "undef", atau mungkin kuak()s. Selepas
ini nilai pulangan jenis "negative_is_failure" akan mencipta lebih banyak antara muka seperti Perl.

Kenal pasti nilai yang digunakan oleh hanya fungsi C dan XSUB itu sendiri, katakan, apabila a
parameter kepada fungsi haruslah kandungan pembolehubah global. Jika Perl tidak perlu
untuk mengakses kandungan nilai maka mungkin tidak perlu menyediakan terjemahan
untuk nilai itu dari C ke Perl.

Kenal pasti penunjuk dalam senarai parameter fungsi C dan nilai pulangan. Beberapa petunjuk
boleh digunakan untuk melaksanakan parameter input/output atau output, ia boleh dikendalikan dalam XS dengan
operator unari "&", dan, mungkin, menggunakan kata kunci NO_INIT. Sesetengah orang lain akan
memerlukan pengendalian jenis seperti "int *", dan seseorang perlu memutuskan apakah Perl yang berguna
terjemahan akan dilakukan dalam kes sedemikian. Apabila semantik jelas, adalah dinasihatkan untuk meletakkan
terjemahan ke dalam fail peta taip.

Kenal pasti struktur yang digunakan oleh fungsi C. Dalam banyak kes ia mungkin berguna untuk digunakan
peta taip T_PTROBJ untuk struktur ini supaya ia boleh dimanipulasi oleh Perl seperti yang diberkati
objek. (Ini dikendalikan secara automatik oleh "h2xs -x".)

Jika jenis C yang sama digunakan dalam beberapa konteks berbeza yang memerlukan berbeza
terjemahan, "typedef" beberapa jenis baharu dipetakan kepada jenis C ini, dan buat berasingan
peta taip entri untuk jenis baharu ini. Gunakan jenis ini dalam pengisytiharan jenis pulangan dan
parameter kepada XSUB.

Perl Objek dan C Struktur
Apabila berurusan dengan struktur C seseorang harus memilih sama ada T_PTROBJ or T_PTRREF untuk XS
menaip. Kedua-dua jenis direka untuk mengendalikan penunjuk kepada objek kompleks. Jenis T_PTRREF
akan membenarkan objek Perl tidak diberkati manakala jenis T_PTROBJ memerlukan bahawa
objek diberkati. Dengan menggunakan T_PTROBJ seseorang boleh mencapai satu bentuk pemeriksaan jenis kerana
XSUB akan cuba mengesahkan bahawa objek Perl adalah daripada jenis yang dijangkakan.

Kod XS berikut menunjukkan getnetconfigent() fungsi yang digunakan dengan ONC+ TIRPC.
. getnetconfigent() fungsi akan mengembalikan penunjuk kepada struktur C dan mempunyai C
prototaip ditunjukkan di bawah. Contoh akan menunjukkan bagaimana penunjuk C akan menjadi Perl
rujukan. Perl akan menganggap rujukan ini sebagai penunjuk kepada objek dan kehendak yang diberkati
cuba memanggil pemusnah untuk objek itu. Pemusnah akan disediakan dalam XS
sumber untuk membebaskan memori yang digunakan oleh getnetconfigent(). Pemusnah dalam XS boleh dicipta oleh
menentukan fungsi XSUB yang namanya berakhir dengan perkataan Memusnahkan. Pemusnah XS boleh
digunakan untuk membebaskan memori yang mungkin telah dimalokkan oleh XSUB yang lain.

struct netconfig *getnetconfigent(const char *netid);

"typedef" akan dibuat untuk "struct netconfig". Objek Perl akan diberkati dalam a
kelas sepadan dengan nama jenis C, dengan teg "Ptr" dilampirkan dan nama itu sepatutnya
tidak mempunyai ruang terbenam jika ia akan menjadi nama pakej Perl. Pemusnah akan diletakkan
dalam kelas yang sepadan dengan kelas objek dan kata kunci PREFIX akan digunakan untuk
potong nama kepada perkataan DESTROY seperti yang dijangkakan oleh Perl.

typedef struct netconfig Netconfig;

MODUL = PAKEJ RPC = RPC

Netconfig *
getnetconfigent(netid)
char *netid

MODUL = PAKEJ RPC = NetconfigPtr PREFIX = rpcb_

membatalkan
rpcb_DESTROY(netconf)
Netconfig *netconf
KOD:
printf("Sekarang dalam NetconfigPtr::DESTROY\n");
percuma( netconf );

Contoh ini memerlukan entri peta taip berikut. Rujuk perlxstypemap untuk maklumat lanjut
maklumat tentang menambah peta taip baharu untuk sambungan.

PETA TAIP
Netconfig * T_PTROBJ

Contoh ini akan digunakan dengan pernyataan Perl berikut.

gunakan RPC;
$netconf = getnetconfigent("udp");

Apabila Perl memusnahkan objek yang dirujuk oleh $netconf ia akan menghantar objek ke
membekalkan fungsi XSUB DESTROY. Perl tidak dapat menentukan, dan tidak peduli, bahawa ini
objek ialah struct C dan bukan objek Perl. Dalam pengertian ini, tidak ada perbezaan antara
objek yang dicipta oleh getnetconfigent() XSUB dan objek yang dicipta oleh Perl biasa
subrutin.

selamat Penyimpanan statik Tarikh in XS
Bermula dengan Perl 5.8, rangka kerja makro telah ditakrifkan untuk membolehkan data statik
disimpan dengan selamat dalam modul XS yang akan diakses daripada Perl berbilang benang.

Walaupun direka terutamanya untuk digunakan dengan Perl berbilang benang, makro telah
direka supaya mereka akan berfungsi dengan Perl bukan berulir juga.

Oleh itu, amat disyorkan bahawa makro ini digunakan oleh semua modul XS yang membuat
penggunaan data statik.

Cara paling mudah untuk mendapatkan set templat makro untuk digunakan ialah dengan menentukan "-g"
("--global") pilihan dengan h2xs (lihat h2xs).

Di bawah ialah contoh modul yang menggunakan makro.

#define PERL_NO_GET_CONTEXT
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

/* Data Global */

#define MY_CXT_KEY "BlindMice::_guts" XS_VERSION

typedef struct {
kiraan int;
nama char[3][100];
} my_cxt_t;

START_MY_CXT

MODUL = BlindMice PAKEJ = BlindMice

BOOT:
{
MY_CXT_INIT;
MY_CXT.count = 0;
strcpy(MY_CXT.name[0], "Tiada");
strcpy(MY_CXT.name[1], "Tiada");
strcpy(MY_CXT.name[2], "Tiada");
}

int
newMouse(char * nama)
PREINIT:
dMY_CXT;
KOD:
jika (MY_CXT.count >= 3) {
warn("Sudah ada 3 tikus buta");
RETVAL = 0;
}
lain {
RETVAL = ++ MY_CXT.count;
strcpy(MY_CXT.name[MY_CXT.count - 1], nama);
}
PENGELUARAN:
RETVAL

char *
get_mouse_name(index)
indeks int
PREINIT:
dMY_CXT;
KOD:
jika (indeks > MY_CXT.count)
croak("Hanya ada 3 ekor tikus buta.");
lagi
RETVAL = MY_CXT.name[index - 1];
PENGELUARAN:
RETVAL

membatalkan
KLON(...)
KOD:
MY_CXT_CLONE;

MY_CXT RUJUKAN

MY_CXT_KEY
Makro ini digunakan untuk menentukan kunci unik untuk merujuk kepada data statik untuk XS
modul. Skim penamaan yang dicadangkan, seperti yang digunakan oleh h2xs, adalah menggunakan rentetan itu
terdiri daripada nama modul, rentetan "::_guts" dan nombor versi modul.

#define MY_CXT_KEY "MyModule::_guts" XS_VERSION

typedef my_cxt_t
Jenis struct ini kemestian sentiasa dipanggil "my_cxt_t". Makro "CXT*" yang lain diandaikan
kewujudan nama typedef "my_cxt_t".

Isytiharkan typedef bernama "my_cxt_t" iaitu struktur yang mengandungi semua data
yang perlu menjadi penterjemah tempatan.

typedef struct {
int some_value;
} my_cxt_t;

START_MY_CXT
Sentiasa letakkan makro START_MY_CXT terus selepas pengisytiharan "my_cxt_t".

MY_CXT_INIT
Makro MY_CXT_INIT memulakan storan untuk struct "my_cxt_t".

It kemestian dipanggil tepat sekali, biasanya dalam bahagian BOOT:. Jika anda mengekalkan
berbilang jurubahasa, ia harus dipanggil sekali dalam setiap contoh jurubahasa, kecuali
untuk penterjemah yang diklon daripada yang sedia ada. (Tetapi lihat "MY_CXT_CLONE" di bawah.)

dMY_CXT
Gunakan makro dMY_CXT (pengisytiharan) dalam semua fungsi yang mengakses MY_CXT.

MY_CXT
Gunakan makro MY_CXT untuk mengakses ahli struct "my_cxt_t". Contohnya, jika
"my_cxt_t" ialah

typedef struct {
indeks int;
} my_cxt_t;

kemudian gunakan ini untuk mengakses ahli "indeks".

dMY_CXT;
MY_CXT.index = 2;

aMY_CXT/pMY_CXT
"dMY_CXT" mungkin agak mahal untuk dikira dan untuk mengelakkan overhed penggunaan
ia dalam setiap fungsi adalah mungkin untuk menyampaikan pengisytiharan ke fungsi lain menggunakan
makro "aMY_CXT"/"pMY_CXT", cth

batal sub1() {
dMY_CXT;
MY_CXT.index = 1;
sub2(aMY_CXT);
}

batal sub2(pMY_CXT) {
MY_CXT.index = 2;
}

Secara analog dengan "pTHX", terdapat bentuk yang setara apabila makro adalah yang pertama atau
terakhir dalam berbilang argumen, dengan garis bawah mewakili koma, iaitu "_aMY_CXT",
"aMY_CXT_", "_pMY_CXT" dan "pMY_CXT_".

MY_CXT_CLONE
Secara lalai, apabila jurubahasa baharu dicipta sebagai salinan yang sedia ada (cth melalui
"threads->create()"), kedua-dua jurubahasa berkongsi struktur my_cxt_t fizikal yang sama.
Memanggil "MY_CXT_CLONE" (biasanya melalui fungsi "CLONE()" pakej), menyebabkan
salinan bait-untuk-bait struktur yang akan diambil, dan sebarang dMY_CXT akan datang akan menyebabkan
salinan untuk diakses sebaliknya.

MY_CXT_INIT_INTERP(my_perl)
dMY_CXT_INTERP(my_perl)
Ini adalah versi makro yang mengambil penterjemah eksplisit sebagai hujah.

Ambil perhatian bahawa makro ini hanya akan berfungsi bersama dalam sama fail sumber; itu adalah
dMY_CTX dalam satu fail sumber akan mengakses struktur yang berbeza daripada dMY_CTX dalam yang lain
fail sumber.

Sedar benang sistem antara muka
Bermula dari Perl 5.8, dalam tahap C/C++ Perl tahu cara membungkus antara muka sistem/perpustakaan
yang mempunyai versi sedar benang (cth getpwent_r()) ke dalam makro bahagian hadapan (cth getpwent())
yang mengendalikan interaksi berbilang benang dengan betul dengan penterjemah Perl. Ini akan
berlaku secara telus, satu-satunya perkara yang perlu anda lakukan ialah membuat instantiate jurubahasa Perl.

Pembalutan ini sentiasa berlaku apabila menyusun sumber teras Perl (PERL_CORE ditakrifkan) atau
Sambungan teras Perl (PERL_EXT ditakrifkan). Apabila menyusun kod XS di luar teras Perl
pembungkusan tidak berlaku. Walau bagaimanapun, ambil perhatian bahawa mencampurkan _r-bentuk (seperti Perl
disusun untuk operasi berbilang benang akan berfungsi) dan bentuk _r-less tidak baik-
ditakrifkan (hasil yang tidak konsisten, kerosakan data atau ranap menjadi lebih berkemungkinan), mahupun
adakah ia sangat mudah alih.

CONTOH


Fail "RPC.xs": Antara muka kepada beberapa fungsi perpustakaan mengikat ONC+ RPC.

#define PERL_NO_GET_CONTEXT
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

#include

typedef struct netconfig Netconfig;

MODUL = PAKEJ RPC = RPC

SV *
rpcb_gettime(host="localhost")
char *tuan rumah
PREINIT:
masa_t masa;
KOD:
ST(0) = sv_newmortal();
if( rpcb_gettime( hos, &timep ) )
sv_setnv( ST(0), (berganda)masa );

Netconfig *
getnetconfigent(netid="udp")
char *netid

MODUL = PAKEJ RPC = NetconfigPtr PREFIX = rpcb_

membatalkan
rpcb_DESTROY(netconf)
Netconfig *netconf
KOD:
printf("NetconfigPtr::MEMUSNAHKAN\n");
percuma( netconf );

Fail "peta taip": Peta taip tersuai untuk RPC.xs. (rujuk perlxstypemap)

PETA TAIP
Netconfig * T_PTROBJ

Fail "RPC.pm": Modul Perl untuk sambungan RPC.

pakej RPC;

memerlukan Pengeksport;
memerlukan DynaLoader;
@ISA = qw(Pengeksport DynaLoader);
@EXPORT = qw(rpcb_gettime getnetconfigent);

RPC bootstrap;
1;

Fail "rpctest.pl": Program ujian Perl untuk sambungan RPC.

gunakan RPC;

$netconf = getnetconfigent();
$a = rpcb_gettime();
cetak "masa = $a\n";
cetak "netconf = $netconf\n";

$netconf = getnetconfigent("tcp");
$a = rpcb_gettime("poplar");
cetak "masa = $a\n";
cetak "netconf = $netconf\n";

CATATAN


Kod XS mempunyai akses penuh kepada panggilan sistem termasuk fungsi perpustakaan C. Ia dengan itu mempunyai
keupayaan untuk mengganggu perkara yang telah disediakan oleh teras Perl atau modul lain,
seperti pengendali isyarat atau pemegang fail. Ia boleh merosakkan ingatan, atau mana-mana nombor
perkara yang memudaratkan. jangan.

Sesetengah modul mempunyai gelung acara, menunggu input pengguna. Sangat tidak mungkin dua itu
modul tersebut akan berfungsi dengan secukupnya bersama dalam satu aplikasi Perl.

Secara umum, jurubahasa perl melihat dirinya sebagai pusat alam semesta sejauh
Program Perl berjalan. Kod XS dilihat sebagai rakan bantu, untuk mencapai perkara yang perl
tidak melakukan, atau tidak melakukan cukup pantas, tetapi sentiasa tunduk kepada perl. Semakin dekat kod XS
mematuhi model ini, semakin kecil kemungkinan konflik akan berlaku.

Satu kawasan yang telah berlaku konflik adalah berkenaan dengan kawasan C. (Lihat perlocale.)
perl, dengan satu pengecualian dan melainkan diberitahu sebaliknya, menyediakan tempat asas yang
program sedang berjalan ke tempat yang dihantar ke dalamnya dari persekitaran. Ini adalah sebuah
perbezaan penting daripada program bahasa C generik, di mana tempat asas adalah
Tempatan "C" melainkan program mengubahnya. Setakat v5.20, tempat asas ini ialah
tersembunyi sepenuhnya daripada kod perl tulen di luar skop leksikal "use locale" kecuali untuk
beberapa fungsi memanggil dalam modul POSIX yang mana perlu menggunakannya. Tetapi
tempat asas, dengan satu pengecualian itu terdedah kepada kod XS, yang menjejaskan semua perpustakaan C
rutin yang tingkah lakunya bergantung kepada setempat. Kod XS anda lebih baik tidak menganggap bahawa
tempat asas ialah "C". Pengecualian ialah kategori tempat "LC_NUMERIC" dan
sebab ia adalah pengecualian kerana pengalaman telah menunjukkan bahawa ia boleh menjadi masalah untuk XS
kod, sedangkan kami tidak mempunyai laporan masalah dengan kategori tempat lain. Dan
sebab kategori yang satu ini bermasalah ialah aksara yang digunakan sebagai perpuluhan
titik boleh berbeza-beza. Banyak bahasa Eropah menggunakan koma, manakala bahasa Inggeris, dan oleh itu Perl adalah
mengharapkan titik (U+002E: FULL STOP). Banyak modul boleh mengendalikan hanya aksara radix
menjadi titik, dan sebagainya perl cuba menjadikannya begitu. Sehingga melalui Perl v5.20, percubaan itu adalah
semata-mata untuk menetapkan "LC_NUMERIC" semasa permulaan ke tempat "C". mana-mana setlocale() jika tidak,
akan mengubahnya; ini menyebabkan beberapa kegagalan. Oleh itu, bermula dalam v5.22, perl cuba untuk
pastikan "LC_NUMERIC" sentiasa ditetapkan kepada "C" untuk kod XS.

Untuk meringkaskan, berikut ialah perkara yang diharapkan dan cara mengendalikan tempat dalam kod XS:

Kod XS yang tidak disedari tempatan
Perlu diingat bahawa walaupun anda fikir kod anda tidak mengetahui setempat, ia mungkin memanggil C
fungsi perpustakaan iaitu. Mudah-mudahan halaman manual untuk fungsi sedemikian akan menunjukkan
pergantungan itu, tetapi dokumentasinya tidak sempurna.

Tempat semasa terdedah kepada kod XS kecuali mungkin "LC_NUMERIC" (diterangkan dalam
perenggan seterusnya). Tidak ada laporan mengenai masalah dengan yang lain
kategori. Perl memulakan perkara semasa permulaan supaya tempat semasa adalah satu
yang ditunjukkan oleh persekitaran pengguna yang berkuat kuasa pada masa itu. Lihat
"ENVIRONMENT" dalam perllocale.

Walau bagaimanapun, sehingga v5.20, Perl memulakan perkara pada permulaan supaya "LC_NUMERIC"
telah ditetapkan ke tempat "C". Tetapi jika mana-mana kod di mana-mana mengubahnya, ia akan kekal
berubah. Ini bermakna modul anda tidak boleh mengharapkan "LC_NUMERIC" menjadi sesuatu
tertentu, dan anda tidak boleh mengharapkan nombor titik terapung (termasuk rentetan versi) untuk
mempunyai titik di dalamnya. Jika anda tidak membenarkan bukan titik, kod anda boleh pecah jika ada
di mana-mana menukar tempat. Atas sebab ini, v5.22 mengubah tingkah laku supaya Perl
cuba mengekalkan "LC_NUMERIC" dalam tempat "C" kecuali di sekitar operasi secara dalaman
di mana ia sepatutnya menjadi sesuatu yang lain. Kod XS yang salah laku akan sentiasa boleh berubah
tempat itu pula, tetapi contoh yang paling biasa ini disemak dan dikendalikan.

Kod XS yang sedar setempat
Jika tempat daripada persekitaran pengguna dikehendaki, XS tidak perlu
kod untuk menetapkan tempat kecuali untuk "LC_NUMERIC", kerana perl telah menyediakannya. XS
kod harus mengelak daripada menukar tempat, kerana ia boleh menjejaskan yang lain, tidak berkaitan,
kod dan mungkin tidak selamat untuk thread. Walau bagaimanapun, beberapa perpustakaan asing yang mungkin dipanggil melakukannya
tetapkannya, seperti "Gtk". Ini boleh menyebabkan masalah untuk teras perl dan modul lain.
Bermula dalam v5.20.1, memanggil fungsi sync_locale() daripada XS sepatutnya mencukupi
untuk mengelakkan kebanyakan masalah ini. Sebelum ini, anda memerlukan pernyataan Perl tulen bahawa
Adakah ini:

POSIX::setlocale(LC_ALL, POSIX::setlocale(LC_ALL));

Sekiranya kod XS anda mungkin memerlukan tempat "LC_NUMERIC" asas, terdapat
makro tersedia untuk mengakses ini; lihat "Fungsi dan makro berkaitan tempatan" dalam perlapi.

XS VERSION


Dokumen ini merangkumi ciri yang disokong oleh "ExtUtils::ParseXS" (juga dikenali sebagai "xsubpp")
3.13_01.

Gunakan perlxs dalam talian menggunakan perkhidmatan onworks.net



Program dalam talian Linux & Windows terkini