Yardım std::string verisinin garip davranışı

  • Konuyu açan Konuyu açan Kaiser
  • Açılış Tarihi Açılış Tarihi
  • Yanıt Yanıt 4
  • Gösterim Gösterim 149
Konu sahibi bu konuda soru soruyor. Sorusu ile ilgili bilgisi olanların yanıtlamasını bekliyor.

Kaiser

Admin
Admin
Geliştirici
Yardımsever Üye
Mesaj
3.950
Çözümler
381
Beğeni
3.997
Puan
1.849
Ticaret Puanı
0
Merhabalar, uzun uzun uğraşıp araştırmalar yaptım ancak bu konuda bir çözüme ulaşamadığım için sizlere sormak istedim.
Kısaca sorunumdan bahsedeyim; header dosyasında bir vector oluşturup, içerisinde Türkçe karakter vb. barındıran std::string elemanlarını, .cpp içindeki fonksiyon aracılığı ile çekip Python'a gönderdiğim zaman karakterler bozuluyor.

Ancak; .cpp ve fonksiyon içinde statik olarak std::string tanımlayıp doğrudan Pythona gönderdiğimde sorunsuz olarak çalışıyor ve görüntüleniyor.

Örneğin(.cpp):
C++:
Genişlet Daralt Kopyala
std::string arg = "İĞŞÜ"
Py_BuildValue("s", arg.c_str());
Bu şekilde kullandığımda herhangi bir sorun yok.

Ancak(.h içinden çekerken)
C++:
Genişlet Daralt Kopyala
for (const auto& pair : args) // args = .h den çekilen vectorun 2.dizi elemanı.
{
    if (pair.first == arg)
    {
        Py_BuildValue("s", pair.second.c_str());
    }
}
Bu kullanımda Türkçe karakterler bozuluyor. Aklıma gelen bütün kontrolleri ve analizleri gerçekleştirdim. Olayı daha ilginç kılan 2 faktör fark ettim.
1-) İkinci kullanımda aynı zamanda TraceError ile veriyi yazdırırsam sorunsuz yazılıyor ama Python'da bozuk görünüyor.
2-) Her iki kullanımda da Python'a gönderilen verinin byte değerlerini gözden geçirdim. Ve bu sonuç kafamı iyice karıştırdı.

Her iki yöntemde de Python'a gönderilen verinin byte değerleri:
0xC4 -- 0xB0 -> İ
0xC4 -- 0x9E -> Ğ
0xC5 -- 0x9E -> Ş
0xC3 -- 0x9C -> Ü

Yani hiçbir fark yok.

Buna rağmen ikinci kullanımda karakterler bozuluyor. std::string'i güncelleyip std::u8string ile zorladım ama bir faydası olmadı.
Son olarak .cpp ve .h dosyaları zaten UTF-8 kodlamasına sahip.

Belki atladığım bir şey vardır, emin değilim. Tüm fikirlere açığım.
 
sorunun türkçe karakterden değil lifetime'dan olduğunu düşünüyorum, vectordeki verileri listelerken referans kullanmadan deneyin. Ek olarak birden fazla Py_BuildValue döndürüp python tarafında kullanamazsınız, göndereceğiniz verileri c++ tarafında liste haline getirip onu aktarmanız gerekiyor
 
sorunun türkçe karakterden değil lifetime'dan olduğunu düşünüyorum, vectordeki verileri listelerken referans kullanmadan deneyin. Ek olarak birden fazla Py_BuildValue döndürüp python tarafında kullanamazsınız, göndereceğiniz verileri c++ tarafında liste haline getirip onu aktarmanız gerekiyor
Py_BuildValue belirli bir koşula göre çalışıyor, döngünün olması sizi yanıltmasın. Peş peşe çalışan bir kod yapısı değil.

İki yöntemi de az önce denedim ama maalesef sonuç yine aynı. İlk olarak döngüden gelen verileri bir listte bekletip daha sonrasında pythona gönderdim. Sonuç aynı...
Ve bunu yaparken yine TraceError ile kontrol sağladım. Listede biriktirilen veriler TraceError'da sorunsuz görünüyor, ancak pythona geçince bozuk görünüyor.

