'프로그램 사용/iconv() & glibc'에 해당되는 글 6건

  1. 2010.06.01 iconv / gconv 사용시 주의사항(?) - 포팅시 유의사항
  2. 2010.06.01 iconv 라이브러리 위치
  3. 2010.04.23 iconv() 함수 완전정복(?)
  4. 2010.04.20 iconv() 함수 사용하기 (6)
  5. 2010.04.20 linux iconv 테스트
  6. 2010.04.19 iconv 유틸리티/프로그램 사용하기 (2)
/usr/lib/gconv 에는 iconv 에서 사용하는 변환에 대한 테이블(?) 파일들이 존재한다.
예를 들어 ISO8859-1는 ISO8859-1.so 이런식으로 존재하는데
이것을 찾기 위한 alias 파일이 존재한다.

-rw-r--r-- 1 root root  54K Oct  8  2006 gconv-modules

바로 요녀석인데, 이녀석이 존재하지 않으면
so 파일들이 존재해도 파일을 찾지못해 변환을 하지 못한다.

2010/06/01 - [프로그램 사용/iconv() / glibc] - iconv 라이브러리 위치




2010.06.03 추가

임베디드에서 특정 디렉토리에 넣어야 할 경우에는
gconv 디렉토리를 다른곳으로 넣고
export GCONV_PATH=/[new path] 씩으로 .bashrc나 .bash_profile 등에 넣어주면 된다.

GCONV_PATH Directories in which iconv() looks for character encoding libraries
[링크 : http://www.scratchbox.org/documentation/general/tutorials/glibcenv.html]

Posted by 구차니

댓글을 달아 주세요

뜬금없는 이야기지만, 일단 iconv는 libc 를 이용한다.
그런데 이 넘은 실제로 /usr/lib/gconv/*.so 파일들을 사용한다.

아무튼, 이 넘들이 없으면 에러는 안나지만 변환이 안된다.
(임베디드에서 iconv 쓰는데 변환이 안되서 찾은 문제)

더보기


strace를 해보니
gconv-module은 /usr/lib/gconv-modules에서 잘 open 했는데 EUC-KR.so 를 open 한 후 libc.so.6ld-linux.so.2를 찾네요, 저는 shared library를 안쓰고 있는데 ㅠㅠ 그래서 위 두 파일을 ramdisk/usr/lib 에 복사해 넣은 후 TARGET에서 다시 iconv sample 프로그램을 돌려보니 이제는 정상 동작 합니다.

[링크 : http://kldp.org/node/76270]



음.. 그래서 일단은 libc*로 파일들을 검색해보니 "libc.so" 가 없다.
so 라길레 파일 용량을 보니 저렴한 238Byte. 그래서 cat으로 해보니 텍스트 파일이다.

>>> x86 리눅스의 libc.so 내용
# cat /usr/lib/libc.so
/* GNU ld script
   Use the shared library, but some functions are only in
   the static library, so try that secondarily.  */
OUTPUT_FORMAT(elf32-i386)
GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a  AS_NEEDED ( /lib/ld-linux.so.2 ) )

>>> sh4 리눅스의 libc.so 내용
]# cat usr/lib/libc.so
/* GNU ld script
   Use the shared library, but some functions are only in
   the static library, so try that secondarily.  */
OUTPUT_FORMAT(elf32-sh-linux)
GROUP ( libc.so.6 libc_nonshared.a  AS_NEEDED ( /lib/ld-linux.so.2 ) )



수동으로 crt 코드와 libc를 링크시켜 줍니다. 여기까지 해서 동작을 잘 해야 하는데, 컴파일/링킹 워닝이나 에러가 안나지만 프로그램이 동작하지 않습니다.

$ readelf -l test
...
INTERP 0x000114 0x08048114 0x08048114 0x00013 0x00013 R 0x1
[Requesting program interpreter: /usr/lib/libc.so.1]
...

dynamic linker를 시스템 기본값인 /usr/lib/libc.so.1로 지정하는데, 문제는 시스템에는 해당 파일이 없습니다--; 마찬가지 방법으로 /bin/ls의 INTERP 섹션을 읽어보니까 INTERP는 /lib/ld-linux.so.2로 되어 있네요. 위에서 /usr/lib/libc.so.1 은 없고 /usr/lib/libc.so는 있는데, 이 파일의 내용은 다음과 같습니다.

