Genişletme/Ekleme SSS
*********************


C'de kendi fonksiyonlarımı oluşturabilir miyim?
===============================================

Evet, C'de fonksiyonlar, değişkenler, istisnalar ve hatta yeni tipler
içeren yerleşik modüller oluşturabilirsiniz. Bu konu Python
Yorumlayıcısını Genişletme ve Gömme dosyasında açıklanmıştır.

Çoğu orta veya ileri seviye Python kitabı da bu konuyu ele alacaktır.


C++'da kendi fonksiyonlarımı oluşturabilir miyim?
=================================================

Evet, C++'da bulunan C uyumluluk özelliklerini kullanarak.  "extern
"C" { ... }" komutunu Python include dosyalarının etrafına yerleştirin
ve Python yorumlayıcısı tarafından çağrılacak her fonksiyonun önüne
"extern "C"" koyun. Yapıcıları olan global veya statik C++ nesneleri
muhtemelen iyi bir fikir değildir.


C yazmak zor; başka alternatifler var mı?
=========================================

Ne yapmaya çalıştığınıza bağlı olarak, kendi C uzantılarınızı yazmanın
bir dizi alternatifi vardır.

Cython and its relative Pyrex are compilers that accept a slightly
modified form of Python and generate the corresponding C code.  Cython
and Pyrex make it possible to write an extension without having to
learn Python's C API.

If you need to interface to some C or C++ library for which no Python
extension currently exists, you can try wrapping the library's data
types and functions with a tool such as SWIG.  SIP, CXX Boost, or
Weave are also alternatives for wrapping C++ libraries.


C'den rastgele Python komutlarını nasıl çalıştırabilirim?
=========================================================

Bunu yapan en üst düzey fonksiyon "PyRun_SimpleString()" olup,
"__main__" modülü bağlamında çalıştırılmak üzere tek bir string
argüman alır ve başarı için "0", bir istisna oluştuğunda
("SyntaxError" dahil) "-1" döndürür.  Daha fazla kontrol istiyorsanız,
"PyRun_String()" kullanın; "PyRun_SimpleString()" için
"Python/pythonrun.c" içindeki kaynağa bakın.


C'den rastgele Python komutlarını nasıl değerlendirebilirim?
============================================================

Önceki sorudaki "PyRun_String()" fonksiyonunu "Py_eval_input"
başlangıç sembolü ile çağırın; bu fonksiyon bir ifadeyi ayrıştırır,
değerlendirir ve değerini döndürür.


Bir Python nesnesinden C değerlerini nasıl çıkarabilirim?
=========================================================

That depends on the object's type.  If it's a tuple, "PyTuple_Size()"
returns its length and "PyTuple_GetItem()" returns the item at a
specified index.  Lists have similar functions, "PyList_Size()" and
"PyList_GetItem()".

For bytes, "PyBytes_Size()" returns its length and
"PyBytes_AsStringAndSize()" provides a pointer to its value and its
length.  Note that Python bytes objects may contain null bytes so C's
"strlen()" should not be used.

Bir nesnenin türünü test etmek için, önce "NULL" olmadığından emin
olun ve ardından "PyBytes_Check()", "PyTuple_Check()",
"PyList_Check()" vb. kullanın.

Ayrıca Python nesneleri için 'abstract' arayüzü tarafından sağlanan
üst düzey bir API de vardır -- daha fazla ayrıntı için
"Include/abstract.h" dosyasını okuyun.  "PySequence_Length()",
"PySequence_GetItem()", vb. gibi çağrıları kullanarak her türlü Python
dizisi ile arayüz oluşturmanın yanı sıra sayılar ("PyNumber_Index()"
ve diğerleri) ve PyMapping API'lerindeki eşlemeler gibi diğer birçok
yararlı protokolü de sağlar.


İsteğe bağlı uzunlukta bir tuple oluşturmak için Py_BuildValue() işlevini nasıl kullanabilirim?
===============================================================================================

Bunu yapamazsınız.  Bunun yerine "PyTuple_Pack()" kullanın.


