LINUX.ORG.RU

Wchar_t и wprintf, C, Python

 , ,


0

2

Начал осваивать написание модулей Python. Читаю руководство по Unicode-строкам в его документации и вижу, что у этого типа бывает разный размер, в зависимости от системы. Как и у wchar_t, применяемого для хранения многобайтовых символов. Проверил на своей системе размер в байтах таким образом:

setup.py для модуля Python

from distutils.core import setup, Extension
 
module1 = Extension('hello', sources = ['hellomodule.c'])
 
setup (name = 'PackageName',
        version = '1.0',
        description = 'This is a demo package',
        ext_modules = [module1])

Вывод

running build
running build_ext
building 'hello' extension
x86_64-pc-linux-gnu-gcc -pthread -fPIC -I/usr/include/python2.7 -c hellomodule.c -o build/temp.linux-x86_64-2.7/hellomodule.o
x86_64-pc-linux-gnu-gcc -pthread -shared build/temp.linux-x86_64-2.7/hellomodule.o -L/usr/lib64 -lpython2.7 -o build/lib.linux-x86_64-2.7/hello.so

Проверка

static PyObject* hw(PyObject* self, PyObject* args) 
{ 
	Py_UNICODE  *src;
	int srclen;

	if (! PyArg_ParseTuple(args, "u#", &src, &srclen))
		return NULL;
	
	printf("%lu=%lu=%lu",
	       ( unsigned long )sizeof(Py_UNICODE),
	       ( unsigned long )sizeof(wchar_t),
	       ( unsigned long )sizeof(int)
	); puts("");
	
	Py_RETURN_NONE;
}

На выходе имею 4=4=4, получается, в моей системе размер в байтах типа UNICODE для питона равен размеру int/wchar_t.

Проверил копирование в wchar, дополнил код так:

wchar_t *aw;
aw = (wchar_t*)calloc(srclen + 1, sizeof(wchar_t));

size_t i;
for (i=0; i < srclen; ++i){
  aw[i]=src[i];
    printf  ("&#%u &#%u", src[i], aw[i]);
  puts    ("");
}

Получил, соответственно, вывод нескольких букв в десятичном представлении. И попытался уже их вывести, однако ничего не увидел в терминале.

wprintf(L"%ls\n", aw); free(aw);

Как заставить здесь работать wprintf и что я с ним напутал? Судя по различным форумам, я пропускаю установку локали, но я не разобрался с этой частью. Кроме того, является-ли такое копирование при помощи цикла нормальным, или есть гораздо более простые и удобные функции, которые делают его иначе?



Последнее исправление: KM155TM2 (всего исправлений: 1)

А ларчик-то так просто открывался:

if (! setlocale(LC_ALL, "ru_RU.utf8")) return PyErr_SetFromErrno(SetLocaleError);
wprintf(L"%ls\n", src);

KM155TM2
() автор топика

Так делать нельзя. Py_UNICODE содержит юникод, а wchar_t может содержать любую хрень, ведомую только компилятору. Поэтому преобразуй в utf-8 и печатай char * с помощью обычного printf.

Reset ★★★★★
()
Ответ на: комментарий от Reset

Спасибо, интересная мысль.

любую хрень, ведомую только компилятору

Надо повникать, как GCC с этим обращается на досуге.

Кстати, на будущее, при контантенации двух равных по размеру Py_UNICODE, либо char, либо wchar_t ведь нет никакой разницы в производительности?

KM155TM2
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.