Son olarak her ne kadar saçma olsa da verinin vektörden çıkarken/çekilirken bozulma veya değişime uğrama ihtimalini de düşündüm ve pythona gönderme işlemi yapmadan pair.second verisini yazdırdığımda sorunsuz olarak çıktığı görülüyor. Daha ne deneyebilirim hiç bilmiyorum, ihtimal kalmadı neredeyse...
 
Ne zaman "ihtimal kalmadı neredeyse" kısmına kafa olarak yaklaşsam yapay zekayla uzun bir istiraşe yaparım, çoğunlukla saçmalasa bile arada çözüme götürdüğü oluyor, yapay zekaya kendin sordun mu bilmiyorum fakat şöyle tahminleri var belki işine yarar:



Türkçe karakterlerin bozulması sorunu, C++ ve Python arasındaki veri aktarımında karşılaşılabilecek yaygın bir karakter kodlama problemidir. Sorunun kaynağı genellikle std::string'in ve Python'un bu karakterleri nasıl işlediği ile ilgilidir. Statik olarak tanımlanan stringlerde sorun yaşanmaması, bellekte bu stringlerin nasıl tutulduğuyla ilgilidir.

İki farklı durumda std::string veri türü üzerinden veri aktarımı yapılırken, bellekteki veri tam olarak aynı olsa bile Python'a aktarılırken farklı şekillerde işlenebilir. Bu durumun birkaç olası nedeni olabilir:

  • Verinin Bellekte Farklı Yerlere Yazılması: Dinamik olarak oluşturulan ve bir vector içinde saklanan stringler bellekte farklı yerlere yazılır ve bu, karakterlerin farklı yorumlanmasına neden olabilir. Bu durumda, stringin sonuna yanlışlıkla eklenen bir NULL karakteri ya da bellekte başka bir yerde bulunan geçersiz veri sorun yaratabilir.
  • Kodlama Sorunu: std::string'in bellekteki kodlaması UTF-8 olsa bile, Python'a aktarılırken bu stringin doğru şekilde kodlandığından emin olunması gerekir. Python'da bu tür durumlarda PyUnicode_FromString fonksiyonu kullanılarak stringin doğru şekilde kodlanmış bir Unicode objesi olarak aktarılmasını sağlamak genellikle daha iyi sonuç verir.

C++:
Genişlet Daralt Kopyala
PyObject* unicodeString = PyUnicode_FromString(pair.second.c_str());

  • Bellek Yönetimi: Vektörden çekilen stringlerin yaşam süresiyle ilgili sorunlar yaşanabilir. Vektördeki stringler, bellekteki orijinal konumlarını kaybedebilir ve bu da bozulmalara neden olabilir. Bunun üstesinden gelmek için std::string yerine std::wstring veya std::u16string gibi geniş karakter stringleri kullanılabilir ve ardından Python tarafına uygun bir dönüşüm yapılabilir.

Öneri:​

C++ kodunuza şu şekilde bir yaklaşım ekleyebilirsiniz:

C++:
Genişlet Daralt Kopyala
PyObject* unicodeString = PyUnicode_DecodeUTF8(pair.second.c_str(), pair.second.size(), "strict");

Bu, stringin doğru şekilde UTF-8 olarak çözümlenmesini sağlar ve Python'a doğru bir Unicode nesnesi gönderir. Bellekte dinamik olarak oluşturulan ve saklanan verilerle ilgili sorunları ortadan kaldırmak için her zaman karakter kodlamasını açıkça belirtmek iyi bir uygulamadır.

Bu yöntemle, karakterlerin doğru şekilde Python'a aktarılmasını sağlayabilirsiniz.
 
Ne zaman "ihtimal kalmadı neredeyse" kısmına kafa olarak yaklaşsam yapay zekayla uzun bir istiraşe yaparım, çoğunlukla saçmalasa bile arada çözüme götürdüğü oluyor, yapay zekaya kendin sordun mu bilmiyorum fakat şöyle tahminleri var belki işine yarar:



Türkçe karakterlerin bozulması sorunu, C++ ve Python arasındaki veri aktarımında karşılaşılabilecek yaygın bir karakter kodlama problemidir. Sorunun kaynağı genellikle std::string'in ve Python'un bu karakterleri nasıl işlediği ile ilgilidir. Statik olarak tanımlanan stringlerde sorun yaşanmaması, bellekte bu stringlerin nasıl tutulduğuyla ilgilidir.

İki farklı durumda std::string veri türü üzerinden veri aktarımı yapılırken, bellekteki veri tam olarak aynı olsa bile Python'a aktarılırken farklı şekillerde işlenebilir. Bu durumun birkaç olası nedeni olabilir:

  • Verinin Bellekte Farklı Yerlere Yazılması: Dinamik olarak oluşturulan ve bir vector içinde saklanan stringler bellekte farklı yerlere yazılır ve bu, karakterlerin farklı yorumlanmasına neden olabilir. Bu durumda, stringin sonuna yanlışlıkla eklenen bir NULL karakteri ya da bellekte başka bir yerde bulunan geçersiz veri sorun yaratabilir.
  • Kodlama Sorunu: std::string'in bellekteki kodlaması UTF-8 olsa bile, Python'a aktarılırken bu stringin doğru şekilde kodlandığından emin olunması gerekir. Python'da bu tür durumlarda PyUnicode_FromString fonksiyonu kullanılarak stringin doğru şekilde kodlanmış bir Unicode objesi olarak aktarılmasını sağlamak genellikle daha iyi sonuç verir.

C++:
Genişlet Daralt Kopyala
PyObject* unicodeString = PyUnicode_FromString(pair.second.c_str());

  • Bellek Yönetimi: Vektörden çekilen stringlerin yaşam süresiyle ilgili sorunlar yaşanabilir. Vektördeki stringler, bellekteki orijinal konumlarını kaybedebilir ve bu da bozulmalara neden olabilir. Bunun üstesinden gelmek için std::string yerine std::wstring veya std::u16string gibi geniş karakter stringleri kullanılabilir ve ardından Python tarafına uygun bir dönüşüm yapılabilir.

Öneri:​

C++ kodunuza şu şekilde bir yaklaşım ekleyebilirsiniz:

C++:
Genişlet Daralt Kopyala
PyObject* unicodeString = PyUnicode_DecodeUTF8(pair.second.c_str(), pair.second.size(), "strict");

Bu, stringin doğru şekilde UTF-8 olarak çözümlenmesini sağlar ve Python'a doğru bir Unicode nesnesi gönderir. Bellekte dinamik olarak oluşturulan ve saklanan verilerle ilgili sorunları ortadan kaldırmak için her zaman karakter kodlamasını açıkça belirtmek iyi bir uygulamadır.

Bu yöntemle, karakterlerin doğru şekilde Python'a aktarılmasını sağlayabilirsiniz.
Evet ben de bu noktaya gelene kadar yapay zeka ile uzun uzun konuştum. Ancak belirli bir noktadan sonra aynı şeyleri söyleme başladı ve neredeyse önerdiği her şeyi denedim. Burada yazılanlar da dahil. PyUnicode_DecodeUTF8 ve PyUnicode_FromString gibi araçları kullandığımda nedense gönderdiğim veri hiç görünmez bir hale geliyor. Bozuk bir şekilde bile göstermiyor.

Projenin yapılandırma ayarlarında "Çok baytlı karakter kümesi" seçeneği seçili. Bunu Unicode olarak değiştirip deneyecektim ama daha sonra bunun anlamsız olduğunu fark ettim çünkü src içinde evrim sistemine ait Türkçe etiketler mevcut ve onlar zaten sorunsuz çalışıyor.
Ama oradaki çalışma mantığı konuda belirttiğim ilk yöntem gibi. Statik olarak tanımlandığı için sorunsuz çalışıyor ve Py_BuildValue bunu sorunsuz bir şekilde işliyor. Benim durumumda da Py_BuildValue çalışıyor, ama sadece statik olarak.
Ancak nedense bir vector veya dizi içinden çekince aynı byte değerine sahip olsa bile bozuk görünüyor. Ek olarak buf kullanmayı denedim ama sonuç yine değişmedi.
 
Üst