$ cat /usr/lib/libc.so
/* GNU ld script
Use the shared library, but some functions are only in
the static library, so try that secondarily. */
OUTPUT_FORMAT(elf32-i386)
GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a AS_NEEDED ( /lib/ld-linux.so.2 ) )
출처:ld의 동작


[링크 : http://earthfall.egloos.com/1794074]

Posted by 구차니

댓글을 달아 주세요

iconv() 함수에서
변환결과로 나와야 하는 방법이 unicode일 경우에는 (일단 다른건 안해봤으니 -ㅁ-?)
(strlen(inbuf) + 2) * 2 가 된다.

size_t iconv(iconv_t cd,
                     char **inbuf, size_t *inbytesleft,
                     char **outbuf, size_t *outbytesleft);

예를 들어 UTF-8을 UNICODE로 변환시에는
UTF-8 문자열 특성상, stelen(utf8str) == 100 일 경우
유니코드(2바이트) 스트링은 최소 25에서 최대 100 까지 변환이 된다.

그리고 iconv 특성상 처음에 2바이트 BOM(Byte Order Mark)을 붙이므로
실질적으로 변환을 위해 필요로 하는 outbuf의 길이는
(strlen(inbuf) + 2) * 2 가 된다.

원래대로라면
(strlen(inbuf) + 1) * 2 + 2 이고
+1 은 '\0'
+2 는 Unicode BOM(0xFEFF in big endian)이다.

[링크 : http://mwultong.blogspot.com/2006/05/qna-unicode-bom-byte-order-mark.html]


덧 : UTF-8로 인코딩된 아랍어의 경우, 조합은 별도로 해주어야 한다.
iconv()가 UNICODE로 변환은 해주지만, 그렇다고 해서 조합까지 해주지는 않는다.
Posted by 구차니

댓글을 달아 주세요

iconv_open() 함수는 dest, source 형식으로 인자를 받고
iconv() 함수는 2중 포인터를 사용한다.

#include <iconv.h>

iconv_t iconv_open(const char *tocode, const char *fromcode);
size_t iconv(iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);

iconv_open(TO, FROM);
이므로 반대로 넣으면 이상하게 나온다. 주의요망!

그리고 iconv() 함수는
문자열 변수들은 2중 포인터로 넘겨주고(왜?)
inbytesleft는 strlen(*inbuf) 의 값을
outbytesleft는 strlen(*outbuf) 의 값을 넣어주면된다.

물론 변환에 따라서, 길이가 가변적으로 달라질수 있기 때문에 주의해야 한다.

만약, 변환중 메모리가 넘치게 되면 EILSEQ 에러가 발생하게 되며, (물론 넘치기 전에 데이터는 빼낼수 있다.)
변수의 포인터가 2중 포인터가 아니면
"__gconv: Assertion `outbuf != ((void *)0) && *outbuf != ((void *)0)' failed."
이런 에러를 만나게 될 것이다.


#include "stdio.h"
#include "string.h"
#include "iconv.h"
#include "errno.h"

#define BUFF_SIZE 64

int main()
{
        iconv_t cd = iconv_open("UNICODE", "UTF-8");
        if (cd == (iconv_t)(-1))
        {
                perror("iconv_open");
                return 0;
        }

        char inBuf[BUFF_SIZE] = "Hello world";
        int inBufSize = sizeof(inBuf);

        char outBuf[BUFF_SIZE];
        int outBufSize = sizeof(outBuf);
        memset(outBuf, 0, outBufSize);

        // convert
        size_t readBytes = strlen(inBuf);
        size_t writeBytes = sizeof(outBuf);
        char* in = inBuf;
        char* out = outBuf;

        printf("readBytes:%d writeBytes:%d\n",readBytes,writeBytes);

        if (iconv(cd, &in, &readBytes, &out, &writeBytes) == -1)
        {
                printf("failed to iconv errno:%d EILSEQ:%d\n", errno, EILSEQ);
        }
        else
        {
                int idx;
                printf("in:%x out:%x\n",in,out);
                printf("readBytes:%d writeBytes:%d\n",readBytes,writeBytes);
                for(idx = 0; idx < BUFF_SIZE; idx++)
                {
                        printf("%03d %c %x\t\t", idx, inBuf[idx], inBuf[idx]);
                        printf("%03d %c %x\n", idx, outBuf[idx], outBuf[idx]);
                }
                outBuf[writeBytes] = '\0';
        }

        iconv_close(cd);
        return 0;
}


2010/04/20 - [Linux] - linux iconv 테스트
2010/04/19 - [Linux] - iconv

Posted by 구차니

댓글을 달아 주세요

  1. 제 블로그에 담아가겠습니다~ 좋은자료 감사드려요!

    2012.04.26 17:13 신고 [ ADDR : EDIT/ DEL : REPLY ]
  2. ㅁㄴㅇㅁㄴㅇ

    25번 라인 size_t readBytes = strlen(inBuf)+1; 이 되어야할 것같습니다

    2014.08.12 21:18 [ ADDR : EDIT/ DEL : REPLY ]
    • +1은 대개 malloc 시 NULL 공간을 넣기 위함인데
      지금은 NULL을 처리할 이유가 없기 때문에 +1을 해줄 필요는 없을것으로 생각됩니다.

      2014.08.12 21:27 신고 [ ADDR : EDIT/ DEL ]
  3. ㅁㄴㅇㅁㄴㅇ

    아, 제가 malloc한 문자열에서 이 코드를 사용하다 부딪힌 문제였네요. 감사합니다 ㅎㅎ

    2014.08.12 21:32 [ ADDR : EDIT/ DEL : REPLY ]

iconv 유틸리티를 이용해서 일단 변환 테스트.
-f=UTF-8        (UTF-8 문서를)
-t=UNICODE   (유니코드로 변환)
-o result.txt    (result.txt로 출력)

$ cat test.str
Hello world
$ vi test.str
  1 Hello world

$ iconv -f=UTF8 -t=UNICODE test.str -o result.txt

$ cat result.txt
▒▒Hello world
$ vi result.txt
  1 ÿþH^@e^@l^@l^@o^@ ^@w^@o^@r^@l^@d^@
  2 ^@



$ iconv --help


Posted by 구차니
TAG iconv

댓글을 달아 주세요

iconv는 utf 나 iso8859 등, 여러가지 방법으로
문자열 코딩을 변환해주는 역활을 하는 함수/유틸리티이다.

$ man -k iconv
iconv                (1)  - Convert encoding of given files from one encoding to another
iconv                (1p)  - codeset conversion
iconv                (3)  - perform character set conversion
iconv                (3p)  - codeset conversion function
iconv.h [iconv]      (0p)  - codeset conversion facility
iconv_close          (3)  - deallocate descriptor for character set conversion
iconv_close          (3p)  - codeset conversion deallocation function
iconv_open           (3)  - allocate descriptor for character set conversion
iconv_open           (3p)  - codeset conversion allocation function
아무튼, iconv는 함수(3/3p) 이자 유틸리티(1) 인데
함수의 경우 iconv_open() - iconv() - iconv_close() 를 이용하여 사용한다.

#include <iconv.h>
iconv_t iconv_open(const char *tocode, const char *fromcode);

tocode나 fromcode에 들어갈 내용은

$ iconv --list

명령어로 확인이 가능하다.

$ ldd /usr/bin/iconv
        linux-gate.so.1 =>  (0x005e5000)
        libc.so.6 => /lib/libc.so.6 (0x47ae8000)
        /lib/ld-linux.so.2 (0x47119000)
ldd로 확인해보니, libc만 있으면 실질적으로 구동이 가능한 함수로 보인다.

테스트가 필요한 코드
[링크 : http://kldp.org/node/77391]
[링크 : http://www.korone.net/bbs/board.php?bo_table=etc_misc&wr_id=160&page=2]
Posted by 구차니
TAG iconv

댓글을 달아 주세요

  1. 게르드

    오랜만이에요~ 형..ㅋㅋㅋㅋ
    iconv. ㅋㅋㅋ
    예전에 KDE 깔았을 때 자막을 전부 유니코드로 변환한다고 삽질할 때 썼던 필수 명령어~!!!+_+

    2010.04.20 16:45 [ ADDR : EDIT/ DEL : REPLY ]