SWIG ile güzelce çalışan küçük bir projem var. Özellikle, bazı işlevlerim Python'da tuplelere çevrilen std::vector
s döndürüyor. Şimdi, çok sayıda sayısal yapıyorum, bu yüzden sadece SWIG bunları C++ kodundan döndükten sonra numpy dizilerine dönüştürüyor. Bunu yapmak için, SWIG'de aşağıdaki gibi bir şey kullanırım.SWIG'in yeni yerleşik özelliği ile pythonappend'i kullanmanın bir yolu var mı?
%feature("pythonappend") My::Cool::Namespace::Data() const %{ if isinstance(val, tuple) : val = numpy.array(val) %}
(Aslında val
aslında bir tanımlama grubu olup olmadığını kontrol neden olan, yüzen dönüş bazıları Veri olarak adlandırılan bir kaç fonksiyonları vardır.) Bu sadece güzel çalışıyor.
Ayrıca, şu anda mevcut olan -builtin
bayrağını kullanmak istiyorum. Bu Veri işlevlerine yapılan çağrılar nadirdir ve çoğunlukla etkileşimlidir, bu nedenle yavaşlıkları bir sorun değildir, ancak yerleşik seçenekle önemli ölçüde hızlanan başka yavaş döngüler de vardır.
Sorun şu ki, bu bayrağı kullandığımda, pythonappend özelliği sessizce yok sayılır. Şimdi, Data tekrar bir tuple döndürüyor. Uyuşmuş dizileri geri döndürmenin bir yolu var mı? Tipemaps kullanmayı denedim, ama dev bir karmaşaya dönüştü.
Düzenleme: Borealid çok güzel soruya cevap vardır
. Sadece tamlık için, ihtiyacım olan bir çift ile ilgili ama çok farklı tiplemeler ekledim çünkü const referansı ile dönüyorum ve vektörlerin vektörlerini kullanıyorum (başlama!). Bunlar, kimsenin küçük farklılıkları anlamaya çalışmasını istemeyecek kadar farklı.
%typemap(out) std::vector<int>& {
npy_intp result_size = $1->size();
npy_intp dims[1] = { result_size };
PyArrayObject* npy_arr = (PyArrayObject*)PyArray_SimpleNew(1, dims, NPY_INT);
int* dat = (int*) PyArray_DATA(npy_arr);
for (size_t i = 0; i < result_size; ++i) { dat[i] = (*$1)[i]; }
$result = PyArray_Return(npy_arr);
}
%typemap(out) std::vector<std::vector<int> >& {
npy_intp result_size = $1->size();
npy_intp result_size2 = (result_size>0 ? (*$1)[0].size() : 0);
npy_intp dims[2] = { result_size, result_size2 };
PyArrayObject* npy_arr = (PyArrayObject*)PyArray_SimpleNew(2, dims, NPY_INT);
int* dat = (int*) PyArray_DATA(npy_arr);
for (size_t i = 0; i < result_size; ++i) { for (size_t j = 0; j < result_size2; ++j) { dat[i*result_size2+j] = (*$1)[i][j]; } }
$result = PyArray_Return(npy_arr);
}
Düzenleme 2:
Ben benzer sorunlar Monk yaklaşımı (explained here) @ kullanılarak çözülebilir, aradığı oldukça ne rağmen.
Bunu, tipik bir şekilde pythonappend'in normal olarak yerleştirildiği kodu kaldırdığı için, bir yazım haritası yazmadan ve C tarafında yapmadan yapabileceğinizi sanmıyorum. -builtin'in çok daha hızlı olduğundan emin misiniz (yani, profil kullanmanız sizi yönlendirdi mi?). İki modülü kullanmak için cazip olmalıyım. – Flexo
'-builtin' pythonappend'i göz ardı ettiğine dair bir uyarı olmadığına şaşırdım. Ben std :: vector's numm dizileri içine typemapping meydan okuma için değilim. Profil yaptım ve arayüzümdeki en sinir bozucu döngüyü önemli ölçüde hızlandırdı (ara vermek için yeterince uzun değil; sık beklemek için çok uzun). Ama aynı zamanda bu döngüyü C++ koduma taşıyabildiğimi fark ettim - biraz garip olsa da. Yani ben böyle giderim. Yine de, 'iki modül' öneriniz ilginç ve diğer durumlarda yararlı olabilir. – Mike
SWIG ile -Wall'ı aradınız mı? Bu davada uyarılacağını düşündüm. – Flexo