C'de bir nesnenin metodunu nasıl çağırabilirim?
===============================================

"PyObject_CallMethod()" fonksiyonu, bir nesnenin rastgele bir metodunu
çağırmak için kullanılabilir.  Parametreler nesne, çağrılacak yöntemin
adı, "Py_BuildValue()" ile kullanılan gibi bir string ve değişken
değerleridir:

   PyObject *
   PyObject_CallMethod(PyObject *object, const char *method_name,
                       const char *arg_format, ...);

Bu, ister yerleşik ister kullanıcı tanımlı olsun, yöntemleri olan
herhangi bir nesne için geçerlidir. Sonunda dönüş değerini
:"Py_DECREF()"'lemekten siz sorumlusunuz.

Örneğin, bir dosya nesnesinin "seek" yöntemini 10, 0 argümanlarıyla
çağırmak için (dosya nesnesi işaretçisinin "f" olduğunu varsayarak):

   res = PyObject_CallMethod(f, "seek", "(ii)", 10, 0);
   if (res == NULL) {
           ... an exception occurred ...
   }
   else {
           Py_DECREF(res);
   }

"PyObject_CallObject()" *her zaman* argüman listesi için bir tuple
istediğinden, argümansız bir fonksiyon çağırmak için format olarak
"()" ve tek argümanlı bir fonksiyon çağırmak için argümanı parantez
içine alın, örneğin "(i)".


PyErr_Print() işlevinden (veya stdout/stderr'e yazdıran herhangi bir şeyden) gelen çıktıyı nasıl yakalayabilirim?
=================================================================================================================

Python kodunda, "write()" metodunu destekleyen bir nesne tanımlayın.
Bu nesneyi "sys.stdout" ve "sys.stderr" öğelerine atayın.
Print_error'ı çağırın ya da sadece standart geri izleme mekanizmasının
çalışmasına izin verin. Ardından, çıktı "write()" yönteminizin
gönderdiği yere gidecektir.

Bunu yapmanın en kolay yolu "io.StringIO" sınıfını kullanmaktır:

   >>> import io, sys
   >>> sys.stdout = io.StringIO()
   >>> print('foo')
   >>> print('hello world!')
   >>> sys.stderr.write(sys.stdout.getvalue())
   foo
   hello world!

Aynı şeyi yapan özel bir nesne şöyle görünecektir:

   >>> import io, sys
   >>> class StdoutCatcher(io.TextIOBase):
   ...     def __init__(self):
   ...         self.data = []
   ...     def write(self, stuff):
   ...         self.data.append(stuff)
   ...
   >>> import sys
   >>> sys.stdout = StdoutCatcher()
   >>> print('foo')
   >>> print('hello world!')
   >>> sys.stderr.write(''.join(sys.stdout.data))
   foo
   hello world!


Python'da yazılmış bir modüle C'den nasıl erişebilirim?
=======================================================

Modül nesnesine aşağıdaki gibi bir işaretçi alabilirsiniz:

   module = PyImport_ImportModule("<modulename>");

Modül henüz içe aktarılmamışsa (yani "sys.modules" içinde henüz mevcut
değilse), bu modülü başlatır; aksi takdirde sadece
"sys.modules["<modulename>"]" değerini döndürür. Modülü herhangi bir
isim alanına girmediğine dikkat edin -- sadece başlatıldığından ve
"sys.modules" içinde saklandığından emin olur.

Daha sonra modülün özniteliklerine (yani modülde tanımlanan herhangi
bir isme) aşağıdaki şekilde erişebilirsiniz:

   attr = PyObject_GetAttrString(module, "<attrname>");

Modüldeki değişkenlere atamak için "PyObject_SetAttrString()" çağrısı
da çalışır.


Python'dan C++ nesnelerine nasıl arayüz oluşturabilirim?
========================================================

Gereksinimlerinize bağlı olarak, birçok yaklaşım vardır.  Bunu manuel
olarak yapmak için the "Extending and Embedding" belgesini okuyarak
başlayın.  Python çalışma zamanı sistemi için, C ve C++ arasında çok
fazla fark olmadığının farkına varın -- bu nedenle bir C yapı
(işaretçi) türü etrafında yeni bir Python türü oluşturma stratejisi
C++ nesneleri için de işe yarayacaktır.

C++ kütüphaneleri için bakınız C yazmak zor; başka alternatifler var
mı?.


Kurulum dosyasını kullanarak bir modül ekledim ve derleme başarısız oldu; neden?
================================================================================

Kurulum bir satır sonu ile bitmelidir, eğer satır sonu yoksa derleme
işlemi başarısız olur.  (Bunu düzeltmek için biraz biçimsiz shell
script düzenlemesi gerekir ve bu hata o kadar küçük ki çabaya değmez
gibi görünüyor)


Bir uzantıda nasıl hata ayıklayabilirim?
========================================

Dinamik olarak yüklenen uzantılarla GDB kullanırken, uzantınız
yüklenene kadar uzantınızda bir kesme noktası ayarlayamazsınız.

".gdbinit" dosyanıza (veya etkileşimli olarak) şu komutu ekleyin:

   br _PyImport_LoadDynamicModule

Sonra, GDB'yi çalıştırdığınızda:

   $ gdb /local/bin/python
   gdb) run myscript.py
   gdb) continue # repeat until your extension is loaded
   gdb) finish   # so that your extension is loaded
   gdb) br myfunction.c:50
   gdb) continue


