İngilizceFransızcaİspanyolca

OnWorks favicon'u

PDL::PPp - Bulutta Çevrimiçi

PDL::PPp'yi Ubuntu Online, Fedora Online, Windows çevrimiçi emülatörü veya MAC OS çevrimiçi emülatörü üzerinden OnWorks ücretsiz barındırma sağlayıcısında çalıştırın

Bu, Ubuntu Online, Fedora Online, Windows çevrimiçi emülatörü veya MAC OS çevrimiçi emülatörü gibi birden fazla ücretsiz çevrimiçi iş istasyonumuzdan birini kullanarak OnWorks ücretsiz barındırma sağlayıcısında çalıştırılabilen PDL::PPp komutudur.

Program:

ADI


PDL::PP - Kısa açıklamalardan PDL rutinleri oluşturun

SİNOPSİS


Evliliğin bona fide bir evlilik olduğu şu belgeler ile ispatlanabilir:

pp_def(
'sumak',
Pars => 'a(n); [o]b();',
Kod => q{
çift ​​tmp=0;
döngü(n) %{
tmp += $a();
%}
$b() = tmp;
},
);

pp_done();

FONKSİYONLAR


Burada PDL::PP tarafından sağlanan işlevlerin hızlı bir başvuru listesi bulunmaktadır.

pp_add_boot
Oluşturulan XS dosyasının BOOT bölümüne kod ekleyin

pp_add_exported
Dışa aktarılan işlevler listesine işlevler ekleyin

pp_add_isa
@ISA listesine girdiler ekleyin

pp_addbegin
Oluşturma .pm dosyasının üstüne eklenecek kodu ayarlar

pp_addhdr
Oluşturulan XS dosyasının C bölümüne kod ekleyin ve içerir

pp_addpm
Oluşturulan .pm dosyasına kod ekleyin

pp_addxs
Oluşturulan XS dosyasına fazladan XS kodu ekleyin

pp_beginwrap
Oluşturulan .pm dosyası için koda BEGIN-blok sarma ekleyin

pp_bless
XS kodunun eklendiği paketi ayarlar (varsayılan PDL'dir)

pp_boundscheck
PDL sınırlarını kontrol etme etkinliğinin kontrol durumu

pp_core_importList
PDL::Core'dan nelerin içe aktarılacağını belirtin

pp_def
Yeni bir PDL işlevi tanımlayın

pp_deprecate_module
Kullanımdan kaldırılan bir modül hakkında çalışma zamanı ve POD uyarıları ekleyin

pp_done
Dosyadaki PDL::PP tanımlarının sonunu işaretleyin

pp_export_nothing
Oluşturduğunuz modül için dışa aktarma listesini temizleyin

pp_line_numbers
PDL::PP kodunda hata ayıklamayı basitleştirmek için satır numarası bilgisi ekleyin

pp_setversion
.pm ve .xs dosyaları için sürümü ayarlayın

GENEL BAKIŞ


Neden PP'ye ihtiyacımız var? Birkaç neden: ilk olarak, alt program oluşturabilmek istiyoruz.
PDL veri türlerinin her biri için kod (PDL_Byte, PDL_Short, vb.). OTOMATİK OLARAK. İkincisi,
Perl'deki PDL dizilerinin dilimlerine atıfta bulunurken (örneğin "$a->slice('0:10:2,:')" veya diğer
transpoze gibi şeyler) bunu şeffaf bir şekilde yapabilmek ve yapabilmek güzel
bunu 'yerinde' yapmak için - yani, bölümün bir bellek kopyasını yapmak zorunda kalmamak. PP kulplar
sizin için gerekli tüm eleman ve ofset aritmetiği. kavramları da var
iş parçacığı oluşturma (birden çok dilim için aynı rutinin tekrarlanan çağrılması, bkz. PDL::İndeksleme)
ve PP kullanımının izin verdiği veri akışı (bkz. PDL::Dataflow).

Aşağıdakilerin çoğunda, okuyucunun aşağıdaki kavramlara aşina olduğunu varsayacağız.
PDL içinde örtük ve açık iş parçacığı oluşturma ve dizin manipülasyonları. henüz yapmadıysanız
Bu kavramları duydunuz veya onlarla çok rahat değilseniz, kontrol etmenin zamanı geldi
PDL::İndeksleme.

Adından da anlaşılacağı gibi PDL::PP bir Ön İşlemcidir, yani kodu şu şekilde genişletir:
gerçek C kodu yapmak için ikameler. Teknik olarak çıktı XS kodudur (bkz. perlx'ler) fakat
C'ye çok yakın.

Peki PP'yi nasıl kullanıyorsunuz? Eh, çoğunlukla, sadece sıradan C kodu yazıyorsunuz, bunun dışında
şu şekli alan özel PP yapıları:

$bir şey(başka bir şey)

ya da alışveriş sepetinize tıklayın:

PPişlev %{

%}

En önemli PP yapısı "$array()" formudur. Çok basit PP'yi düşünün
1B vektörün öğelerini toplama işlevi (aslında bu, gerçek vektöre çok benzer)
'sumover' tarafından kullanılan kod):

pp_def('toplam',
Pars => 'a(n); [o]b();',
Kod => q{
çift ​​tmp;
tmp = 0;
döngü(n) %{
tmp += $a();
%}
$b() = tmp;
}
);

Neler oluyor? "Pars =>" satırı PP için çok önemlidir - tüm
argümanlar ve boyutları. biz buna imza PP fonksiyonunun (karşılaştırın
ayrıca PDL::İndeksleme içindeki açıklamalar). Bu durumda rutin, 1 boyutlu işlevi şu şekilde alır:
girdi ve çıktı olarak 0-D skaler döndürür. "$a()" PP yapısı erişmek için kullanılır
a(n) dizisinin elemanları sizin için - PP gerekli tüm C kodunu doldurur.

"q{}" tek tırnak operatörünü kullandığımızı fark edeceksiniz. bu bir değil
kaza. PP Kodu bölümlerinizi belirtmek için genellikle tek tırnak kullanmak istersiniz. PDL::PP
ayrıştırma için "$var()" kullanır ve tek tırnak kullanmazsanız Perl,
"$var()" enterpolasyonu yapın. Ayrıca, tek tırnaklı "q" operatörünü kaşlı ayraçlarla kullanmak,
Bir kod bloğu oluşturuyormuşsunuz gibi görünüyorsunuz, yani Ne Demek İstiyorsunuz. (Perl yeterince akıllı
iç içe küme parantezlerini arayın ve eşleşen kümeyi bulana kadar teklifi kapatmayın
destekleyin, bu nedenle iç içe bloklara sahip olmak güvenlidir.)
dize bitiştirmelerini kullanarak bir Kod bloğunu bir araya getirmek, genellikle kullanımı en kolay olanıdır
gibi gerçek tek tırnak

Kod => 'bir şey'.$interpolable.'bir şey;'

Buradaki tüm elemanlara erişilen basit durumda, PP yapısı "loop(n) %{ ...
%}", "n" boyutundaki tüm öğeler üzerinde döngü yapmak için kullanılır. PP'nin şu özelliğine dikkat edin: ALL
ÖLÇÜLER İSİM İLE BELİRTİLMİŞTİR.

PP'den kaçınırsak bu daha açık hale gelir. döngü () döngüyü açıkça oluştur ve yaz
geleneksel C kullanarak:

pp_def('toplam',
Pars => 'a(n); [o]b();',
Kod => q{
int i,n_size;
çift ​​tmp;
n_size = $SIZE(n);
tmp = 0;
for(i=0; ben
tmp += $a(n=>i);
}
$b() = tmp;
},
);

öncekiyle aynı şeyi yapar, ancak daha uzun solukludur. "i" öğesini elde etmek için görebilirsiniz
a() "$a(n=>i)" deriz - boyutu "n" adıyla belirtiyoruz. 2D olarak şunu söyleyebiliriz:

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

"m=>i" sözdizimi, aslında uygulamada kullanılan Perl karmalarından ödünç alır.
PP'nin. Sıra önemli olmadığından "$a(n=>j,m=>i)" de denilebilir.

Yukarıdaki örnekte başka bir PP yapısının kullanımını da görebilirsiniz - $SIZE(n) almak için
"n" boyutunun uzunluğu.

Bununla birlikte, mümkün olduğunda açık bir C-döngüsü yazmamanız gerektiğine dikkat edilmelidir.
PDL::PP döngü sınırlarını otomatik olarak kontrol ettiğinden, PP "döngü" yapısını kullandık
siz, "döngü" kullanımı kodu daha özlü hale getirir, vb. Ama kesinlikle durumlar var
döngünün açık kontrolüne ihtiyaç duyduğunuz yerde ve şimdi nasıl yapacağınızı biliyorsunuz;).

'Neden PP?' konusunu tekrar ziyaret etmek için - için yukarıdaki kod zirve() her veri türü için üretilecektir. Bilişim Teknoloji
'yerinde' dizi dilimleri üzerinde çalışacaktır. Otomatik olarak işleyecektir - örneğin bir 2D ise
dizi verilirse, her 1D satır için tekrar tekrar çağrılır (tekrar PDL::Indexing için kontrol edin.
iş parçacığı ayrıntıları). Ve sonra b(), her satırın toplamlarının 1B dizisi olacaktır. Yapabiliriz
bunun yerine sütunları toplamak için $a->xchg(0,1) ile çağırın. Ve Dataflow izleme vb.
kullanılabilir.

PP'nin programcıyı gereksiz yere tekrar eden çok sayıda C kodu yazmaktan kurtardığını görebilirsiniz --
Bize göre bu, PDL'nin yeni C alt rutinleri yazmanın en iyi özelliklerinden biridir.
PDL için inanılmaz kısa ve öz bir egzersiz. İkinci bir neden, PP'yi genişletme yeteneğidir.
kısa kod tanımlarınızı bilgisayarın ihtiyaçlarına göre farklı C koduna dönüştürün
söz konusu mimari. Örneğin, bir süper bilgisayara sahip olduğunuz için şanslı olduğunuzu hayal edin.
ellerin; bu durumda PDL::PP'nin kesinlikle avantaj sağlayan kod oluşturmasını istersiniz.
makinenizin vektörleştirme/paralel hesaplama özelliklerinin (bu,
gelecek). Her durumda, sonuç olarak, değişmeyen kodunuzun hala genişletilmesi gerektiğidir.
PDL'nin içindekiler değişse bile çalışan XS kodu.

Ayrıca, kodu gerçek bir Perl betiğinde oluşturduğunuz için, birçok eğlence vardır.
yapabileceğiniz şeyler. Diyelim ki hem sumt (yukarıdaki gibi) hem de multit yazmanız gerekiyor.
Biraz yaratıcılıkla yapabiliriz

for({Ad => 'sumit', Init => '0', Op => '+='},
{Ad => 'çoklu', Başlangıç ​​=> '1', İşlem => '*='}) {
pp_def($_->{Ad},
Pars => 'a(n); [o]b();',
kod => '
çift ​​tmp;
tmp = '.$_->{Init}.';
döngü(n) %{
tmp '.$_->{Op}.' $a();
%}
$b() = tmp;
');
}

bu, her iki işlevi de kolayca tanımlar. Şimdi, daha sonra imzayı değiştirmeniz gerekirse veya
boyutluluk ya da her neyse, kodunuzda yalnızca bir yeri değiştirmeniz gerekir. Evet tabi,
düzenleyicinizde 'kes ve yapıştır' ve 'ara ve değiştir' var ama yine de daha az
tek bir yeri unutmak ve garip hatalara sahip olmak can sıkıcı ve kesinlikle daha zor
sürün. Ayrıca, 'orit' (bitsel veya) sonradan eklemek tek satırlık bir işlemdir.

Ve unutmayın, gerçekten Perl'in tüm yeteneklerine sahipsiniz - çok kolay okuyabilirsiniz
herhangi bir girdi dosyası ve bu dosyadaki bilgilerden rutinler yapın. gibi basit durumlar için
yukarıdakiler, yazar (Tjl) şu anda yukarıdaki gibi karma sözdizimini tercih ediyor - çok değil
karşılık gelen dizi sözdiziminden çok daha fazla karakter, ancak anlaşılması çok daha kolay ve
değiştirin.

Burada ayrıca verinin başlangıcına işaretçiyi alma yeteneğinden de bahsetmeliyiz.
bellek - PDL'yi bazı kitaplıklarla arabirimlemek için bir ön koşul. Bu ile halledilir
"$P(var)" yönergesi, aşağıya bakın.

Yeni bir pp_def'ined işlevi üzerinde çalışmaya başlarken, bir hata yaparsanız, genellikle
oluşturulan XS dosyasında satır numaralarını gösteren bir yığın derleyici hatası bulun. Eğer sen
XS dosyalarını nasıl okuyacağınızı bilin (veya zor yoldan öğrenmek istiyorsanız),
XS dosyasını oluşturun ve hatalı satır numarasını arayın. Ancak yakın zamanda bir
PDL::PP'ye ek olarak, hatalarınızın doğru satır numarasını bildirmenize yardımcı olur:
"pp_line_numbers". Orijinal zirve örneğiyle çalışmak, eğer yanlış yazılmışsa
tmp olarak yazarsanız, (hatalar) kodunu bunun gibi bir şeyle değiştirebilirsiniz ve
derleyici size çok daha faydalı bilgiler verecektir:

pp_def('toplam',
Pars => 'a(n); [o]b();',
Kod => pp_line_numbers(__LINE__, q{
çift ​​tmp;
tmp = 0;
döngü(n) %{
tmp += $a();
%}
$b() = devir;
})
);

Yukarıdaki durum için derleyicim bana şunları söylüyor:

...
test.pd:15: hata: 'rmp' bildirilmedi (bu işlevde ilk kullanım)
...

Örnek betiğimde (test.pd olarak adlandırılır), 15. satır tam olarak benim yaptığım satırdır.
yazım hatası: "tmp" yerine "rmp".

Bu nedenle, PDL rutinlerini programlamanın genel özelliklerine bu hızlı genel bakıştan sonra,
PDL::PP bunu hangi durumlarda kullanmanız gerektiğini özetleyelim.
önişlemci/ön derleyici. İsterseniz PDL::PP kullanmalısınız.

· bazı harici kütüphanelere arayüz PDL

· Perl'de kodlanırsa yavaş olacak bir algoritma yazın (bu sizin kadar sık ​​değil
düşünmek; önce iş parçacığına ve veri akışına bir göz atın).

