2008-10-17 26 views
7

Bir C programına bir Python yorumlayıcısını yerleştirdim. C programının bir bayttan bir diziden bir char dizisine okunduğunu ve baytların belirli bir kodlamayla (örn. ISO 8859-1, Windows-1252 veya UTF-8) metinleri temsil ettiğini (bir şekilde) öğrenir. Bu char dizininin içeriğini bir Python dizesine nasıl çözebilirim?Dizede ASCII olmayan karakterler olduğunda bir C dizesini (karakter dizisi) bir Python dizesine dönüştürme işlemi nasıl yapılır?

Python dizesi genel olarak unicode türünde olmalıdır; örneğin, Windows-1252 kodlu girişindeki 0x93, u'\u0201c' haline gelir.

PyString_Decode'u kullanmayı denedim, ancak dizede ASCII olmayan karakterler olduğunda her zaman başarısız oluyor.

#include <Python.h> 
#include <stdio.h> 

int main(int argc, char *argv[]) 
{ 
    char c_string[] = { (char)0x93, 0 }; 
    PyObject *py_string; 

    Py_Initialize(); 

    py_string = PyString_Decode(c_string, 1, "windows_1252", "replace"); 
    if (!py_string) { 
      PyErr_Print(); 
      return 1; 
    } 
    return 0; 
} 

hata mesajı biz PyString_Decode çağrısında windows_1252 belirtmek olsa ascii kodlama bile kullanıldığını gösterir ki, UnicodeEncodeError: 'ascii' codec can't encode character u'\u201c' in position 0: ordinal not in range(128) geçerli: Burada başarısız bir örnektir. Bir Unicode gösterimi dizesi deşifre etmek istemiyorum

#include <Python.h> 
#include <stdio.h> 

int main(int argc, char *argv[]) 
{ 
    char c_string[] = { (char)0x93, 0 }; 
    PyObject *raw, *decoded; 

    Py_Initialize(); 

    raw = PyString_FromString(c_string); 
    printf("Undecoded: "); 
    PyObject_Print(raw, stdout, 0); 
    printf("\n"); 
    decoded = PyObject_CallMethod(raw, "decode", "s", "windows_1252"); 
    Py_DECREF(raw); 
    printf("Decoded: "); 
    PyObject_Print(decoded, stdout, 0); 
    printf("\n"); 
    return 0; 
} 
+0

Niteliği almak için, bir C dizesi bir char [] değil, char * –

+1

Nitelemek için, bir değere başvururken önemli değildir. Diziler zaten işlevlere işaretçi olarak geçirilir. – gnud

cevap

6

PyString_Decode yapar. Buradaki problem PyString_AsDecodedObject yerine PyString_AsDecodedString'den kaynaklanmaktadır. PyString_AsDecodedString PyString_AsDecodedObject yapar, ancak sonuçta oluşan unicode nesneyi varsayılan kodlamayla (sizin için ASCII gibi görünüyor) bir string nesnesine dönüştürmeyi dener. Başarısız olduğu yer burası.

İki çağrı yapmanız gerektiğine inanıyorum - ancak python "decode" yöntemini çağırmak yerine PyString_AsDecodedObject öğesini kullanabilirsiniz. Bu şekilde çalışan PyString_Decode arkasındaki mantık nedir tamamen emin değilim

#include <Python.h> 
#include <stdio.h> 

int main(int argc, char *argv[]) 
{ 
    char c_string[] = { (char)0x93, 0 }; 
    PyObject *py_string, *py_unicode; 

    Py_Initialize(); 

    py_string = PyString_FromStringAndSize(c_string, 1); 
    if (!py_string) { 
      PyErr_Print(); 
      return 1; 
    } 
    py_unicode = PyString_AsDecodedObject(py_string, "windows_1252", "replace"); 
    Py_DECREF(py_string); 

    return 0; 
} 

: gibi bir şey. very old thread on python-dev, çıktıyı zincirleme ile ilgili bir şey olduğunu belirtiyor gibi görünüyor, ancak Python yöntemleri aynı şeyi yapmadığından, hala ilgili olup olmadığından emin değilim.

+0

Opps! Teşekkürler Ljosa; sabit. Python3 için –

+0

https://docs.python.org/3.5/c-api/unicode.html#c.PyUnicode_FromString – crizCraig

3

:

Aşağıdaki kod onun decode yöntemini sonra, şifresi çözülmemiş bayt Python dize oluşturmak için PyString_FromString kullanarak arayarak sorunu çalışır Sadece bir bayt dizisi olarak davranmak istiyorsun, değil mi?

Sadece PyString_FromString kullanın: hepsi

char *cstring; 
PyObject *pystring = PyString_FromString(cstring); 

. Artık bir Python str() nesnesine sahipsiniz. Bkz. Buradaki dokümanlar: https://docs.python.org/2/c-api/string.html

"str" ​​veya "unicode" ifadelerinin nasıl belirtileceği konusunda biraz kafam karışık. ASCII olmayan karakterleriniz varsa bunlar oldukça farklıdır. Bir C dizgisi ve kodunu çözmek istiyorsanız, tam olarak hangi karakter kümesinin bulunduğunu biliyorsanız, o zaman PyString_DecodeString başlamak için iyi bir yerdir.

+0

Aslında bunu çözmek istiyorum, bu yüzden Python kodunun dize kullanılarak bittiği her şeyin kodunun orijinal olarak nasıl kodlandığını bilmesi gerekmiyor (C programına girişte). Belirsiz olduğumu işaret ettiğin için teşekkürler. Sorumu düzenledim. –

2

"if (!py_string)" ifadesinde PyErr_Print() numaralı telefonu aramayı deneyin. Belki de python istisnası size biraz daha bilgi verecektir. bir dizeye dönüştürür, sonra da Dize kodu -

PyObject *PyString_Decode(const char *s, 
       Py_ssize_t size, 
       const char *encoding, 
       const char *errors) 
{ 
    PyObject *v, *str; 

    str = PyString_FromStringAndSize(s, size); 
    if (str == NULL) 
    return NULL; 
    v = PyString_AsDecodedString(str, encoding, errors); 
    Py_DECREF(str); 
    return v; 
} 

IOW, ne sizin ikinci örnekteki yapıyoruz temelde yapar:

+0

Teşekkürler, bilgiyi soruya dahil ettim ve dahil ettim. –

+0

Sorun değil. Tavsiye yardımcı olsaydı, bir bağış takdir ediyorum. :-) –

İlgili konular