Ищите «Hello World» для обработки юникода ctypes (включая и код Python, и C) - PullRequest
2 голосов
/ 21 мая 2009

Может кто-нибудь показать мне действительно простой пример ctypes Python, включающий строки Unicode , включая код C?

Скажем, способ взять строку Python Unicode и передать ее функции C, которая объединяет ее с собой и возвращает ее в Python, который ее печатает.

Ответы [ 3 ]

6 голосов
/ 03 сентября 2009

Эта программа использует ctypes для вызова wcsncat из Python. Он объединяет a и b в буфер, который недостаточно длинный, чтобы a + b + (null terminator) демонстрировал более безопасную n версию объединения.

Вы должны передать create_unicode_buffer() вместо обычного неизменяемого u"unicode string" для неконстантных wchar_t* параметров, в противном случае вы, вероятно, получите ошибку сегментации.

Если функция, с которой вам нужно поговорить, возвращает UCS-2 и sizeof(wchar_t) == 4, тогда вы не сможете использовать unicode_buffer(), потому что она преобразует между wchar_t во внутреннее представление Unicode Python. В этом случае вы можете использовать комбинацию result.create_string_buffer() и result.decode('UCS2') или просто создать массив из c_short и u''.join(unichr(c) for c in buffer). Я должен был сделать это для отладки драйвера ODBC.

example.py:

#!/usr/bin/env python
#-*- encoding: utf-8 -*-
import sys
from ctypes import *
example = cdll.LoadLibrary(".libs/libexample.so")
example.its_an_example.restype = c_wchar_p
example.its_an_example.argtypes = (c_wchar_p, c_wchar_p, c_uint)
buf = create_unicode_buffer(19) # writable, unlike u"example".
buf[0] = u"\u0000"
a = u"あがぃいぅ ☃ "
b = u"個人 相命理 網上聯盟"
print example.its_an_example(buf, a, len(buf) - len(buf.value) - 1)
print example.its_an_example(buf, b, len(buf) - len(buf.value) - 1)
print buf.value # you may have to .encode("utf-8") before printing
sys.stdout.write(buf.value.encode("utf-8") + "\n")

example.c:

#include <stdlib.h>
#include <wchar.h>

wchar_t *its_an_example(wchar_t *dest, const wchar_t *src, size_t n) {
    return wcsncat(dest, src, n);
}

Makefile: (убедитесь, что отступ - это один символ табуляции, а не пробелы):

all:
    libtool --mode=compile gcc -g -O -c example.c
    libtool --mode=link gcc -g -O -o libexample.la example.lo \
            -rpath /usr/local/lib
0 голосов
/ 21 мая 2009
from ctypes import *

buffer = create_string_buffer(128)
cdll.msvcrt.strcat(buffer, "blah")
print buffer.value

Примечание. Я понимаю, что код Python прост, но я борюсь с кодом C. Нужно ли освободить входную строку? Будет ли его выходная строка освобождена Python от его имени?

Нет, вам нужно вручную освободить буфер. Обычно люди сразу копируют строку python из buffer.value, а затем освобождают буфер.

Можете ли вы опубликовать код C? - Майк 2 часа назад

#include <string.h>

char* mystrcat(char* buffer) {
    strcat(buffer, "blah");
    return buffer;
}
0 голосов
/ 21 мая 2009

Не проверено, но я думаю, что это должно работать.

s = "inputstring"
mydll.my_c_fcn.restype = c_char_p
result = mydll.my_c_fcn(s)
print result

Что касается управления памятью, я понимаю, что ваш код c должен управлять памятью, которую он создает. То есть он не должен освобождать входную строку, но в конечном итоге должен освободить возвращаемую строку.

...