· bir PDL geliştiricisi olun (ve o zaman bile zorunlu değildir)

UYARI


Mimarisi nedeniyle, PDL::PP bir yandan hem esnek hem de kullanımı kolay olabilir,
ama aynı zamanda aşırı derecede karmaşık. Şu anda, sorunun bir kısmı bu hatadır.
mesajlar çok bilgilendirici değildir ve bir şeyler ters giderse, ne yaptığınızı bilseniz iyi olur.
yapıyor ve dahili olarak yolunuzu kesebileceksiniz (veya
"pp_def" için argümanlarınızda neyin yanlış olduğunu deneme yanılma). için çalışma yapılıyor olsa da
daha iyi uyarılar üretin, varsa sorularınızı e-posta listesine göndermekten çekinmeyin.
başın belaya girer.

TANIM


Artık yeni PDL işlevlerini tanımlamak için "pp_def"in nasıl kullanılacağı hakkında bir fikriniz olduğuna göre, şimdi zamanı geldi.
"pp_def"in genel sözdizimini açıklar. "pp_def" argüman olarak önce
tanımladığınız işlev ve ardından çeşitli anahtarlar içerebilen bir karma liste.

Bu anahtarlara dayalı olarak PP, XS kodu ve bir .pm dosyası oluşturur. "pp_done" işlevi (bkz.
SYNOPSIS'teki örnek), PDL::PP'de daha fazla tanım olmadığını söylemek için kullanılır.
bu dosya ve .xs dosyasını oluşturma zamanı geldi ve
.pm dosyası.

Sonuç olarak, birkaç olabilir pp_def() bir dosyanın içindeki çağrılar (konvansiyonel dosyalar tarafından
PP kodu ile .pd veya .pp uzantısına sahiptir, ancak genellikle yalnızca bir pp_done().

İki ana farklı kullanım türü vardır. pp_def(), 'veri işlemi' ve 'dilim
operasyonun prototipleri.

'Veri işlemi' bazı verileri almak, karıştırmak ve diğer bazı verileri çıktılamak için kullanılır; Bugün nasılsın
örneğin '+' işlemini, matris tersini, toplamayı vb. ve tüm örnekleri içerir
Şimdiye kadar bu belgede bahsettik. Örtük ve açık iş parçacığı oluşturma ve
Bu işlemlerde sonucun oluşturulması otomatik olarak halledilir. hatta yapabilirsin
"zirve", "sumover" vb. ile veri akışı yapın (anlayamıyorsanız dehşete kapılmayın
PDL'de veri akışı kavramı henüz çok iyi; hala çok deneysel).

'Dilim işlemi' farklı bir işlem türüdür: bir dilim işleminde
herhangi bir veriyi değiştirerek, iki farklı öğe arasındaki yazışmaları tanımlarsınız.
piddles (örnekler, dosyadaki dizin işleme/dilimleme işlevi tanımlarını içerir
dilimler.pd bu, PDL dağıtımının bir parçasıdır; ama dikkat, bu başlangıç ​​seviyesi değil
şey).

PDL hatalı değerler desteğiyle derlenmişse (yani "WITH_BADVAL => 1"), o zaman ek
aşağıda açıklandığı gibi "pp_def" için anahtarlar gereklidir.

Sadece bazı harici kütüphanelerle iletişim kurmakla ilgileniyorsanız (örneğin bazı
lineer cebir/matris kitaplığı), genellikle 'veri işlemini' isteyeceksiniz, bu yüzden gidiyoruz
önce bunu tartışmak için.

Veri operasyon


A basit örnek
Veri işleminde, hangi veri boyutlarına ihtiyacınız olduğunu bilmelisiniz. İlk olarak, bir örnek
skaler ile:

pp_def('ekle',
Pars => 'a(); B(); [o]c();',
Kod => '$c() = $a() + $b();'
);

Bu biraz garip görünüyor ama onu inceleyelim. İlk satır kolaydır: bir
'ekle' adıyla rutin. İkinci satır basitçe parametrelerimizi bildirir ve
parantezler skaler oldukları anlamına gelir. Parametrelerimizi tanımlayan dizgeyi çağırırız ve
onların boyutluluğu imza bu işlevin. Konuyla ilgisi nedeniyle
iş parçacığı ve dizin manipülasyonları PDL::Indexing kılavuz sayfasını kontrol edin.

Üçüncü satır gerçek işlemdir. Dolar işaretlerini ve parantezleri kullanmanız gerekir
parametrelerinize atıfta bulunmak için (bu muhtemelen gelecekte bir noktada değişecektir,
iyi sözdizimi bulundu).

Bu satırlar, PDL işlevini gerçekten tanımlamak için gerekli olan tek şeydir (peki,
aslında değil; ayrıca bir Makefile.PL yazmanız (aşağıya bakın) ve
modül ('perl Makefile.PL; make' gibi bir şey); ama şimdilik bunu görmezden gelelim).
Yani şimdi yapabilirsin

MyModule'u kullanın;
$a = pdl 2,3,4;
$b = pdl 5;

$c = ekle($a,$b);
# veya
add($a,$b,($c=null)); # Alternatif form, eğer $c kullanılmışsa kullanışlıdır
# büyük bir şeye önceden ayarlanmış, burada kullanışlı değil.

ve iş parçacığının düzgün çalışmasını sağlayın (sonuç $c == [7 8 9]).

The Pars Bölüm: the imza of a PP işlev
Yukarıdaki örnek kodu görünce büyük olasılıkla şunu soracaksınız: Bu garip "$c=null" nedir?
yeni "ekle" işlevimize yapılan ikinci çağrıdaki sözdizimi? eğer bir daha bakarsan
"ekle" tanımının üçüncü argümanı olan "c"nin şu şekilde işaretlendiğini fark edeceksiniz.
PDL::PP'ye bunun bir çıktı argümanı olduğunu söyleyen "[o]" niteleyicisi. Yani yukarıdaki çağrı
add 'doğru boyutlarla sıfırdan yeni bir $c oluştur' anlamına gelir - "boş" özel bir
'boş piddle' için belirteç (bunu işaretlemek için neden "undef" değerini kullanmadığımızı sorabilirsiniz)
PDL'ye özgü "boş" yerine; Şu anda onu düşünüyoruz;).

[Bu, kılavuzun başka bir bölümünde de açıklanmalıdır!!] Nedeni
alternatif olarak bu sözdizimine sahip olmak, gerçekten büyük piddle'larınız varsa, şunları yapabilirsiniz:

$c = PDL->null;
for(biraz uzun döngü) {
# muge a,b
ekle($a,$b,$c);
# munge c, a,b'ye bir şey koy
}

ve her seferinde $c tahsis etmekten ve tahsis etmekten kaçının. İlk başta bir kez tahsis edilir
Ekle() ve bundan sonra bellek $c yok edilene kadar kalır.

sadece söylersen

$c = ekle($a,$b);

PP tarafından oluşturulan kod otomatik olarak "$c=null" değerini dolduracak ve sonucu döndürecektir. Eğer
PDL::PP'nin çıktının alındığı bu stili neden desteklediği hakkında daha fazla bilgi edinmek istiyorsunuz.
argümanlar son argümanlar olarak verilir, PDL::Indexing kılavuz sayfasını kontrol edin.

"[o]", bir pdl argümanının imzada sahip olabileceği tek niteleyici değildir. Bir diğeri
önemli niteleyici, bir pdl'yi geçici olarak işaretleyen "[t]" seçeneğidir. bu ne işe yarar
kastetmek? PDL::PP'ye bu pdl'nin yalnızca aşağıdakiler sırasında geçici sonuçlar için kullanıldığını söylersiniz.
hesaplama ve hesaplama yapıldıktan sonra değeriyle ilgilenmiyorsunuz
Tamamlandı. Ama neden PDL::PP bunu en başta bilmek istesin ki? Sebep
pdl otomatik oluşturma kavramlarıyla yakından ilgilidir (bunu yukarıda duydunuz) ve
örtük iş parçacığı. Otomatik olarak boyutsallığını örtük iş parçacığı kullanırsanız
oluşturulan pdls aslında imzada belirtilenden daha büyüktür. "[o]" işaretli
pdl'ler, sayının gerektirdiği ek boyutlara sahip olacak şekilde oluşturulacaktır.
örtük diş boyutları. Ancak geçici bir pdl oluştururken, her zaman yalnızca
bir iş parçacığı döngüsünde bir yineleme için sonucu tutabilmesi için yeterince büyük yapılmalı, yani
imzanın gerektirdiği kadar büyük. Bir pdl'yi şu şekilde işaretlediğinizde daha az bellek boşa harcanır.
geçici. İkinci olarak, otomatik çıktı oluşturma işlemini geçici pdls ile kullanabilirsiniz.
"[o]" ile işaretlenmiş normal çıktı pdl'leri için yasak olan açık iş parçacığı kullanma
(bkz. PDL::İndeksleme).

İşte [t] niteleyicisini kullandığımız bir örnek. "çağrı" fonksiyonunu tanımlarız.
diziyle aynı boyutta ve türde geçici bir diziye ihtiyaç duyan bir C rutini "f"yi çağırır
"a" ($P için ileriye dönük referans için üzgünüm; bu bir işaretçi erişimidir, aşağıya bakın):

pp_def('çağrı',
Pars => 'a(n); [t] tmp(n); [o] b()',
Kod => 'int ns = $SIZE(n);
f($P(a),$P(b),$P(tmp),ns);
'
);

Tartışma boyutlar ve the imza
Şimdi pdls'nin boyutlarından ve imzadan bahsettik. Nasıl ilişkilidirler?
Bir vektöre bir skaler + indeks numarası eklemek istediğimizi varsayalım:

pp_def('add2',
Pars => 'a(n); B(); [o]c(n);',
Kod => 'loop(n) %{
$c() = $a() + $b() + n;
%}'
);

Burada dikkat edilmesi gereken birkaç nokta vardır: ilk olarak, "Pars" argümanı şimdi n
içinde tek bir boyuta sahip olduğumuzu gösteren argümanlar a ve c. not etmek önemlidir
bu boyutlar, adla erişilen gerçek varlıklardır, bu nedenle bu beyan eder a ve c için
sahip aynı ilk boyutlar. Çoğu PP tanımında, adlandırılmış boyutların boyutu
çıktı olmayan pdl'lerin ilgili boyutlarından ayarlanabilir ("[o]" bayrağı olmayanlar) ancak
bazen adlandırılmış bir boyutun boyutunu bir
tamsayı parametresi. Bunun nasıl çalıştığını "DiğerPars" bölümünün açıklamasında aşağıya bakın.

sabit tartışma boyutlar in the imza
Bir çıktı yığınının otomatik olarak oluşturulmasını istediğinizi ve bunu her seferinde bildiğinizi varsayalım.
boyutu ne olursa olsun, boyutu aynı boyuta sahip olacaktır (9 diyelim).
giriş kürekleri. Bu durumda, belirtmek için Pars bölümünde aşağıdaki sözdizimini kullanırsınız.
boyutun boyutu:

' [o] y(n=9); '

Beklendiği gibi, gerekirse diş açmanın gerektirdiği ekstra boyutlar oluşturulacaktır. Eğer sen
daha karmaşık bir formüle göre adlandırılmış bir boyut atamanız gerekir (sabitten)
aşağıda açıklanan "RedoDimsCode" anahtarını kullanmalısınız.

Tip dönüşümler ve the imza
İmza ayrıca, bir PP olduğunda gerçekleştirilecek tür dönüşümlerini de belirler.
fonksiyon çağrılır. Peki daha önce tanımlanmış olanlarımızdan birini çağırdığımızda ne olur?
farklı türde pdl'ler içeren işlevler, örn.

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

burada $a "PDL_Float" türünde ve $b "PDL_Short" türünde? İmzada gösterildiği gibi
işlemin veri türünün üzerindeki "add2" tanımı (çalışma zamanında belirlendiği gibi)
'en yüksek' tipteki pdl'ninki (sıra bayt < kısa < ushort < uzun < kayan noktadır)
< çift). add2 örneğinde, işlemin veri türü kayan noktadır ($a şuna sahiptir:
veri tipi). Tüm pdl bağımsız değişkenleri daha sonra tür bu veri türüne dönüştürülür (bunlar
yerine dönüştürülür, ancak bir pdl bağımsız değişkeni yoksa doğru türde bir kopya oluşturulur
işlemin türü). Null pdls, aşağıdakilerin belirlenmesinde bir türe katkıda bulunmaz.
operasyonun türü. Ancak, işlemin veri tipi ile oluşturulacaklar;
örneğin burada $ret float türünde olacaktır. zaman bu kuralların farkında olmalısınız.
ek depolamayı almak için farklı türlerdeki pdl'lerle PP işlevlerini çağırmak ve
çalışma zamanı gereksinimleri dikkate alınır.

Bu tür dönüştürmeler, normalde "pp_def" ile tanımladığınız çoğu işlev için doğrudur.
Ancak, biraz değiştirilmiş tür dönüştürme davranışının olduğu bazı durumlar vardır.
İstenen. Bu durumlarda, imzadaki ek niteleyiciler aşağıdakileri belirtmek için kullanılabilir:
tip dönüşümü ile ilgili istenen özellikler. Bu niteleyiciler ile birleştirilebilir
daha önce karşılaştığımız ( oluşturma elemeleri "[o]" ve "[t]"). Hadi gidelim
tür dönüştürme davranışını değiştiren niteleyiciler listesi aracılığıyla.

En önemlisi, bir pdl argümanı kullanıldığında kullanışlı olan "int" niteleyicisidir.
indeksleri başka bir pdl'de temsil eder. "PDL::Ufunc" dan bir örneğe bakalım:

pp_def('maksimum_ind',
Pars => 'a(n); int [o] b()',
Kod => '$GENERIC() kür;
int lor;
döngü(n) %{
if (!n || $a() > cur) {cur = $a(); lor = n;}
%}
$b() = köri;',
);

"maximum_ind" işlevi, bir vektörün en büyük öğesinin dizinini bulur. Eğer bakarsan
imzada, "b" çıktı argümanının şu ifadeyle bildirildiğini fark edeceksiniz.
ek "int" niteleyici. Bunun, tür dönüşümleri için aşağıdaki sonuçları vardır:
pdl "a" girişinin türünden bağımsız olarak, pdl "b" çıkışının türü "PDL_Long" olacaktır.
bu mantıklı çünkü "b", "a" içindeki bir dizini temsil edecektir. Ayrıca, aramanız durumunda
mevcut bir çıktı pdl "b" ile işlev, türü, veri türünü etkilemez
çalıştırma (yukarıya bakın). Dolayısıyla, "a", "b"den daha küçük bir türde olsa bile,
"b" tipine uyacak şekilde dönüştürülür, ancak dokunulmadan kalır, bu da bellek ve CPU döngülerinden tasarruf sağlar
ve "b" endeksleri temsil ettiğinde yapılacak doğru şeydir. Ayrıca, kullanabileceğinizi unutmayın.
'int' niteleyicisi, diğer niteleyicilerle ("[o]" ve "[t]" niteleyicileri) birlikte. sipariş
önemli -- tür niteleyicileri, oluşturma niteleyicilerinden ("[o]" ve "[t]") önce gelir.

Yukarıdaki örnek, "$GENERIC()" makrosunun tipik kullanımını da gösterir. genişler
sözde genel bir döngüde geçerli türe. Genel döngü nedir? zaten senin gibi
bir PP işlevinin, pdl argümanlarının türüne göre belirlenen bir çalışma zamanı veri türüne sahip olduğunu duydum
ile çağrılmıştır. Bu işlev için PP tarafından oluşturulan XS kodu bu nedenle bir
bir vaka seçen "switch (type) {case PDL_Byte: ... case PDL_Double: ...}" gibi geçiş yapın
fonksiyonun çalışma zamanı veri tipine dayalıdır (''loop'' tipi olarak adlandırılır çünkü
PP kodunda vakaları oluşturan bir döngüdür). Her durumda kodunuz bir kez eklenir
her PDL türü için bu switch ifadesine girin. "$GENERIC()" makrosu yalnızca
bu "switch" ifadesinde, ayrıştırılmış kodunuzun her bir kopyasında ilgili tip, örn.
"case PDL_Byte" bölümü "cur", "PDL_Byte" olarak genişler ve diğer durum için böyle devam eder
ifadeler. Sanırım bunun bazı durumlarda pdls değerlerini tutmak için kullanışlı bir makro olduğunun farkındasınızdır.
kodu.

"int" ile benzer etkilere sahip birkaç niteleyici daha vardır. senin için
kolaylık, benzer sonuçları olan "yüzer" ve "çift" niteleyiciler vardır.
dönüşümleri "int" olarak yazın. Diyelim ki bir çok istediğiniz büyük dizi
"sumover" işlevinin eşdeğeri ile satır ve sütun toplamlarını hesaplayın. Bununla birlikte,
"sumover"ın normal tanımı, verileriniz, örneğin
kısa yazın. gibi bir çağrı

toplam($large_pdl,($toplam = boş));

$sums'ın kısa türünde olmasına neden olur ve bu nedenle aşağıdaki durumlarda taşma hatalarına eğilimlidir:
$large_pdl çok büyük bir dizidir. Öte yandan arayarak

@dims = $large_pdl->dims; kaydırma @dims;
toplam($large_pdl,($toplamlar = sıfırlar(double,@dims)));

da iyi bir alternatif değil. Şimdi $sums ile taşma problemimiz yok ama
$large_pdl türünün iki katına dönüştürülmesinin maliyeti, bu gerçekten kötüyse kötü bir şey
büyük bir pdl İşte burada "çift" işe yarar:

pp_def('sumoverd',
Pars => 'a(n); çift ​​[o] b()',
Kod => 'çift tmp=0;
loop(n) %{ tmp += a(); %}
$b() = tmp;',
);

Bu bizi tür dönüştürme ve taşma sorunlarının etrafından dolaştırır. Yine, buna benzer
"int" niteleyicisi "double", türünden bağımsız olarak "b"nin her zaman double türünde olmasını sağlar
Bir yan etki olarak "a" türünde bir dönüşüme yol açmadan "a"nın.

Son olarak, type'ın "int" veya "float" karakterlerinden biri olduğu "type+" niteleyicileri vardır. Ne
anlamına mı gelir. "int+" niteleyicisini gerçek tanımıyla gösterelim.
özet:

pp_def('toplam',
Pars => 'a(n); int+ [o] b()',
Kod => '$GENERIC(b) tmp=0;
loop(n) %{ tmp += a(); %}
$b() = tmp;',
);

"int", "float" ve "double" niteleyicileri için daha önce gördüğümüz gibi, bir pdl ile işaretlenmiş bir
"type+" niteleyicisi, pdl işleminin veri türünü etkilemez. onun anlamı
"bu pdl'yi, türün gerektirdiği şekilde en az "tür" veya daha yüksek türde yapın
işlemi". Toplama örneğinde bunun anlamı, işlevi "a" ile çağırdığınızda
PDL_Short türünde çıktı pdl, PDL_Long türünde olacaktır (tıpkı
"int" niteleyicili durum). Bu, kullanırken yine taşma sorunlarından kaçınmaya çalışır.
küçük veri türleri (örneğin bayt görüntüleri). Ancak, işlemin veri tipi daha yüksek olduğunda
"type+" niteleyicisinde belirtilen türden "b" veri türü ile oluşturulacaktır.
işlem, örneğin "a" double türünde olduğunda "b" de double olacaktır. Umut ediyoruz
Bunun "summer" için mantıklı bir davranış olduğunu kabul ediyorsunuz. nasıl olduğu açık olmalı
"float+" niteleyicisi analojiyle çalışır. Bir küme belirtebilmek gerekli hale gelebilir
parametreler için alternatif türler. Ancak, bu muhtemelen uygulanmayacak
Birisi bunun için makul bir kullanım bulana kadar.

Şunu not edin ki, şimdi $GENERIC makrosunu türetmek için pdl adıyla belirtmemiz gerekiyordu.
bu argümandan yazın. Nedenmiş? Açıklamalarımızı dikkatlice takip ettiyseniz,
bazı durumlarda "b"nin,
operasyon. Bağımsız değişken olarak "b" ile '$GENERIC' makrosunu çağırmak, türün
jenerik döngünün o bölümünde her zaman "b" ile aynı olacaktır.

Bir "pp_def" çağrısındaki "Pars" bölümü hakkında söylenecek her şey bu kadar. Malısın
bu bölümün aşağıdakileri tanımladığını unutmayın: imza PP tanımlı bir fonksiyonun
belirli argümanları çıktı ve geçici argümanlar olarak nitelendirmek için çeşitli seçenekler ve tümü
Daha sonra "Kod" bölümünde başvurabileceğiniz boyutlar adla tanımlanır.

En son PDL'den beri imzanın anlamını anlamanız önemlidir.
sürümleri Perl içinden iş parçacıklı işlevleri tanımlamak için kullanabilirsiniz, yani biz ne diyoruz
Perl seviye threading. Lütfen ayrıntılar için PDL::İndekslemeyi kontrol edin.

The Kod Bölüm
"Kod" bölümü, bir programın en iç kısmında yer alacak gerçek XS kodunu içerir.
iş parçacığı döngüsü (bir iş parçacığı döngüsünün ne olduğunu bilmiyorsanız, o zaman hala okumadınız
PDL::İndeksleme; şimdi yapın ;) herhangi bir PP makrosu ($GENERIC gibi) ve PP işlevleri tamamlandıktan sonra
genişletilmiş (daha sonra açıklayacağımız "döngü" işlevi gibi).

"Sumover" örneğini hızlıca tekrarlayalım:

pp_def('toplam',
Pars => 'a(n); int+ [o] b()',
Kod => '$GENERIC(b) tmp=0;
loop(n) %{ tmp += a(); %}
$b() = tmp;',
);

"Kod" bölümündeki "döngü" yapısı ayrıca boyut adına atıfta bulunur, bu nedenle
herhangi bir limit belirtmeniz gerekiyor: döngü doğru boyutlandırılmış ve her şey sizin için yapılmış,
tekrar.

Ardından, "$a()" ve "$b()" öğelerinin yaptığı şaşırtıcı bir gerçek var. değil indeksi içerir. Bu
gerekli değil çünkü döngü yapıyoruz n ve her iki değişken de hangi boyutları biliyor
böylece otomatik olarak devre dışı bırakıldıklarını bilirler.

Bu özellik birçok yerde çok işe yarar ve kodun çok daha kısa olmasını sağlar. İle ilgili
Elbette, bunu atlatmak istediğiniz zamanlar vardır; burada bir işlev yapan bir işlev
matris simetriktir ve açık döngünün nasıl kodlanacağına bir örnek olarak hizmet eder:

pp_def('symm',
Pars => 'a(n,n); [o]c(n,n);',
Kod => 'loop(n) %{
int n2;
for(n2=n; n2<$SIZE(n); n2++) {
$c(n0 => n, n1 => n2) =
$c(n0 => n2, n1 => n) =
$a(n0 => n, n1 => n2);
}
%}
'
);

