linux 에서 multibyte, unicode 프로그래밍
제목을 달아놓고 보니 좀 적당하지 않은것 같기도 하지만
일단 "고수" 님들의 조언을 구해봅니다.
win32 로 짜여진 코드를 linux 로 포팅 작업을 하고 있습니다.
이곳저곳의 도움을 많이 받아 어느정도는 해결이 되었는데,
다음과 같은 문제는 영 쉽지가 않네요..
1. snprintf 류 ( snprintf, vsnprintf) 등에선
len = snprintf(NULL, 0, "target = %s, distance = %d.\n", ptar, pdis);
등과 같이 사용하여 snprintf 의 첫번째 매개변수에 사용될 버퍼의
길이(len) 를 미리 확인할수 있는것으로 알고 있습니다.
win32 에서는
char string 에선 _snprintf, _vsnprintf 를,
wchar_t string 에선 _snwprintf, _vsnwprintf 를 이용하여 해당 값을 구할수 있고
linux 에서도
char string 에선 snprintf, vsnprintf 이 동일하게 대응되는 것을 확인했습니다.
그런데 linux 의 wchar_t 에 대응하는 함수를 찾을수가 없네요.
swprintf, vswprintf 등을 확인해봤는데 -1 이 나오는것 같네요.
linux 에서 unicode 로 개발시, 해당 기능에 대해서 경험이 있으신 분의 조언을 구해봅니다.
2. printf 와 wprintf 를 동시에 사용할수 없습니까?
KLDP 에서 검색해보니 char 와 wchar_t 를 동일 스트림에서 사용할수 없다라는 내용을 보았습니다.
그렇다면 모든 linux 어플리케이션은 이러한 제약을 가지고 있나요?
다른 우회(?) 적인 방법이라도.. 없는지요?
이상입니다.
수고하세요~
내부에서 utf-8로
내부에서 utf-8로 다루시는건 어떨까요. 그편이 좀 편할지도 모르겠습니다.
언제나 삽질 - http://tisphie.net/typo/
프로그래밍 언어 개발 - http://langdev.net
언제나 삽질 - http://tisphie.net/typo/
프로그래밍 언어 개발 - http://langdev.net
리눅스에서 지원
리눅스에서 지원 여부와 상관없이 멀티바이트와 wchar_t는 윈도우 전용이다
라고 생각하는 편이 삶을 윤택하게 해주는 것 같에요;
sizeof wchar_t 을 찍어 보시면 예상과는 다른 결과를 보실 수 도 있고요.
윗 분 말씀처럼 하시는 것이 아름다운 길이라고 생각해요;
문제는 ..
개발이 아니라..포팅이기 때문에..
그래서 어떻게든 output 이 나와야 하는..
obbaya 님의 의견은 linux 에서 wchar_t 관련 개발은 포기하는게 정신건강에
이롭다....라는 말씀이신가요?
정말 linux 에서 그정도로 취약한가요?
**
linux 에서 sizeof wchar_t 가 4바이트 인걸 보고 꽤 의아했었습니다. ㅎㅎ
ISO C 표준에
ISO C 표준에 swprintf()는 버퍼 크기가 부족하면 음수를 리턴하게 되어 있습니다. 정상입니다.
wchar_t의 크기는 compiler마다 다릅니다.
제 경우는, wide character 쪽 함수는 거의 쓰지 않습니다. 무엇보다, wide character는 compiler-specific하기 때문에 unicode와 아무런 상관이 없습니다. 물론, 많은 시스템이 wide character를 unicode에 mapping되게 해 놓았지만, 표준과 상관이 없기 때문에 불안함?을 떨치기 힘듭니다. glibc는 wide character로 32bit UCS-4를 씁니다. 잘 모르지만 Windows에서는 wide character로 16bit UCS-2를 쓰는 것으로 알고 있습니다.
꼭 제 방식이 좋다는 것은 아니지만, (저는 대부분 작업을 linux에서 하는 관계로...) 필요하면 iconv()로 변경해서 작업하고 있습니다. 보통 internationalization 관련해서 완벽한 unicode를 쓰려면 ICU 같은 외부 라이브러리를 쓰는 것이 좋을 겁니다.
http://www.icu-project.org/
간단히.. C 표준은 unicode에 대한 언급이 없습니다. 따라서 wide character와 unicode가 호환된다고 할 수 없습니다. GNU 측에서는 표준을 준수하는 경향을 보이기 때문에, GLIBC의 wide character 관련 함수만 써서 unicode를 다루기에는 무리가 있어 보입니다. Windows는 이에 비해, 표준을 따르지 않고, wide character를 unicode와 밀접하게 붙여서 쓰는 것 같아 보입니다. 따라서 MS의 C 라이브러리를 쓰면 unicode 취급이 쉬워보이나, 표준이 아닌 관계로 다른 OS로 이식하기에 큰 무리가 있어 보입니다.
방법은?? 이식성이 뛰어난, 외부 unicode library를 쓰는게 좋아보이네요.
--
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Korean Ver: http://www.cinsk.org/cfaqs/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Korean Ver: http://cinsk.github.io/cfaqs/
_
윈도의 wchar_t는 utf-16으로 작동합니다. 윈도 2000 이전 세대에서는 ucs-2만 지원하기는 했고, 또 아직도 ucs-2를 utf-16와 혼동해서 사용하는 경우가(윈도 유니코드는 모두 wchar_t 하나로 표현이 되는 것으로 혼동하는 경우가) 많이 있기는 하지만요.
또한 윈도에서의 wchar_t가 16비트라는 것은 OS 차원에서 정의해둔 것이기 때문에, wchar_t를 윈도 내부에서만 사용하는 것은 큰 문제는 없는 것 같습니다.
glibc 소스를 참고하시면 될것 같네요
1.
vc/c++ 에 (vsnprintf, snwprintf) 쌍이 존재하는 것처럼 유닉스계열도 비슷하게 있습니다.
자세한것을 당연히 매뉴얼을 참고하시면 되겠죠 :-)
참고로, glibc소스의 libio디렉토리를 보시면 tst-wprintf.c tst-swscanf.c 등등이 있으니 참고하시면 될것 같네요.
제가 갖고있는것은 2.7인데 그이후 버젼도 별반 다르지 않을것 같네요.
문제는 제경험상 snwprintf의 리눅스 버젼이 있더라도 wchar_t가 4바이트로 정의되 있어, 기존 소프트웨어와 호환성이 떨어진다는 겁니다. 컴파일시 -fshort-wchar 옵션으로 2바이트로 사용하는 방법도 있지만(http://daftcoder.egloos.com/2557534), 다른옵션으로 컴파일된 라이브러리와는 호환성이 떨어지고 성공사례가 드뭅니다.
대안은 몇가지 있지만 손이 많이 갈겁니다.
A. snwprintf 시리즈 함수들을 2바이트버젼을 따로 직접 작성한다. (라이브러리를 찾아보시면 웬만한것은 있을겁니다.)
B. 인코딩 변환하여 사용한다. (ucs2 <--> ucs4), (any <---> utf8 : 요건 그냥 printf함수 사용하는방법임)
C. 최적화된 라이브러리를 사용한다. (찾으시면 저한테도 연락좀 부탁드립니다. :-) )
2. 요건 모든 OS에 해당되는 내용입니다. EUC-KR과 UTF8을 동시에 출력못합니다. (한쪽이 잘나오면 다른쪽은 깨진다는 말입니다.) CP949와 UCS2를 동시에 출력못합니다. 주로 터미널 설정과 관련있는 부분이지요
댓글 달기