Linux sistemimde bir Python modülü derlemek istiyorum, ancak bazı dosyalar eksik. Neden?
========================================================================================

Most packaged versions of Python omit some files required for
compiling Python extensions.

For Red Hat, install the python3-devel RPM to get the necessary files.

For Debian, run "apt-get install python3-dev".


"Eksik girdi" ile "geçersiz girdi'yi nasıl ayırt edebilirim?
============================================================

Bazen Python etkileşimli yorumlayıcısının davranışını taklit etmek
istersiniz; girdi eksik olduğunda size bir devam istemi verir
(örneğin, bir "if" deyiminin başlangıcını yazdınız veya
parantezlerinizi veya üçlü dize tırnaklarınızı kapatmadınız), ancak
girdi geçersiz olduğunda size hemen bir sözdizimi hata mesajı verir.

Python'da, ayrıştırıcının davranışına yeterince yaklaşan "codeop"
modülünü kullanabilirsiniz.  Örneğin IDLE bunu kullanır.

Bunu C'de yapmanın en kolay yolu "PyRun_InteractiveLoop()" çağırmak
(belki ayrı bir iş parçacığında) ve Python yorumlayıcısının girdiyi
sizin için işlemesine izin vermektir. Ayrıca
"PyOS_ReadlineFunctionPointer()" 'ı özel girdi fonksiyonunuza işaret
edecek şekilde ayarlayabilirsiniz. Daha fazla ipucu için
"Modules/readline.c" ve "Parser/myreadline.c" dosyalarına bakın.


Tanımlanmamış g++ sembolleri __builtin_new veya __pure_virtual'ı nasıl bulabilirim?
===================================================================================

G++ uzantı modüllerini dinamik olarak yüklemek için Python'u yeniden
derlemeli, g++ kullanarak yeniden bağlamalı (Python Modules
Makefile'da LINKCC'yi değiştirin) ve uzantı modülünüzü g++ kullanarak
bağlamalısınız (örneğin, "g++ -shared -o mymodule.so mymodule.o").


Bazı yöntemleri C'de, bazı yöntemleri Python'da (örneğin miras yoluyla) uygulanan bir nesne sınıfı oluşturabilir miyim?
=======================================================================================================================

Evet, "int", "list", "dict", vb. gibi yerleşik sınıflardan miras
alabilirsiniz.

Boost Python Kütüphanesi (BPL,
http://www.boost.org/libs/python/doc/index.html) bunu C++'dan yapmanın
bir yolunu sağlar (yani BPL'yi kullanarak C++'da yazılmış bir uzantı
sınıfından miras alabilirsiniz).