Neler olduğunu inceleyelim. İlk olarak, bu işlevin ne yapması gerekiyor? ondan
eşit sayıda sütun ve satır içeren bir 2B matris aldığını gördüğünüz imza ve
aynı boyutta bir matris çıktısı verir. Verilen bir girdi matrisinden $a simetrik bir
çıktı matrisi $c (a^T = A olduğu matris anlamında simetrik, burada ^T matris anlamına gelir
devrik veya PDL dilinde $c == $c->xchg(0,1)). Bunu sadece değerleri kullanarak yapar.
$a köşegeninin üzerinde ve altında. Çıktı matrisinde $c üzerindeki ve altındaki tüm değerler
köşegen $a'dakilerle aynıdır, köşegenin üzerindekiler ise
köşegenin altındakiler (yukarıdaki ve alttakiler burada PDL'nin yazdırdığı şekilde yorumlanır)
2D pdf'ler). Bu açıklama hala biraz garip geliyorsa, devam edin, küçük bir dosya oluşturun.
içine bu tanımı yazdığınız yeni PDL uzantısını oluşturun (bkz.
PP kodu için Makefiles) ve birkaç örnekle deneyin.

Fonksiyonun ne yapması gerektiğini açıkladıktan sonra, buna değecek birkaç nokta var.
sözdizimsel açıdan dikkat çekicidir. İlk olarak, adlı boyutun boyutunu alıyoruz
$SIZE makrosunu kullanarak tekrar "n". İkincisi, birdenbire şu komik "n0" ve "n1"ler var.
koddaki dizin adları, imza yalnızca "n" boyutunu tanımlar. Neden bu? NS
$a ve $b'nin hem birinci hem de ikinci boyutunun
"symm" imzasında "n" olarak adlandırılır. Bu, PDL::PP'ye birinci ve ikinci
bu argümanların boyutu aynı boyutta olmalıdır. Aksi takdirde oluşturulan fonksiyon
bir çalışma zamanı hatası oluşturacaktır. Ancak, şimdi $a ve $c'ye erişimde PDL::PP anlayamaz
hangi indeksin "n" olduğunu, artık sadece indeksin adından ifade eder. bu yüzden
eşit boyut adlarına sahip dizinler, 0'dan başlayarak soldan sağa doğru numaralandırılır, örn.
yukarıdaki örnek "n0", $a ve $c'nin birinci boyutuna, "n1" ikinci boyuta ve
yakında.

Şimdiye kadarki tüm örneklerde, hash'in yalnızca "Pars" ve "Code" üyelerini kullandık.
"pp_def"e geçirildi. Kesinlikle PDL::PP tarafından tanınan başka anahtarlar da vardır ve
bazılarını bu belge boyunca duyacağız. Bir (kapsamlı olmayan) bulun
Ek A'daki anahtarların listesi. Makroların ve PPişlevlerinin bir listesi (sadece karşılaştığımız
henüz yukarıdaki örneklerde bulunanlardan bazıları) hash argümanının değerlerinde genişletilmiştir.
"pp_def" için Ek B'de özetlenmiştir.

