2016-03-18 13 views
1

Ich habe ein PyUnicode-Objekt Ich versuche, zurück in eine C-Zeichenfolge (char *) zu konvertieren.Wie funktioniert String-Konvertierung zwischen PyUnicode String und C String?

Die Art, wie ich es versuche, scheint nicht zu funktionieren. Hier ist mein Code:

PyObject * objectCompName = PyTuple_GET_ITEM(compTuple, (Py_ssize_t) 0); 
PyObject * ooCompName = PyUnicode_AsASCIIString(objectCompName); 
char * compName = PyBytes_AsString(ooCompName); 
Py_DECREF(ooCompName); 

Gibt es einen anderen/besseren Weg, ich sollte dies tun?

+0

Definieren Sie "scheint nicht zu funktionieren". Hast du Abstürze? Ergebnisse anders als was Sie wollten? In beiden Fällen genau was? –

+0

Mit welcher Version von Python arbeiten Sie? –

+0

@JohnBollinger es segfolds, wenn es hier ankommt. Python 3. – ComputerLocus

Antwort

4

Wenn UTF-8 kodierten char * OK ist, können Sie auf jeden Fall PyUnicode_AsUTF8AndSize verwenden sollte (was Python 3.3 erfordert):

PyObject * objectCompName = PySequence_GetItem(compTuple, 0); 
if (! objectCompName) { 
    return NULL; 
} 

size_t size; 
char *ptr = PyUnicode_AsUTF8AndSize(objectCompName, &size); 
if (!ptr) { 
    return NULL; 
} 

// notice that the string pointed to by ptr is not guaranteed to stay forever, 
// and you need to copy it, perhaps by `strdup`. 

Auch Verstehen Sie, dass obligatorisch ist, um den Rückgabewert jedes einzelnen Funktionsaufrufs zu überprüfen, den Sie jemals in Ihrem Code ausführen.

Hier die PyTuple_GetItem kehrt NULL wenn compTuple ist kein tuple oder 0 verursacht IndexError. PyUnicode_AsUTF8AndSize wird NULL zurückgeben, wenn objectCompName kein str Objekt ist. Ignoriere den Rückgabewert und CPython stürzt mit SIGSEGV ab, wenn die Bedingungen stimmen.

+0

Die PyUnicode-Zeichenfolge wird ursprünglich in einer anderen C-Funktion mit 'PyUnicode_DecodeASCII' erstellt. – ComputerLocus

+0

In diesem Fall ist 'PyUnicode_AsUTF8AndSize' sehr gut. –

+0

Okay, großartig. Sie geben an, dass es "obligatorisch" ist, die Rückgabewerte zu überprüfen. Ich plane, sie zu überprüfen, ich war einfach nicht so, wie ich es nur testen und sicherstellen wollte, dass es zuerst funktioniert. Ist es tatsächlich eine Anforderung, den Rückgabewert zu überprüfen, oder Sie sagen nur, dass dies eine sehr gute Praxis ist? – ComputerLocus

0

Sie müssen zuerst Ihre Python PyUnicode in eine Nicht-Unicode-Python-Zeichenfolge konvertieren (lesen Sie mehr hier: https://docs.python.org/2/c-api/unicode.html#ascii-codecs), dann können Sie das Ergebnis einfach in char* konvertieren.

Unten finden Sie eine Pseudo-Code Ihnen zu helfen, gehen Sie vor:

// Assumption: you have a variable named "pyobj" which is 
// a pointer to an instance of PyUnicodeObject. 

PyObject* temp = PyUnicode_AsASCIIString(pyobj); 
if (NULL == temp) { 
    // Means the string can't be converted to ASCII, the codec failed 
    printf("Oh noes\n"); 
    return; 
} 

// Get the actual bytes as a C string 
char* c_str = PyByteArray_AsString(temp); 

// Use the string in some manner 
printf("The python unicode string is: %s\n", c_str); 

// Make sure the temp stuff gets cleaned up at the end 
Py_XDECREF(temp); 
+1

Die Zeile mit dem 'PyByteArray_AsString (temp);' ist segfaulting. – ComputerLocus