Bu noktada PDL::PP'nin tamamen statik olmadığını belirtmek yerinde olabilir,
iyi tasarlanmış rutinler seti (Tuomas'ın dediği gibi: "PP'yi bir dizi rutin olarak düşünmeyi bırakın.
taşa oyulmuş rutinler") değil, PDL::PP yazarının yazdığı şeylerin bir koleksiyonudur.
(Tuomas J. Lukka), PDL uzatma rutinlerine sık sık yazmak zorunda kalacağını düşündü.
PP genişletilebilir olmaya çalışır, böylece gelecekte yeni ihtiyaçlar ortaya çıktıkça yeni ortak kodlar kullanılabilir.
içine geri soyutlanmalıdır. Neden değiştirmek isteyebileceğiniz hakkında daha fazla bilgi edinmek istiyorsanız
PDL::PP ve bunun nasıl yapılacağı, PDL::PP içindekiler bölümüne bakın.

kullanma kötü değerlerimiz
PDL'de derlenmiş kötü değer desteğiniz yoksa bu bölümü ve
ilgili anahtarlar: "BadCode", "HandleBad", ... (değerini yazdırmayı deneyin)
$PDL::Kötü::Durum - 0'a eşitse dümdüz ilerleyin).

Hatalı değerleri işlemek için kod yazarken kullanılan birkaç anahtar ve makro vardır. İlk
biri "HandleBad" anahtarıdır:

HandleBad => 0
Bu, bir pp rutinini şu şekilde işaretler: DEĞİL kötü değerlerle başa çıkmak. Bu rutin piddles gönderilirse
"badflag" setleri ile, ardından STDOUT'a ve piddle'lara bir uyarı mesajı yazdırılır
hatalı değerleri temsil etmek için kullanılan değer geçerli bir sayıymış gibi işlenir. NS
"badflag" değeri, çıktı yığınlarına yayılmaz.

Bunun kullanıldığı duruma bir örnek, genellikle bir yolu olmayan FFT rutinleri içindir.
verilerin bir kısmını görmezden gelmek.

HandleBad => 1
Bu, PDL::PP'nin BadCode bölümünün kullanılmasını sağlayan fazladan kod yazmasına neden olur ve
"$ISBAD()" makrosu (ve kardeşleri) çalışır.

HandleBad verilmez
Giriş kümelerinden herhangi birinin "kötü bayrak" seti varsa, çıkış kümeleri
"kötü bayrak" ayarlıdır, ancak sağlanan herhangi bir BadCode yok sayılır.

"HandleBad" değeri, "BadDoc" anahtarının içeriğini tanımlamak için kullanılır.
Verilen.

Kötü değerleri işlemek için kod biraz farklı yazılmalıdır; Örneğin,

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

gibi bir şey olur

if ( $a() != KÖTÜ DEĞER && $b() != KÖTÜ DEĞER ) {
$c() = $a() + $b();
} Else {
$c() = KÖTÜ;
}

Ancak, ikinci sürümü yalnızca giriş yığınlarında hatalı değerler varsa istiyoruz.
(ve bu kötü değer desteği isteniyor!) - aksi halde orijinal kodu istiyoruz.
"BadCode" anahtarının devreye girdiği yer burasıdır; kötüyse yürütülecek kodu belirtmek için kullanırsınız
değerler mevcut olabilir ve PP bir şeyler yaratmak için hem onu ​​hem de "Kod" bölümünü kullanır.
sevmek:

eğer (bad_values_are_present) {
fantezi_threadloop_stuff {
KötüKod
}
} Else {
fantezi_threadloop_stuff {
Kod
}
}

Bu yaklaşım, kötü değerler olmadığında neredeyse hiç ek yük olmadığı anlamına gelir.
(yani, bozuk bayrak rutini 0 döndürür).

BadCode bölümü, Kod bölümüyle aynı makroları ve döngü yapılarını kullanabilir.
Ancak, aşağıdaki ek makrolar olmadan pek bir faydası olmaz:

$ISBAD(var)
Bir kepçenin değerinin kötü olup olmadığını kontrol etmek için $ISBAD makrosunu kullanın:

if ( $ISBAD(a()) ) { printf("a() bozuk\n"); }

Bir kepçenin verilen öğelerine de erişebilirsiniz:

if ( $ISBAD(a(n=>l)) ) { printf("a() öğesinin %d öğesi kötü\n", l); }

$ISGOOD(var)
Bu, $ISBAD makrosunun tersidir.

$SETBAD(var)
Bir piddle öğesini kötü ayarlamak istediğinizde.

$ISBADVAR(c_var,pdl)
Bir "$a()" kepçesinin değerini bir c değişkenine ("foo" diyelim) önbelleğe aldıysanız, o zaman
kötü olup olmadığını kontrol edin, "$ISBADVAR(foo,a)" kullanın.

$ISGOODVAR(c_var,pdl)
Yukarıdaki gibi, ancak bu sefer önbelleğe alınan değerin kötü olmadığı kontrol ediliyor.

$SETBADVAR(c_var,pdl)
Bir kepçenin hatalı değerini ac değişkenine kopyalamak için "$SETBADVAR(foo,a)" kullanın.

YAPMAK: "$PPISBAD()" vb makrolardan bahsedin.

Bu makroları kullanarak yukarıdaki kod şu şekilde belirtilebilir:

Kod => '$c() = $a() + $b();',
KötüKod => '
eğer ( $ISBAD(a()) || $ISBAD(b()) ) {
$SETBAD(c());
} Else {
$c() = $a() + $b();
}',

Bu Perl, TMTOWTDI olduğundan, şunu da yazabilirsiniz:

KötüKod => '
if ( $ISGOOD(a()) && $ISGOOD(b()) ) {
$c() = $a() + $b();
} Else {
$SETBAD(c());
}',

Belirli bir piddle için bozuk bayrağın değerine erişmek istiyorsanız,
"$PDLSTATExxxx()" makroları:

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

YAPMAK: "pp_def" için "FindBadStatusCode" ve "CopyBadStatusCode" seçeneklerinden de bahsedin
"BadDoc" anahtarı olarak.

arayüz senin kendi/kütüphane fonksiyonlar kullanma PP
Şimdi şunları düşünün: kendi C fonksiyonunuz var (aslında bu
Argüman olarak iki işaretçiyi alan PDL ile arayüz oluşturmak istediğiniz bazı kitaplıklar)
double vektörleri:

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

PDL işlevini tanımlamanın doğru yolu şudur:

pp_def('fonksiyonum',
Pars => 'a(n); [o]b(n);',
GenericTypes => ['D'],
Kod => 'fonksiyonum($SIZE(n),$P(a),$P(b));'
);

"$P(" yılından beri ")" sözdizimi, ilk öğeye bir işaretçi döndürür ve diğer öğeler
bundan sonra yalan söylemesi garanti.

Burada birçok hata yapmanın mümkün olduğuna dikkat edin. İlk olarak, $SIZE(n) kullanılmalıdır
"n" yerine. İkincisi, bu koda herhangi bir döngü koymamalısınız. Üçüncüsü, burada karşılaştığımız
PDL::PP tarafından tanınan yeni bir karma anahtar: "GenericTypes" bildirimi PDL::PP'ye şunu söyler:
YALNIZCA BELİRTİLEN TÜRLERİN LİSTESİNİ FOP TİPİ OLUŞTURUN. Bu durumda "çift". Bu
iki avantajı vardır. İlk olarak, derlenen kodun boyutu büyük ölçüde azaltılır, ikincisi ise
çift ​​olmayan argümanlar "myfunc()" öğesine iletilir PDL bunları otomatik olarak
harici C rutinine geçmeden önce ikiye katlayın ve daha sonra geri dönüştürün.

Bireysel argüman türlerini nitelemek için "Pars" da kullanılabilir. Böylece biri de olabilir
bunu şu şekilde yaz:

pp_def('fonksiyonum',
Pars => 'çift a(n); double [o]b(n);',
Kod => 'fonksiyonum($SIZE(n),$P(a),$P(b));'
);

"Pars" içindeki tür belirtimi, argümanı typeloop'taki varyasyondan muaf tutar -
bunun yerine otomatik olarak ve belirtilen türden dönüştürülür. bu açıkçası
daha genel bir örnekte yararlıdır, örneğin:

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

pp_def('fonksiyonum',
Pars => 'float a(n); uzun [o]b(n);',
GenericTypes => ['F'],
Kod => 'fonksiyonum($SIZE(n),$P(a),$P(b));'
);

Tip döngüsünün boyutunu azaltmak için hala "GenericTypes" kullandığımızı unutmayın, açıkçası PP olabilir
prensipte bunu tespit edin ve kod henüz bunu elde etmemiş olsa da otomatik olarak yapın
gelişmişlik seviyesi!

Son olarak, türler otomatik olarak dönüştürüldüğünde, "[o]" niteleyicisini kullanmak ZORUNDADIR.
çıktı değişkenleri veya zor bir değişiklik PP tarafından optimize edilecektir!

Büyük bir kitaplığın arabirimini kurarsanız, arabirimi daha da otomatik hale getirebilirsiniz. Perl olabilir
Bunu yaparken size tekrar(!) yardımcı olun. Pek çok kitaplıkta belirli arama kurallarınız vardır.
Bu istismar edilebilir. Kısacası, küçük bir ayrıştırıcı yazabilirsiniz (ki bu gerçekten
Perl'de zor), daha sonra ayrıştırılmış açıklamalardan "pp_def" çağrılarını oluşturur.
bu kitaplıktaki işlevler. Örnek olarak, lütfen kontrol edin arduvaz arayüzde
PDL dağıtımının "Lib" ağacı. Hangisinin çağrıldığını (hata ayıklama sırasında) kontrol etmek istiyorsanız
PP işlevleri, Perl kodunuz tarafından oluşturulan küçük bir yardımcı paket kullanışlıdır.
PP işlevlerini, bağımsız değişkenlerini stdout'a atan aynı adlı işlevlerle değiştirir.

Sadece söyle

perl -MPDL::PP::Myfile.pd dökümü

"pp_def" ve arkadaşlarına yapılan aramaları görmek için. ile deneyin operasyon.pd ve slatec.pd. Eğer öyleysen
ilgilenen (veya geliştirmek istiyorsanız), kaynak Basic/Gen/PP/Dump.pm'de

Diğer: belirtin makrolar ve fonksiyonlar in the Kod Bölüm
Makrolar: Şimdiye kadar $SIZE, $GENERIC ve $P makrolarıyla karşılaştık. şimdi gidiyoruz
PDL::PP'nin "Kod" bölümünde genişletilen diğer makroları hızlı bir şekilde açıklayın
kullanımlarından örneklerle.

$T $T makrosu, tür anahtarları için kullanılır. Bu, kullanmanız gerektiğinde çok kullanışlıdır.
bağımsız değişkenlerin giriş türüne bağlı olarak farklı harici (örneğin kitaplık) işlevler.
Genel sözdizimi

$Ttypeletters(type_alternatives)

burada "daktilolar", "BSULFD" harflerinin bir alt kümesinin bir permütasyonudur.
Byte, Short, Ushort, vb. için ve "type_alternatives", tür
PP işleminin miktarı, ilgili harfle gösterilene eşittir. Haydi
Bu anlaşılmaz açıklamayı bir örnekle açıklayın. İki C'niz olduğunu varsayarsak
prototiplerle işlevler

void float_func(kayan *içeri, kayan *dışarı);
void double_func(çift *giriş, çift *çıkış);

temelde aynı şeyi yapan ancak biri kayan noktayı ve diğer çift işaretçileri kabul eder.
Genel bir "foofunc" işlevi tanımlayarak (ki bu
dönüşümün türüne bağlı olarak doğru işlevi çağırın):

pp_def('foofunc',
Pars => ' a(n); [o] b();',
Kod => ' $TFD(float_func,double_func) ($P(a),$P(b));'
GenericTypes => [qw(FD)],
);

Lütfen söyleyemeyeceğinizi unutmayın

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

$T makrosu, C önişlemci makrolarına benzer şekilde, izleyen boşluklarla genişlediğinden.
Yukarıda gösterilen biraz daha uzun form doğrudur. Gerçekten kısalık istiyorsanız,
elbette yapabilir

'$TBSULFD('.(join ',',harita {"long_identifier_name_$_"}
qw/byt kısa unseigned lounge flotte duble/).');'

PP $
$PP makrosu, sözde fiziksel işaretçi erişim. fiziksel atıfta
PDL'nin bazı dahili optimizasyonları (PDL çekirdeğine aşina olanlar için
vaffine optimizasyonları hakkında konuşuyor). Bu makro esas olarak dahili kullanım içindir ve siz
normal kodlarınızın hiçbirinde kullanmanız gerekmez.

$COMP (ve "Diğer Pars" bölümü)
$COMP makrosu, kod bölümündeki pdl olmayan değerlere erişmek için kullanılır. Onun adı
PDL'deki dönüşümlerin uygulanmasından türetilmiştir. başvurabileceğiniz değişkenler
$COMP kullanmak, PDL'yi temsil eden "derlenmiş" yapının üyeleridir.
söz konusu dönüşüm ancak boyutlar hakkında henüz herhangi bir bilgi içermiyor
(daha fazla ayrıntı için PDL::Internals'a bakın). Ancak, $COMP'u sadece bir
PDL'deki dönüşümlerin uygulanması hakkında hiçbir şey bilmeden kara kutu.
Peki bu makroyu ne zaman kullanırsınız? Ana kullanımı, bağımsız değişkenlerin değerlerine erişmektir.
"pp_def" tanımının "OtherPars" bölümünde bildirilir. Ama sonra yapmadın
"OtherPars" anahtarını duydunuz mu? Açıklayan başka bir örnek verelim
her iki yeni özelliğin tipik kullanımı:

pp_def('pnmout',
par =>'a(m)',
OtherPars => "char* fd",
GenericTypes => [qw(BUSL)],
Kod => 'PerlIO *fp;
GÇ *İO;

io = GvIO(gv_fetchpv($COMP(fd),YANLIŞ,SVt_PVIO));
if (!io || !(fp = IoIFP(io)))
croak("FP'yi çözemiyorum");

if (PerlIO_write(fp,$P(a),len) != uzun)
croak("pnm dosyası yazılırken hata oluştu");
');

Bu işlev, bir pdl'den bir dosyaya veri yazmak için kullanılır. Dosya tanıtıcısı iletildi
bu işleve bir dize olarak. Bu parametre "Pars" bölümüne girmez
bir pdl gibi yararlı bir şekilde ele alınamayacağından, bunun yerine uygun bir şekilde adlandırılmış
"DiğerPars" bölümü. "DiğerPars" bölümündeki parametreler "Pars" bölümündeki parametreleri takip eder.
işlev çağrılırken bölüm, yani

DOSYA'yı açın">out.dat" veya die "out.dat açılamadı";
pnmout($pdl,'DOSYA');

Bu parametreye kod bölümünden erişmek istediğinizde PP ile belirtmeniz gerekmektedir.
$COMP makrosunu kullanarak, yani örnekte olduğu gibi "$COMP(fd)" yazıyorsunuz. Aksi takdirde PP
Bahsettiğiniz "fd"nin, belirtilenle aynı olduğunu bilemezsiniz.
"DiğerPars" bölümü.

"Diğer Pars" bölümünün başka bir kullanımı, imzada adlandırılmış bir boyut ayarlamaktır.
Bunun nasıl yapıldığına bir örnek verelim:

pp_def('setdim',
Pars => '[o] a(n)',
OtherPars => 'int ns => n',
Kod => 'loop(n) %{ $a() = n; %}',
);

Bu, adlandırılmış "n" boyutunun, değerin değerinden başlatılacağını söylüyor. diğer
parametre Tamsayı türündeki "ns" (sanırım
"CType From => name_dim" sözdizimi). Şimdi bu işlevi normal şekilde çağırabilirsiniz:

setdim(($a=null),5);
$a yazdır;
[ 0 1 2 3 4 ]

Kuşkusuz bu işlev çok kullanışlı değil ama nasıl çalıştığını gösteriyor. Eğer sen
işlevi mevcut bir pdl ile çağırın ve açıkça belirtmeniz gerekmez.
"n" boyutu, çünkü PDL::PP onu boş olmayan pdl'nin boyutlarından anlayabilir. İçinde
bu durumda boyut parametresini "-1" olarak verirsiniz:

$a = geçmiş($b);
setdim($a,-1);

İşte bunu yapmak gerekir.

Şu ana kadar örneklerde kullandığımız tek PP işlevi "loop"tur. Bunlara ek olarak,
şu anda "Kod" bölümünde tanınan iki işlev daha vardır:

iplik halkası
Yukarıda duyduğumuz gibi, PP tanımlı bir fonksiyonun imzası, tüm boyutların boyutlarını tanımlar.
bir ile ilgili pdl argümanları ilkel operasyon. Ancak, genellikle
PP ile tanımladığınız fonksiyonlardan daha fazla boyutu olan pdls ile
imzada belirtilir. Bu durumda ilkel işlem tüm
olarak adlandırılan şeyde uygun boyutlu alt dilimler iplik döngü (Ayrıca bkz
yukarıdaki genel bakış ve PDL::İndeksleme). Bu kavram hakkında bir fikriniz olduğunu varsayarsak,
muhtemelen kod bölümünde belirtilen işlemin olması gerektiğini takdir edecektir.
optimize edilmiştir çünkü bu, bir iplik döngüsü içindeki en sıkı döngüdür. Ancak, tekrar ziyaret ederseniz
"pnmout" fonksiyonunu tanımladığımız örnekte, baktığınızı hemen anlayacaksınız.
iç iş parçacığı döngüsündeki "IO" dosya tanımlayıcısını yukarı yazarken çok verimli değil
çok satırlı bir pdl. "IO" tanımlayıcısını bir kez aramak daha iyi bir yaklaşım olacaktır.
iplik ilmeğinin dışında ve ardından değerini en sıkı iplik ilmeği içinde kullanın. Bu
"threadloop" işlevinin tam olarak kullanışlı olduğu yer. İşte geliştirilmiş bir tanım
Bu işlevi kullanan "pnmout":

pp_def('pnmout',
par =>'a(m)',
OtherPars => "char* fd",
GenericTypes => [qw(BUSL)],
Kod => 'PerlIO *fp;
GÇ *İO;
int uzunluk;

io = GvIO(gv_fetchpv($COMP(fd),YANLIŞ,SVt_PVIO));
if (!io || !(fp = IoIFP(io)))
croak("FP'yi çözemiyorum");

uzunluk = $BOYUT(m) * sizeof($GENERIC());

iplik döngüsü %{
if (PerlIO_write(fp,$P(a),len) != uzun)
croak("pnm dosyası yazılırken hata oluştu");
%}
');

Bu aşağıdaki gibi çalışır. Normalde "Kod" bölümünün içine yazdığınız C kodu yerleştirilir.
bir iş parçacığı döngüsü içinde (yani PP, etrafına uygun sarma XS kodunu oluşturur).
Ancak, "threadloop" işlevini açıkça kullandığınızda, PDL::PP bunu tanır ve
kodunuzu ek bir iş parçacığı döngüsüyle sarmaz. Bu, sizi kodlayan etkiye sahiptir.
iş parçacığı döngüsünün dışına yazma, dönüşüm başına yalnızca bir kez yürütülür ve yalnızca kod
ile çevredeki "%{ ... %}" çifti en sıkı iplik döngüsüne yerleştirilir. Bu
ayrıca bir karar vermek istediğinizde (veya başka bir kod, özellikle
CPU yoğun kod) iş parçacığı başına yalnızca bir kez, yani

pp_addhdr('
#tanımla RAW 0
#ASCII 1'i tanımla
');
pp_def('do_raworascii',
Pars => 'a(); B(); [o]c()',
OtherPars => 'int modu',
Kod => ' anahtarı ($COMP(mod)) {
vaka RAW:
iplik döngüsü %{
/* ham şeyler yap */
%}
break;
vaka ASCII:
iplik döngüsü %{
/* ASCII şeyler yap */
%}
break;
Varsayılan:
croak("bilinmeyen mod");
}'
);

türleri
Types işlevi, $T makrosuna benzer şekilde çalışır. Ancak, "türler" işleviyle
aşağıdaki bloktaki kod (her zamanki gibi "%{" ve "%}" ile sınırlandırılmıştır) tümü için yürütülür
işlemin veri türünün olduğu durumlar herhangi of tarafından temsil edilen türler
"type" argümanındaki harfler, ör.

Kod => '...

türler(BSUL) %{
/* tamsayı tipi işlem yap */
%}
türleri(FD) %{
/* kayan nokta işlemi yap */
%}
...'

The Yeniden YapDimsCode Bölüm
"RedoDimsCode" anahtarı, boşlukların boyutlarını hesaplamak için kullanılan isteğe bağlı bir anahtardır.
imzadan hesaplama boyutları için standart kuralların olmaması durumunda çalışma zamanı
yeterli. "RedoDimsCode" girişinin içeriği şu şekilde yorumlanır:
Kod bölümü yorumlanır-- yani, PP makroları genişletilir ve sonuç
C kodu olarak yorumlanır. Kodun amacı, bazı boyutların boyutunu ayarlamaktır.
imzada görünüyor. Depolama ayırma ve iş parçacığı döngüleri vb. olarak ayarlanacaktır.
hesaplanan boyut imzada görünseydi. Kodunuzda, önce hesaplarsınız
imzada ihtiyacınıza göre adlandırılmış bir boyutun istediğiniz boyutu ve ardından
bu değeri ona $ ile atayınBOY() makro.

Örnek olarak, aşağıdaki durumu göz önünde bulundurun. Harici bir kütüphaneyle arayüz oluşturuyorsunuz
çalışma alanının bağımsız değişken olarak iletilmesi için geçici bir dizi gerektiren rutin. XNUMX
geçirilen girdi veri dizileri p(m) ve x(n). Çıktı veri dizisi y(n)'dir. NS
rutin, n+m*m uzunluğunda bir çalışma alanı dizisi gerektirir ve depolamayı istersiniz
[t] veya [o] ile işaretlenmiş herhangi bir piddle için olduğu gibi otomatik olarak oluşturulur. Ne
istediğin gibi bir şey söylemek

pp_def("dış işlevim",
Pars => " p(m); x(n); [o] y; [t] iş(n+m*m); ", ...

ama bu işe yaramaz, çünkü PP aritmetik ile ifadeleri yorumlayamaz.
imza. bunun yerine sen yaz

pp_def("dış işlevim",
Pars => " p(m); x(n); [o] y; [t] iş(w); ",
RedoDimsCode => "
int im = $PDL(p)->dims[0];
int in = $PDL(x)->dims[0];
int min = + im * im;
int inw = $PDL(work)->dims[0];
$SIZE(wn) = inw >= min ? inw : dk; ",
kod => "
haricifonk($P(p),$P(x),$BOYUT(m),$BOY(n),$P(iş));
";)

Bu kod şu şekilde çalışır: $PDL(p) makrosu, aşağıdakiler için pdl yapısına bir işaretçiye genişler:
pide s. Bu durumda verilere (yani $P ) bir işaretçi istemezsiniz, çünkü
C düzeyindeki piddle yöntemlerine erişmek istiyorum. ilk boyutunu elde edersiniz
piddle'ların her biri ve onları tamsayılarda saklayın. Sonra minimum uzunluğu hesaplarsınız
iş dizisi olabilir. Kullanıcı yeterli depolama alanına sahip bir "çalışma" gönderdiyse, bırakın
tek başına. Kullanıcı gönderdiyse, boş bir pdl söyleyin veya hiç pdl yoksa, o zaman wn boyutu
sıfırlayın ve minimum değere sıfırlayın. Kod bölümündeki koddan önce
yürütülen PP, mevcut değilse "iş" için uygun depolamayı yaratacaktır. unutmayın ki
yalnızca "p" ve "x"in ilk boyutunu aldı çünkü kullanıcı
ekstra diş açma boyutları. Tabii ki, geçici piddle "çalışır" ([t] bayrağına dikkat edin)
zaten herhangi bir diş boyutu verilmemelidir.

[o] ile işaretlenmiş bir piddle'ın boyutunu ayarlamak için "RedoDimsCode"u da kullanabilirsiniz. Bunda
$ kullanarak imzadaki adlandırılmış boyutun boyutlarını ayarlamanız durumundaBOY() içinde olduğu gibi
önceki örnek. Ancak, piddle [t] yerine [o] ile işaretlendiğinden,
diş açma boyutları, gerekirse boyutun boyutu gibi eklenecektir.
olağan kurallara göre imzadan hesaplanır. İşte bir örnek
PDL::Matematik

pp_def("çoklu kökler",
Pars => 'cr(n); ci(n); [Ö]rr(m); [Ö]ri(m);',
RedoDimsCode => 'int sn = $PDL(cr)->dims[0]; $BOYUT(m) = sn-1;',

Girdi yığınları, karmaşık katsayıların gerçek ve sanal kısımlarıdır.
polinom. Çıktı topları köklerin gerçek ve hayali parçalarıdır. "n" var
"n". dereceden bir polinomun kökleri ve böyle bir polinomun "n+1" katsayıları vardır (
"n" ile sıfır). Bu örnekte, iş parçacığı oluşturma düzgün çalışacaktır. yani,
çıkış milinin ilk boyutu, boyutu ayarlanmış, ancak diğer diş açma
boyutlar, "RedoDimsCode" yokmuş gibi atanacaktır.

Tip haritası idare in the "Diğer Pars" Bölüm
Yukarıda tartışılan "Diğer Pars" bölümü, aşağıdaki durumlarda genellikle kesinlikle çok önemlidir.
PDL ile harici kütüphaneleri arayüzleyin. Ancak çoğu durumda dış kütüphaneler ya
türetilmiş türleri veya çeşitli türlerdeki işaretçileri kullanın.

Bunu Perl'de halletmenin standart yolu bir "typemap" dosyası kullanmaktır. Bu tartışılır
standart Perl belgelerinde perlx'lerde bazı ayrıntılar. PP'de işlevsellik çok
benzer, böylece PP dosyanızın bulunduğu dizinde bir "typemap" dosyası oluşturabilirsiniz.
ve oluşturulduğunda uygun çeviriyi bulmak için otomatik olarak okunur
C tipi ile Perl'in yerleşik tipi arasında.

Bununla birlikte, türlerin genel olarak ele alınmasından birkaç önemli fark vardır.
XS'de. Birincisi ve muhtemelen en önemlisi, şu anda türlere yönelik işaretçilerin
"DiğerPars" bölümünde izin verilmez. Bu sınırlamayı aşmak için
"IV" tipi (taşınabilirlik için bunun gerekli olduğunu belirttiği için Judd Taylor'a teşekkürler).

Bunu birkaç kod parçacığıyla göstermek muhtemelen en iyisidir:

Örneğin, "gsl_spline_init" işlevi aşağıdaki C bildirimine sahiptir:

int gsl_spline_init(gsl_spline * spline,
const double xa[], const double ya[], size_t boyut);

Açıkça, "xa" ve "ya" dizileri, piddles olarak geçirilmeye adaylardır ve
"boyut" argümanı, bu piddle'ların yalnızca uzunluğudur, böylece
PP'de "$SIZE()" makrosu. Sorun, "gsl_spline" türünün işaretçisidir. Doğal
çözüm, formun bir "OtherPars" bildirimini yazmak olacaktır.

OtherPars => 'gsl_spline *spl'

ve bu türü işleyen kısa bir "typemap" dosyası yazın. Bu şu anda çalışmıyor
Yine de! O halde yapmanız gereken, sorunu biraz (ve bazı yönlerden) dolaşmaktır.
bu da daha kolay!):

Çözüm, "Diğer Pars" bölümünde "Tamsayı Değeri" kullanarak "spline" bildirmek,
"IV". Bu, değişkenin doğasını PP'den gizler ve daha sonra yapmanız gerekir (kaçınmak için
en azından derleyici uyarıları!) değişkeni kodunuzda kullandığınızda bir tür dökümü gerçekleştirin.
Böylece "OtherPars" şu şekilde olmalıdır:

OtherPars => 'IV spl'

ve kodda kullandığınızda yazacaksınız

INT2PTR(gsl_spline *, $COMP(spl))

önlemek için işaretçi dökümünü işlemek için Perl API makrosu "INT2PTR" kullanıldı
32bit ve 64bit Perl karışık makineler için derleyici uyarıları ve sorunları
konfigürasyonlar. Bunu Andres Jordan'ın yaptığı gibi bir araya getirmek (değişiklikle
dağıtım kaynağındaki "gsl_interp.pd" içinde Judd Taylor tarafından "IV" kullanılarak) şunları elde edersiniz:

pp_def('init_meat',
Pars => 'çift x(n); çift ​​y(n);',
OtherPars => 'IV spl',
Kod =>'
gsl_spline_init,( INT2PTR(gsl_spline *, $COMP(spl)), $P(x),$P(y),$SIZE(n)));'
);

bir makro sarmalayıcı çağrısını kaldırdığım yer, ancak bu, tartışmayı gizleyecektir.

Perl'deki standart tip haritası işleme ile karşılaştırıldığında diğer küçük fark şudur:
kullanıcı, aşağıdakileri kullanarak standart olmayan tip haritası konumlarını veya tip haritası dosya adlarını belirtemez.
MakeMaker'da "TYPEMAPS" seçeneği... Böylece yalnızca "typemap" adlı bir dosyayı ve/veya
Yukarıdaki "IV" numarası.

Diğer: belirtin işe yarar PP anahtarlar in veri operasyon tanımları
"OtherPars" anahtarını zaten duydunuz. Şu anda, başka pek çok anahtar yok
normal (her ne ise) PP programlamasında faydalı olacak bir veri işlemi için. İçinde
Aslında, ihtiyaç duyduğunuzdan daha fazlasına ihtiyacınız olduğunu düşündüğünüz bir vakayı duymak ilginç olurdu.
anda verilmektedir. Lütfen PDL posta listelerinden birinde konuşun. Diğerlerinin çoğu
"pp_def" tarafından tanınan anahtarlar, yalnızca dediğimiz şey için gerçekten yararlıdır dilim operasyonlar (görmek
ayrıca yukarıda).

Güçlü bir şekilde planlanmakta olan bir şey, değişken sayıda argümandır.
biraz zor.

Kullanılabilir anahtarların eksik listesi:

yerinde
Bu tuşun ayarlanması rutini yerinde çalışıyor olarak işaretler - yani giriş ve çıkış
pideler aynı. Örnek olarak "$a->inplace->sqrt()" (veya "sqrt(inplace($a))") verilebilir.

Yerinde => 1
Rutin, "sqrt" gibi tekli bir işlev olduğunda kullanın.

Yerinde => ['a']
Birden fazla giriş yığını varsa, olabilecek birinin adını belirtin.
bir dizi referansı kullanılarak yerinde değiştirildi.

Yerinde => ['a','b']
Birden fazla çıktı kepçesi varsa, giriş kepçesinin adını belirtin ve
2 elemanlı bir dizi referansında çıktı kepçesi. Bu muhtemelen gerekli değil, ama kaldı
eksiksizlik için.

Kötü değerler kullanılıyorsa, yayılmayı sağlamak için özen gösterilmelidir.
yerinde kullanıldığında kötü bayrak; bu alıntıyı dikkate alın Temel/Kötü/kötü.pd:

pp_def('replacebad',HandleBad => 1,
Pars => 'a(); [o]b();',
OtherPars => 'çift yeni değer',
Yerinde => 1,
CopyBadStatusCode =>
'/* yerindeyse ve değişmişse kötü bayrağı yaymak */
if ( a == b && $ISPDLSTATEBAD(a) )
PDL->propogate_badflag(b, 0);

/* çıktının her zaman "iyi" olduğundan emin olun */
$SETPDLSTATEGOOD(b);
',
...

Bu yordam tüm bozuk değerleri kaldırdığından, çıktı piddle'ın bozuk bayrağı vardı
temizlendi. Yerinde çalıştırılırsa (yani "a == b"), tüm çocuklara "a" yı söylemeliyiz.
kötü bayrak temizlendi (zaman kazanmak için
"PDL->propogate_badgflag" yalnızca giriş kepçesinin hatalı bayrağı ayarlanmışsa).

NOT: bir fikir, rutinin belgelerinin otomatik olarak
yerinde yürütülebileceğini belirtmek için işaretlendi, yani nasıl yapılacağına benzer bir şey
"HandleBad", sağlanmadıysa "BadDoc"u ayarlar (bu ideal bir çözüm değildir).

Diğer: belirtin PDL::PP fonksiyonlar için destek Özlü paket tanım
Buraya kadar "pp_def" ve "pp_done" fonksiyonlarını tanımladık. PDL::PP birkaçını dışa aktarır
kısa PDL uzantı paketi tanımları yazmanıza yardımcı olacak diğer işlevler.

pp_addhdr

Çoğu zaman, yukarıdaki örnekte olduğu gibi kitaplık işlevleriyle arayüz oluşturduğunuzda, eklemeniz gerekir.
ek C dosyaları içerir. XS dosyası PP tarafından oluşturulduğundan, bazı araçlara ihtiyacımız var.
PP'nin oluşturulan XS'ye uygun içerme yönergelerini doğru yere eklemesini sağlayın
dosya. Bu amaçla "pp_addhdr" işlevi vardır. Bu aynı zamanda kullanılacak işlevdir
bazı XS işlevleri tarafından dahili kullanım için bazı C işlevlerini tanımlamak istediğinizde
(çoğunlukla "pp_def" ile tanımlanan işlevlerdir). Bu işlevleri buraya ekleyerek
PDL::PP'nin kodunuzu gerçek XS modülünün bulunduğu noktadan önce eklediğinden emin olun.
bölüm başlar ve bu nedenle xsubpp tarafından dokunulmaz (bkz. perlx'ler ve perlxstut
adam sayfaları).

Tipik bir arama

pp_addhdr('
#Dahil etmek /* XXXX tanımlarına ihtiyacımız var */
#include "libprotos.h" /* kitaplık fonksiyonlarının prototipleri */
#include "mylocaldecs.h" /* Yerel decs */

statik void real_work do_the(PDL_Byte * giriş, PDL_Byte * çıkış, int n)
{
/* verilerle bazı hesaplamalar yapın */
}
');

Bu, ihtiyacınız olan tüm sabitlerin ve prototiplerin uygun şekilde dahil edilmesini ve
burada "pp_def"lerde tanımlanan dahili işlevleri kullanabilirsiniz, örneğin:

pp_def('barfoo',
Pars => ' a(n); [o] b(n)',
GenericTypes => ['B'],
Kod => ' int ns = $SIZE(n);
do_the_real_work($P(a),$P(b),ns);
',
);

pp_addpm

Çoğu durumda, gerçek PP kodu ("pp_def" çağrılarının argümanları anlamına gelir) yalnızca bir parçasıdır.
Şu anda uygulamakta olduğunuz paket. Genellikle ek Perl kodu ve XS vardır
normalde pm ve XS dosyalarına yazacağınız kod, şimdi otomatik olarak
PP tarafından oluşturulur. Peki bu şeyleri dinamik olarak oluşturulmuş dosyalara nasıl sokabilirim?
Neyse ki, genellikle "pp_addXXX" olarak adlandırılan ve size yardımcı olan birkaç işlev vardır.
Bunu yaparken.

Oluşturulan dosyaya girmesi gereken ek Perl kodunuz olduğunu varsayalım. pm-dosya. Bu
"pp_addpm" komutuyla kolayca elde edilir:

pp_addpm(<<'EOD');

=kafa1 ADI

PDL::Lib::Mylib -- Mylib kitaplığına yönelik bir PDL arabirimi

= head1 DESCRIPTION

Bu paket, Mylib paketine tam bir arayüz uygular.
diş açma ve indeksleme desteği (bkz. L ).

= kes

PGPLOT'u kullanın;

=kafa2 use_myfunc
bu işlev, myfunc işlemini tüm
boyutlardan bağımsız olarak giriş pdl öğeleri
ve sonucun toplamını döndürür
= kes

alt use_myfunc {
benim $pdl = vardiyam;

myfunc($pdl->küme(-1),($res=null));

$res->sum döndür;
}

DOE

pp_add_exported

Muhtemelen fikrin var. Bazı durumlarda ek dosyanızı da dışa aktarmak istersiniz.
fonksiyonlar. @EXPORT ile de uğraşan PP ile sorun yaşamamak için
PP'ye işlevlerinizi dışa aktarılan işlevler listesine eklemesini söylemeniz yeterlidir:

pp_add_exported('use_myfunc gethynx');

pp_add_isa

"pp_add_isa" komutu, "pp_add_exported" işlevi gibi çalışır. argümanlar
"pp_add_isa" @ISA listesine eklenir, örn.

pp_add_isa(' Bazı::Diğer::Sınıf ');

pp_bless

pp_def rutinleriniz nesne yöntemleri olarak kullanılacaksa, belirtmek için "pp_bless" kullanın.
paketiniz (yani sınıf) pp_defed yöntemleri eklenecektir. Örneğin,
"pp_bless('PDL::MyClass')". Bu atlanırsa varsayılan "PDL"dir.

pp_addxs

Bazen kendinize ait fazladan XS kodu eklemek istersiniz (bu genellikle
herhangi bir iş parçacığı/dizin oluşturma sorunu ancak erişmek istediğiniz başka işlevler sağlar
Perl tarafından) oluşturulan XS dosyasına, örneğin

pp_addxs('','

# Makinenin endianlığını belirleyin

int
isbigendian()
KOD:
imzasız kısa i;
PDL_Byte *b;

ben = 42; b = (PDL_Byte*) (geçersiz*) &i;

eğer (*b == 42)
GERİ DÖN = 0;
aksi takdirde (*(b+1) == 42)
GERİ DÖN = 1;
başka
croak("İmkansız - makine ne büyük ne de küçük endian!!\n");
ÇIKIŞ:
GERİ DÖN
');

Özellikle "pp_add_exported" ve "pp_addxs" dikkatli kullanılmalıdır. PP kullanımları
PDL::Exporter, dolayısıyla PP'nin işlevinizi dışa aktarmasına izin vermek,
varsayılan olarak dışa aktarılan standart işlev listesi (dışa aktarma etiketi tarafından tanımlanan liste
``:İşlev''). "pp_addxs" kullanıyorsanız, iş parçacığı içeren herhangi bir şey yapmaya çalışmamalısınız.
veya doğrudan indeksleme. PP, bilgisayarınızdan uygun kodu oluşturmada çok daha iyidir.
tanımlar.

pp_add_boot

Son olarak, XS dosyasının BOOT bölümüne bazı kodlar eklemek isteyebilirsiniz (eğer yapmazsanız).
bunun ne olduğunu bil perlx'ler). Bu, "pp_add_boot" komutuyla kolayca yapılabilir:

pp_add_boot(<
açıklama = mylib_initialize(KEEP_OPEN);

if (açıklama == NULL)
croak("Kütüphane başlatılamıyor");

GlobalStruc->açıkla = açıkla;
GlobalStruc->maxfiles = 200;
EOB

pp_export_nothing

Varsayılan olarak, PP.pm, pp_def işlevi kullanılarak tanımlanan tüm alt öğeleri .pm çıktısına yerleştirir.
dosyanın İHRACAT listesi. Alt sınıflanmış bir nesne oluşturuyorsanız, bu sorun yaratabilir.
dışa aktarılan herhangi bir yöntemi istemiyorsunuz. (yani yöntemler yalnızca
$nesne->yöntem sözdizimi).

Bu durumlar için arayabilirsiniz pp_export_hiçbir şey() ihracat listesini temizlemek için Örnek (
.pd dosyasının sonu):

pp_export_nothing();
pp_done();

pp_core_importList

Varsayılan olarak, PP.pm 'Çekirdeği kullan;' çıktı .pm dosyasına satır. Bu, Core'un
mevcut ad alanına dışa aktarılan adlar, aşırıya kaçarsanız sorun yaratabilir.
Geçerli dosyada Core'un yöntemlerinden birini kullanmak. gibi mesajlar alıyorsun
Programı çalıştırırken "Uyarı: subclass.pm dosyasında alt toplam yeniden tanımlandı".

Bu durumlarda, pp_core_importList, içe aktarılanları değiştirmek için kullanılabilir.
çekirdek.pm. Örneğin:

pp_core_importList('()')

Bunun sonucunda

çekirdek() kullanın;

çıktı .pm dosyasında oluşturuluyor. Bu, hiçbir adın içe aktarılmamasına neden olur
çekirdek.pm. Benzer şekilde, arama

pp_core_importList(' qw/ barf /')

sonuç verecek

Core qw/ barf/ kullanın;

çıktı .pm dosyasında oluşturuluyor. Bu, yalnızca 'barf'ın içe aktarılmasına neden olur
Core.pm'den.

pp_setversion

Bunun .pm ve .xs dosyalarını aynı anda ayarlamanıza izin verdiğinden oldukça eminim.
sürümler, böylece ikisi arasında gereksiz sürüm çarpıklığı önlenir. Bunu kullanmak için, sadece
.pd dosyanızın bir noktasında aşağıdaki satır:

pp_setversion('0.0.3');

Ancak Module::Build::PDL kullanıyorsanız bunu kullanmayın. için bu modülün belgelerine bakın
detaylar.

pp_deprecate_module

Belirli bir modülün eski olduğu kabul edilirse, bu işlev onu şu şekilde işaretlemek için kullanılabilir:
kullanımdan kaldırıldı. Bu, bir kullanıcı "kullanmaya" çalıştığında bir uyarı verme etkisine sahiptir.
modül. Bu modül için oluşturulan POD ayrıca bir kullanımdan kaldırma bildirimi de taşır. NS
değiştirme modülü şöyle bir argüman olarak iletilebilir:

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

İşlevin etkilediğini unutmayın bir tek çalışma zamanı uyarısı ve POD.

Yapımı senin PP işlev "özel"


Diyelim ki modülünüzde PP'yi kullanan PDL::foo adlı bir fonksiyonunuz var.
ağır kaldırmayı yapmak için "bar_pp" işlevi. Ama bu "bar_pp"nin reklamını yapmak istemezsiniz.
var. Bunu yapmak için, PP işlevinizi modül dosyanızın en üstüne taşımanız gerekir, ardından
çağrı

pp_export_hiçbir şey()

"İHRACAT" listesini temizlemek için Hiçbir belgenin (varsayılan PP belgeleri bile) olmadığından emin olmak için
oluşturulmuş, ayarlanmış

Belge => tanımsız

ve fonksiyonun sembol tablosuna eklenmesini önlemek için,

PMFunc => ''

pp_def bildiriminizde (örnek için Image2D.pd'ye bakın). Bu etkili bir şekilde yapacak
PP işleviniz "özel". Ancak öyle her zaman Perl'den dolayı PDL::bar_pp aracılığıyla erişilebilir
modül tasarımı. Ancak bunu özel yapmak kullanıcının kendi sınırlarının çok dışına çıkmasına neden olur.
kullanmanın bir yolu, bu yüzden sonuçları omuzluyor!

Dilim operasyon


Bu kılavuzun dilim işlemi bölümü, veri akışı ve tembel değerlendirme kullanılarak sağlanmıştır:
İhtiyacınız olduğunda Tjl'den yazmasını isteyin. e-postayı aldığım andan itibaren bir hafta içinde teslimat
%95 olası ve iki haftalık doğum %99 olasıdır.

Her neyse, dilim işlemleri, PDL'nin dahili bilgileri hakkında çok daha fazla bilgi gerektirir.
veri işlemlerinden daha fazladır. Ayrıca, ilgili konuların karmaşıklığı,
ortalama veri işlemindekinden çok daha yüksek. ikna etmek istersen
bu gerçeğe bir göz atın Temel/Dilimler/dilimler.pd PDL'deki dosya
dağıtım :-). Bununla birlikte, dilim işlemleri kullanılarak oluşturulan fonksiyonlar,
PDL'nin dizin işleme ve veri akışı yeteneklerinin kalbi.

Ayrıca, sanal piddles ve vaffines ile ilgili bir çok kirli konu var ki bunları ele alacağız.
burayı tamamen atlayın.

Dilimler ve kötü değerlerimiz
Dilim işlemlerinin hatalı değerleri işleyebilmesi gerekir (destek PDL'de derlenirse).
Bakmak en kolayı Temel/Dilimler/dilimler.pd Bunun nasıl çalıştığını görmek için.

"BadCode" ile birlikte, "BadBackCode" ve "BadRedoDimsCode" tuşları da vardır.
"pp_def". Ancak, herhangi bir "EquivCPOffsCode" değil değişiklik yapılması gerekiyor, çünkü herhangi bir değişiklik
"$EQUIVCPOFFS()" makrosunun tanımına dahil edilir (yani işlenir
PDL::PP> tarafından otomatik olarak.

A az notlar on yazı yazıyor a dilimleme rutin...
Aşağıdaki birkaç paragraf, yeni bir dilimleme rutininin ('aralık') yazılmasını açıklamaktadır; herhangi
hatalar CED'lerdir. (--CED 26-Ağustos-2002)

kullanma of "uyarmak" ve "barf" in PP Kod


Uyarı mesajlarını yazdırmak veya iptal/ölmek için PP'den "uyar" veya "barf" arayabilirsiniz.
kod. Ancak, bu çağrıların C kullanılarak yeniden tanımlandığını bilmelisiniz.
önişlemci makrolarını "PDL->barf" ve "PDL->warn" olarak ayarlayın. Bu yeniden tanımlamalar
yanlışlıkla perl'in "uyarı" veya "barf" ifadesini doğrudan çağırmanızı engeller;
pthreading sırasında segfaults (yani işlemci çoklu iş parçacığı).

PDL'nin kendi "barf" ve "warn" sürümleri, uyarı veya barf mesajlarını sonraya kadar kuyruğa alır
pthreading tamamlandı ve ardından bu rutinlerin Perl versiyonlarını çağırın.

Pthreading hakkında daha fazla bilgi için bkz. PDL::ParallelCPU.

KULLANIŞLI RUTİNLER


PDL "Çekirdek" yapısı, içinde tanımlanan Temel/Çekirdek/pdlcore.h.PL, bir işaretçi içerir
sizin için yararlı olabilecek rutinlerin sayısı. Bu rutinlerin çoğu,
kürekleri manipüle etmek, ancak bazıları daha geneldir:

PDL->qsort_B(PDL_Byte *xx, int a, int b)
"xx" dizisini "a" ve "b" endeksleri arasında sıralayın. için versiyonları da vardır.
"_S", "_U", "_L", "_F" ve "_D" son ekine sahip diğer PDL veri türleri. kullanan herhangi bir modül
bu, "PDL::Ufunc" un yüklendiğinden emin olmalıdır.

PDL->qsort_ind_B( PDL_Byte *xx, int *ix, int a, int b )
"PDL->qsort_B" ile ilgili olarak, ancak bu sefer verilerden ziyade endeksleri sıralıyoruz.

"med2d" rutini Lib/Image2D/image2d.pd bu tür rutinlerin nasıl kullanıldığını gösterir.

YAPILAN DOSYALAR İÇİN PP DOSYALAR


PP dosyanızdan bir paket oluşturacaksanız (tipik dosya uzantıları
PP kodunu içeren dosyalar için ".pd" veya ".pp") bırakmak en kolay ve en güvenli yoldur
Makefile için uygun komutların oluşturulması. Aşağıda ana hatlarıyla anlatacağız
paketinizi otomatik olarak oluşturmak ve kurmak için tipik bir Perl Makefile formatı
PP dosyasındaki bir açıklama. xs, pm ve diğer gerekli dosyaları oluşturmak için kuralların çoğu
PP dosyasından PDL::Core::Dev paketinde önceden tanımlanmıştır. sadece yapmalıyız
MakeMaker'a kullanmasını söyleyin.

Çoğu durumda Makefile'ınızı şöyle tanımlayabilirsiniz:

# PP kodu ile tanımlanan bir paket için Makefile.PL.

PDL::Core::Dev'i kullanın; # Geliştirme yardımcı programlarını alın
ExtUtils::MakeMaker'ı kullanın;

$paket = ["mylib.pd",Mylib,PDL::Lib::Mylib];
%hash = pdlpp_stdargs($paket);
$hash{OBJECT} .= ' ek_Ccode$(OBJ_EXT) ';
$hash{temiz}->{DOSYALAR} .= ' todelete_Ccode$(OBJ_EXT) ';
$hash{'VERSION_FROM'} = 'mylib.pd';
WriteMakefile(%karma);

sub BENİM::postamble { pdlpp_postamble($paket); }

Burada $ paketindeki liste: önce: PP kaynak dosya adı, ardından
üretilen dosyalar ve son olarak tüm paket adı. Karmayı ne olursa olsun değiştirebilirsiniz
istediğiniz gibi ama bazı sınırlar içinde kalmanız mantıklı olur, böylece paketiniz
PDL'nin sonraki sürümleriyle çalışmaya devam edecektir.

Önceden paketlenmiş argümanları kullanmak istemiyorsanız, işte genel bir Makefile.PL yapabilirsiniz ki
kendi ihtiyaçlarınıza göre uyarlayın:

# PP kodu ile tanımlanan bir paket için Makefile.PL.

PDL::Core::Dev'i kullanın; # Geliştirme yardımcı programlarını alın
ExtUtils::MakeMaker'ı kullanın;

Makefile Yaz(
'NAME' => 'PDL::Lib::Mylib',
'VERSION_FROM' => 'mylib.pd',
'TYPEMAPS' => [&PDL_TYPEMAP()],
'OBJECT' => 'mylib$(OBJ_EXT) ek_Ccode$(OBJ_EXT)',
'PM' => { 'Mylib.pm' => '$(INST_LIBDIR)/Mylib.pm'},
'INC' => &PDL_INCLUDE(), # lib'inizin gerektirdiği şekilde ekleme dizinleri ekleyin
'LIBS' => [''], # gerektiğinde bağlantı yönergeleri ekleyin
'temiz' => {'DOSYALAR' =>
'Mylib.pm Mylib.xs Mylib$(OBJ_EXT)
ek_Ccode$(OBJ_EXT)'},
);

# genpp kuralı ekleyin; bu, PP dosyamızda PDL::PP'yi çağırır
# bağımsız değişken, dizinin üç dize öğesi içerdiği bir dizi başvurusudur:
# arg1: PP kodunu içeren kaynak dosyanın adı
# arg2: oluşturulacak xs ve pm dosyalarının temel adı
# arg3: oluşturulacak paketin adı
sub MY::postamble { pdlpp_postamble(["mylib.pd",Mylib,PDL::Lib::Mylib]); }

Hayatı daha da kolaylaştırmak için PDL::Core::Dev, dönen "pdlpp_stdargs" işlevini tanımlar.
iletilebilen varsayılan değerlere sahip bir karma (doğrudan veya uygun
değişiklik) WriteMakefile çağrısına. Şu anda, "pdlpp_stdargs" bir karma döndürür, burada
anahtarlar aşağıdaki gibi doldurulur:

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

Burada $src, PP kodlu kaynak dosyanın adıdır, $pref oluşturulan dosyanın önekidir.
.pm ve .xs dosyaları ve $mod oluşturulacak uzantı modülünün adı.

DAHİLİ


Mevcut sürümün içindekiler, kuralları veren büyük bir tablodan oluşur.
hangi şeylerin tercüme edildiğine ve bu kuralları uygulayan alt bölümlere göre.

Daha sonra, tabloyu kullanıcı tarafından değiştirilebilir hale getirmek iyi olurdu, böylece farklı
şeyler denenebilir.

[Meta yorumu: umarım gelecekte daha fazlası olacaktır; şu anda, en iyi bahsiniz
kaynak kodunu okumak için :-( veya listeden isteyin (önce ikincisini deneyin) ]

Ek A: Bizi anahtarlar tanınan by PDL::PP


Aksi belirtilmedikçe, argümanlar dizelerdir. (Kötü) ile işaretlenen tuşlar yalnızca
kötü değer desteği PDL'de derlenirse kullanılır.

Pars
işlevinizin imzasını tanımlayın

Diğer Pars
pdls olmayan argümanlar. Varsayılan: hiçbir şey. Bu, noktalı virgülle ayrılmış bir listedir.
argümanlar, örneğin, "DiğerPars=>'int k; çift değer; char* fd'". $COMP(x) ve ayrıca bkz.
Ek B'deki aynı giriş.

Kod
işlevselliği uygulayan gerçek kod; birkaç PP makrosu ve PP işlevi
dize değerinde tanınır

HandleBad (kötü)
1'e ayarlanırsa, rutinin hatalı değerleri ve BadCode'daki kodu desteklediği varsayılır.
anahtar, hatalı değerler varsa kullanılır; ayrıca "$ISBAD()"
vb makrolar kullanılabilir. 0'a ayarlanırsa, aşağıdakilerden herhangi biri varsa rutinin bir uyarı yazdırmasını sağlayın.
giriş piddle'larının bozuk bayrağı var.

KötüKod (kötü)
Girdi yığınlarında hatalı değerler varsa kullanılacak kodu verin. Sadece kullanılmış
"HandleBad => 1" ise.

Genel Türler
Bir dizi referansı. Dizi, tek karakterlik 'B' dizelerinin herhangi bir alt kümesini içerebilir,
İşleminizin hangi türleri kabul edeceğini belirten `S', `U', `L', `Q', `F' ve `D'.
Her türün anlamı:

B - imzalı bayt (yani imzalı karakter)
S - imzalı kısa (iki baytlık tam sayı)
U - işaretsiz kısa
L - işaretli uzun (dört baytlık tam sayı, 32 bit sistemlerde int)
Q - işaretli uzun uzun (sekiz bayt tam sayı)
F - yüzer
D - çift

Bu, harici bir kütüphaneyle arayüz oluştururken çok kullanışlıdır (ve önemlidir!). Varsayılan:
[qw/BSULQFD/]

yerinde
Bir işlevi yerinde çalışabilecek şekilde işaretleyin.

Yerinde => 1 ise Pars => 'a(); [o]b();'
Yerinde => ['a'] ise Pars => 'a(); B(); [o]c();'
Yerinde => ['a','b'] ise Pars => 'a(); B(); [o]c(); [o]d();'

Kötü değerler kullanılıyorsa, yayılmayı sağlamak için özen gösterilmelidir.
yerinde kullanıldığında kötü bayrak; örneğin, "replacebad" koduna bakın
Temel/Kötü/kötü.pd.

Belge Bölme biçiminde bir belge dizesi belirtmek için kullanılır. hakkında bilgi için bkz. PDL::Doc
PDL dokümantasyon kuralları. Not: PP 'Doc' dizesinin olduğu özel durumda
bir satır bu, hızlı başvuru VE belgeler için dolaylı olarak kullanılır!

Belge alanı atlanırsa, PP varsayılan belgeler oluşturacaktır (bildiği gibi
İmza hakkında).

Bu noktada işlevin herhangi bir şekilde belgelendirilmemesini gerçekten istiyorsanız (örn.
dahili bir rutin için veya kodun başka bir yerinde yaptığınız için) açıkça
"Doc=>undef" öğesini belirtin.

BadDoc (kötü)
"badinfo" komutu ("perldl" de) veya "-b" anahtarı tarafından döndürülen metni içerir
"pdldoc" kabuk betiğine. Çoğu durumda, bunu belirtmeniz gerekmeyecektir, çünkü
bilgiler PDL::PP tarafından otomatik olarak oluşturulabilir. Ancak bilgisayara yakışır şekilde
oluşturulan metin, oldukça stilize; kendin yapmak çok daha iyi olabilir!

Pthread yok
PDL işlevini belirtmek için isteğe bağlı bayrak değil işlemci iş parçacıklarını kullanın (ör.
pthreads veya POSIX iş parçacıkları), işi birden fazla CPU çekirdeği arasında bölmek için. Bu seçenek
temeldeki PDL işlevi iş parçacığı güvenli değilse tipik olarak 1'e ayarlanır. Bu seçenek
yoksa, işlevin iş parçacığı güvenli olduğu varsayılır. Bu seçenek yalnızca geçerlidir
PDL, POSIX iş parçacıkları etkinleştirilerek derlenmişse.

PMKodu
PDL işlevleri, çıktının kaydedilmesini istediğiniz bir yığına geçmenize izin verir. Bu
kullanışlıdır çünkü bir çıkış kepçesini bir kez tahsis edebilir ve birçok kez yeniden kullanabilirsiniz; NS
alternatif, PDL'nin her seferinde hesaplamayı boşa harcayabilecek yeni bir piddle oluşturması olacaktır.
döngüler veya daha büyük olasılıkla RAM. Bu ek esneklik, daha fazla maliyetle gelir
karmaşıklık: PDL::PP, sayıları saymak için yeterince akıllı işlevler yazmalıdır.
kendisine iletilen argümanlar ve anında yeni yığınlar oluşturun, ancak yalnızca onları istiyorsanız.

PDL::PP bunu yapacak kadar akıllıdır, ancak argüman sıralamasında kısıtlamalar vardır ve
gibi. Daha esnek bir işlev istiyorsanız, kendi Perl tarafınızı yazabilirsiniz.
sarıcı ve PMCode anahtarında belirtin. Sağladığınız dize gerekir (olmalıdır)
ilk adımda pp_def'e verdiğiniz adla eşleşen bir Perl işlevi tanımlayın
yer. Sonunda PP tarafından oluşturulan işlevi çağırmak istediğinizde,
tüm kümeleri imzada belirtilen sırayla sağlayın: çıktı kümeleri
isteğe bağlı değildir ve PP tarafından oluşturulan işlev hiçbir şey döndürmez. şaşkın
arayacağınız isim _ _int.

Bu belgelerin daha fazla açıklamaya ihtiyacı olduğuna inanıyorum, ancak bunun yapılması gerekecek.
:-(

PMFunc
pp_def işlevleri oluşturduğunda, genellikle bunları PDL paketinde tanımlar. Sonra,
modülünüz için oluşturduğu .pm dosyasına genellikle şu satırı ekler:
esasen bu işlevi mevcut paketinizin sembol tablosuna kodla kopyalar
şuna benziyor:

*işlev_adı = \&PDL::işlev_adı;

Bundan biraz daha akıllı (bu tür şeyleri ne zaman
Örneğin BEGIN bloğu ve pp_bless için farklı bir şey belirttiyseniz), ancak
işin özü bu. İşlevi mevcut cihazınıza aktarmayı umursamıyorsanız
paketin sembol tablosunu belirtebilirsiniz

PMFunc => '',

PMFunc'un başka hiçbir yan etkisi yoktur, bu nedenle onu rastgele Perl kodu eklemek için kullanabilirsiniz.
İsterseniz modülünüze. Ancak, Perl eklemek istiyorsanız pp_addpm kullanmalısınız.
modülünüze kodlayın.

Ek B: PP makrolar ve fonksiyonlar


Makrolar
(Kötü) ile etiketlenen makrolar, yalnızca kötü değer desteği PDL'de derlenirse kullanılır.

$değişkenadı_from_sig()
imzada belirtilen bir pdl'ye (adına göre) erişin

$COMP(x)
bu dönüşümün özel veri yapısındaki bir değere erişin (esas olarak
"Diğer Pars" bölümünde belirtilen bir argüman kullanın)

$BOYUT(n)
gerçek boyutu ile çalışma zamanında değiştirilir adlı boyut (belirtildiği gibi
imza)

$GENEL()
işlemin çalışma zamanı tipine eşit olan C tipi ile değiştirilir

$P(a) imzada "a" adlı PDL'ye bir işaretçi erişimi. C ile arayüz oluşturmak için kullanışlıdır
fonksiyonlar

$PP(a) pdl "a"ya fiziksel bir işaretçi erişimi; esas olarak dahili kullanım için

$TXXX(Alternatif,Alternatif)
XXX'in bazı olduğu çalışma zamanı işlem türüne göre genişletme alternatifleri
"/[BSULFD+]/" ile eşleşen dize.

$PDL(a)
"a" kepçesinin pdl veri yapısına (pdl *) bir işaretçi döndür

$ISBAD(a()) (kötü)
"a()" içinde saklanan değer, bu piddle için hatalı değere eşitse true döndürür.
"HandleBad" öğesinin 1 olarak ayarlanmasını gerektirir.

$ISGOOD(a()) (kötü)
"a()" içinde saklanan değer bunun için hatalı değere eşit değilse true değerini döndürür
oyalanmak. "HandleBad" öğesinin 1 olarak ayarlanmasını gerektirir.

$SETBAD(a()) (kötü)
"a()"yı bu piddle için bozuk değere eşitleyecek şekilde ayarlar. "HandleBad" ayarının yapılmasını gerektirir
1 için.

fonksiyonlar
"döngü(DIMS) %{ ... %}"
adlandırılmış boyutlar üzerinde döngü; limitler PP tarafından otomatik olarak oluşturulur

"threadloop %{ ... %}"
aşağıdaki kodu bir iş parçacığı döngüsüne dahil et

"türler(TÜRLER) %{ ... %}"
işlem türü "TÜRLER"den herhangi biriyse aşağıdaki kodu yürütün

Ek C: fonksiyonlar ithal by PDL::PP


"PDL::PP kullandığınızda" bir dizi işlev içe aktarılır. Bunlar şunları içerir:
oluşturulan C veya XS kodunu, oluşturulan Perl kodunu kontrol eden işlevleri ve
kodun oluşturulduğu paketleri ve sembol tablolarını işleyen işlevler.

Yaratma C ve XS Kod
PDL::PP'nin ana amacı, diş açma motorunu makinenizin etrafına sarmanızı kolaylaştırmaktır.
kendi C koduna sahiptir, ancak başka şeyler de yapabilirsiniz.

pp_def
İş parçacığı motorunu C kodunuzun etrafına sarmak için kullanılır. Bu belgenin neredeyse tamamı
pp_def kullanımını tartışır.

pp_done
PDL::PP ile işinizin bittiğini ve .xs ve .pm dosyalarını oluşturması gerektiğini belirtir.
çağırdığınız diğer pp_* işlevlerine göre. Bu fonksiyon hiçbir
argümanlar.

pp_addxs
Bu, .xs dosyanıza XS kodu eklemenizi sağlar. Perl oluşturmak istiyorsanız bu kullanışlıdır.
C kodunu çağıran ancak iş parçacığını başlatamayan veya başlatmaması gereken erişilebilir işlevler
motor. XS, Perl tarafından erişilebilir C kodunu sarmak için kullanılan standart araçtır. Yapabilirsiniz
perlxs'te daha fazlasını öğrenin.

pp_add_boot
Bu işlev, XS BOOT bölümüne ilettiğiniz dizeyi ekler. BOOT bölümü
modülünüz yüklendiğinde Perl tarafından çağrılan ve aşağıdakiler için yararlı olan C kodudur.
otomatik başlatma. Perlxs'te XS ve BOOT bölümü hakkında daha fazla bilgi edinebilirsiniz.

pp_addhdr
XS dosyanıza saf-C kodu ekler. XS dosyaları, saf C kodunun
XS özelliklerinden önce gelir. Bu, bu tür C kodunu belirlemenizi sağlar.

pp_boundscheck
PDL normalde erişimlerinizin sınırlarını, bunları yapmadan önce kontrol eder. bunu çevirebilirsin
MyPackage::set_boundscheck'i ayarlayarak çalışma zamanında açık veya kapalı. Bu fonksiyon size
bu çalışma zamanı esnekliğini kaldırmak ve asla sınır kontrolü yapın. Ayrıca şunu döndürür
herhangi bir argüman olmadan çağrılırsa mevcut sınır kontrol durumu.

NOT: Diğer belgelerde sınır denetimi hakkında hiçbir şey bulamadım. o
ele alınması gerekiyor.

Yaratma Perl Kod
PDL::PP kullandığınızda içe aktarılan birçok işlev, programın içeriğini değiştirmenize izin verir.
oluşturulan .pm dosyası. pp_def ve pp_done'a ek olarak, bu işlevlerin rolü
öncelikle oluşturduğunuz .pm dosyanızın çeşitli bölümlerine kod eklemek için.

pp_addpm
Oluşturulan .pm dosyasına Perl kodunu ekler. PDL::PP aslında üç tanesinin kaydını tutar
oluşturulan kodun farklı bölümleri: Üst, Orta ve Alt. Ekleyebilirsin
Argümanın olduğu tek argüman formunu kullanarak Orta bölüme Perl kodu
Sağlamak istediğiniz Perl kodu. İki argümanlı formda, ilk argüman bir
ikinci argümanın nereye koyulacağını belirten tek bir anahtarla anonim karma,
.pm dosyasına eklemek istediğiniz dize budur. Hash bunlardan biri
üç:

{At => 'Üst'}
{At => 'Orta'}
{At => 'Bot'}

Örneğin:

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

=head1 Bazı belgeler

Bunu dosyamın ortasına yazdığımı biliyorum ama
alt.

= kes

POD

Uyarı: .pd dosyanızın ortasına, aşağıdakiler için hazırlanmış belgeler koyarsanız,
podunuzun altında, CPAN'ı iyice karıştıracaksınız. Öte yandan, eğer içinde
.pd dosyanızın ortasına, dosyanızın altına veya üstüne bir Perl kodu eklersiniz.
.pm dosyası, sadece kafa karıştırabilirsiniz. :-)

pp_beginwrap
BEGIN-blok sarma ekler. Bazı bildirimler BEGIN bloklarına sarılabilir, ancak
varsayılan davranış, böyle bir sarmaya sahip olmamaktır.

pp_addbegin
Belirttiğiniz kodun üzerinde olsa bile, .pm dosyanızın en üstüne eklenecek kodu ayarlar
"pp_addpm({At => 'Üst'}, ...)" ile. pp_addpm'den farklı olarak, bunu çağırmak ne olursa olsun üzerine yazar
daha önce oradaydı. Genel olarak, muhtemelen kullanmamalısınız.

Takip çizgi Rakamlarla
C benzeri kodunuzdan veya Perl kodunuzdan derleme hataları aldığınızda, bu yardımcı olabilir.
bu hataları, hatanın oluştuğu kaynak dosyadaki satır numaralarına geri döndürmek için
oluştu.

pp_line_numbers
Bir satır numarası ve (genellikle uzun) bir kod dizisi alır. satır numarası olmalıdır
alıntının başladığı satırı belirtin. Bu genellikle Perl'in "__LINE__" dir.
değişmez, eğer heredocs kullanmıyorsanız, bu durumda "__LINE__ + 1" olur. NS
döndürülen dize, derleyicinin hataları bildirmesine yardımcı olmak için serpiştirilmiş #line yönergelerine sahiptir
uygun satırda.

Değiştirme the sembol tablo ve İhracat Davranış
PDL::PP genellikle pp_def kullanılarak oluşturulan tüm işlevleri dışa aktarır ve genellikle bunları yükler.
PDL sembol tablosuna. Ancak, bu davranışı bu işlevlerle değiştirebilirsiniz.

pp_bless
XS kodunun eklendiği paketi (sembol tablosu) ayarlar. Varsayılan PDL'dir,
bu genellikle istediğiniz şeydir. Varsayılan kutsamayı kullanırsanız ve bir
işlev myfunc, sonra aşağıdakileri yapabilirsiniz:

$piddle->işlevim( );
PDL::myfunc($piddle, );

Öte yandan, fonksiyonlarınızı başka bir pakete kutsarsanız, çağıramazsınız.
bunları PDL yöntemleri olarak kullanmalı ve şu şekilde çağırmalıdır:

MyPackage::myfunc($piddle, );

Elbette, işlevinizi PDL sembolüne eklemek için her zaman PMFunc tuşunu kullanabilirsiniz.
tablo, ama neden bunu?

pp_add_isa
modüllerin listesine ekler. modül miras alır. Varsayılan liste

qw(PDL::İhracatçı DynaLoader)

pp_core_importlist
Oluşturduğunuz .pm dosyanızın en üstünde şuna benzeyen bir satır bulunur:

PDL::Core kullanın;

Bunu, pp_core_importlist'e bir dize belirterek değiştirebilirsiniz. Örneğin,

pp_core_importlist('::Blarg');

sonuçlanacak

PDL::Core::Blarg'ı kullanın;

Bunu, örneğin, PDL::Core'dan içe aktarılacak bir sembol listesi eklemek için kullanabilirsiniz. İçin
örnek:

pp_core_importlist("':Dahili'");

aşağıdaki kullanım ifadesine yol açacaktır:

PDL::Core ':Internal' kullanın;

pp_setversion
Modülünüzün sürümünü ayarlar. Sürüm, .xs ve .pm arasında tutarlı olmalıdır
dosyasıdır ve Perl kitaplıklarınızın sürümden etkilenmemesini sağlamak için kullanılır.
eğmek.

pp_add_exported
Verdiğiniz adları ne olursa olsun dışa aktarma listesine ekler. pp_def kullanılarak oluşturulan işlevler
otomatik olarak listeye eklenir. Bu işlev, herhangi bir Perl tanımlarsanız kullanışlıdır.
dışa aktarmak istediğiniz pp_addpm veya pp_addxs kullanan işlevler.

pp_export_nothing
Bu, dışa aktarılan sembollerin listesini sıfırlar. Bu muhtemelen daha iyi denir
"pp_export_clear", aramadan sonra dışa aktarılan sembolleri ekleyebileceğiniz için
"pp_export_hiçbir şey". pp_done çağrılmadan hemen önce çağrıldığında, bu,
modül hiçbir şeyi dışa aktarmaz, örneğin, yalnızca programcıların
yöntemler olarak işlev görür.

onworks.net hizmetlerini kullanarak çevrimiçi olarak PDL::PPp kullanın


Ücretsiz Sunucular ve İş İstasyonları

Windows ve Linux uygulamalarını indirin

  • 1
    paket dosya yöneticisi
    paket dosya yöneticisi
    Bu, Total War paketi dosya yöneticisidir.
    proje, sürüm 1.7'den başlayarak. A
    Warscape'e kısa bir giriş
    modlama: ...
    packfilemanager'ı indirin
  • 2
    IPerf2
    IPerf2
    Ölçmek için bir ağ trafiği aracı
    Metriklerle TCP ve UDP performansı
    hem verim hem de gecikme süresi civarında. NS
    hedefler aktif bir şekilde sürdürmeyi içerir
    iperf kodu...
    IPerf2'yi indirin
  • 3
    fre:ac - ücretsiz ses dönüştürücü
    fre:ac - ücretsiz ses dönüştürücü
    fre:ac ücretsiz bir ses dönüştürücü ve CD'dir
    çeşitli formatlar ve kodlayıcılar için ripper.
    MP3, MP4/M4A, WMA, Ogg özelliklerine sahiptir
    Vorbis, FLAC, AAC ve Bonk biçimi
    destek, ...
    fre:ac indir - ücretsiz ses dönüştürücü
  • 4
    matplotlib
    matplotlib
    Matplotlib kapsamlı bir kütüphanedir
    statik, hareketli ve
    Python'da etkileşimli görselleştirmeler.
    Matplotlib kolay şeyleri kolaylaştırır ve
    zor şey...
    Matplotlib'i indirin
  • 5
    Bot Adam
    Bot Adam
    Chatbot mantığınızı bir kez yazın ve
    mevcut olanlardan birine bağlayın
    Amazon dahil mesajlaşma servisleri
    Alexa, Facebook Messenger, Slack,
    Telgraf, hatta sen...
    BotMan'i indirin
  • 6
    Joplin
    Joplin
    Joplin ücretsiz ve açık bir kaynaktır
    not alma ve yapılacaklar uygulaması
    çok sayıda notu işleyebilir
    Markdown formatı, bunları organize edin
    defterler ve...
    İndir Joplin
  • Daha fazla »

Linux komutları

Ad