Libicu,编译时未定义的引用

时间:2015-05-07 08:22:33

标签: linux g++ icu

我正在尝试在共享库中使用lib icu。 所以我生成了使用libicu函数的.so,这部分效果很好。

然后我尝试使用我之前创建的共享库来编译我的主程序。但我得到以下错误:

release//libstring.so: undefined reference to `u_errorName_53'
release//libstring.so: undefined reference to `ucnv_toUnicode_53'
release//libstring.so: undefined reference to `ucnv_close_53'
release//libstring.so: undefined reference to `ucnv_fromUChars_53'
release//libstring.so: undefined reference to `udat_open_53'
release//libstring.so: undefined reference to `udat_parse_53'
release//libstring.so: undefined reference to `udat_format_53'
release//libstring.so: undefined reference to `ucnv_toUChars_53'
release//libstring.so: undefined reference to `ucnv_open_53'
release//libstring.so: undefined reference to `udat_close_53'

我已经使用this帮助安装了libicu。

我用-licuuc编译我的共享库,以及我的主程序只用-l:libstring.so和-licuuc编译。

当我执行ldd libstring.so时,我没有依赖列表中的libicu .so。

问题可能来自于此。

THX

编辑:我已经创建了一个小测试:

icu.h:

#pragma once

#include <iostream>
#include <string>

#include <unicode/ucnv.h>

class                     c_icu
{
private:

        void *             p_priv;

public:

        c_icu();

        void               open(const wchar_t *name);

        void               to_local(std::wstring &, std::wstring &);
        void               from_local(std::wstring &, std::wstring &);

        void               close(void);

        ~c_icu();
};

icu.cpp:

#include "icu.h"

c_icu::c_icu()
{
  p_priv = NULL;
}

c_icu::~c_icu()
{
  if (p_priv)
    close();
}

void              c_icu::open(const wchar_t *name)
{
  UErrorCode      status = U_ZERO_ERROR;
  char            conv_name[256];

  if (wcstombs(conv_name, name, 256) == (size_t)-1)
    {
      std::cout << "ERROR: wcstombs failed" << std::endl;
      exit(0);
    }
  if ((p_priv = (UConverter *)ucnv_open(conv_name, &status)) == NULL)
    {
      std::cout << "ERROR: ucnv_open failed" << std::endl;
      exit(0);
    }
}

void              c_icu::to_local(std::wstring &src, std::wstring &dst)
{
  UErrorCode      status = U_ZERO_ERROR;
  int32_t         len;

  len = ucnv_toUChars((UConverter *)p_priv, (UChar *)NULL, 0, (const char *)src.c_str(), src.size(), &status);
  if (status == U_BUFFER_OVERFLOW_ERROR)
    {
      status = U_ZERO_ERROR;
      dst.resize(len);
      len = ucnv_toUChars((UConverter *)p_priv, (UChar *)dst.c_str(), dst.size(), (const char *)src.c_str(), src.size(), &status);
      if (U_FAILURE(status))
        {
          std::cout << "ERROR: to_local failed" << std::endl;
          exit(0);
        }
    }
}

void              c_icu::from_local(std::wstring &src, std::wstring &dst)
{
  UErrorCode      status = U_ZERO_ERROR;
  int32_t         len;

  len = ucnv_fromUChars((UConverter *)p_priv, (char *)NULL, 0, (const UChar *)src.c_str(), src.size(), &status);
  if (status == U_BUFFER_OVERFLOW_ERROR)
    {
      status = U_ZERO_ERROR;
      dst.reserve(len);
      len = ucnv_fromUChars((UConverter *)p_priv, (char *)dst.c_str(), dst.size(), (const UChar *)src.c_str(), -1, &status);
    }
}

void              c_icu::close(void)
{
  ucnv_close((UConverter *)p_priv);
  p_priv = NULL;
}

TEST.CPP:

#include "icu.h"

int           main(void)
{
  c_icu converter;
  std::wstring src = L"";
  std::wstring dst;
  const wchar_t add[11] = L"Just a test";
  const wchar_t *unicode = L"koi8-r";

  for (unsigned int i = 0; i < 1000; i++)
    src.append(add, 11);

  converter.open(unicode);
  converter.from_local(src, dst);
  converter.close();
}

生成文件:

NAME=           test
LIB_NAME=       libicutest.so
FLAGS=          -W -Wall -Wextra

all:    lib $(NAME)

$(NAME):
        @echo "Main programm compiling ..."
        g++ -c test.cpp -o test.o $(FLAGS)
        g++ -o $(NAME) test.o -Wl,-rpath,'$$ORIGIN/' -licui18n -L. -licutest
        @echo "Main programm compiled"

lib:
        @echo "Lib Compiling ..."
        g++ -std=gnu++11 -c -fPIC icu.cpp -o icu.o $(FLAGS)
        g++ -shared -Wl,-soname,$(LIB_NAME) -o $(LIB_NAME) icu.o -licui18n
        @echo "Lib Compiled"

注意:即使使用-licuuc而不是-licui18n,我也会遇到同样的错误。

输出:

$> make
Lib Compiling ...
g++ -std=gnu++11 -c -fPIC icu.cpp -o icu.o -W -Wall -Wextra
g++ -shared -Wl,-soname,libicutest.so -o libicutest.so icu.o -licui18n
Lib Compiled
Main programm compiling ...
g++ -c test.cpp -o test.o -W -Wall -Wextra
g++ -o test test.o -Wl,-rpath,'$ORIGIN/' -licui18n -L. -licutest
./libicutest.so: undefined reference to `ucnv_close_53'
./libicutest.so: undefined reference to `ucnv_fromUChars_53'
./libicutest.so: undefined reference to `ucnv_toUChars_53'
./libicutest.so: undefined reference to `ucnv_open_53'
collect2: error: ld returned 1 exit status
make: *** [test] Error 1

如果我在共享库上执行ldd:

$> ldd libicutest.so
 linux-vdso.so.1 =>  (0x00007ffd5eb7f000)
 libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f092b5e6000)
 libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f092b221000)
 libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f092af1a000)
 /lib64/ld-linux-x86-64.so.2 (0x00007f092bb00000)
 libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f092ad04000)

EDIT2:

好吧,似乎问题比预期更容易解决。我的程序需要在icu_53中运行,但是我的计算机上安装了icu_48,为什么不知道。

$> locate libicu
/usr/lib/x86_64-linux-gnu/libicudata.so.48
/usr/lib/x86_64-linux-gnu/libicudata.so.48.1.1
/usr/lib/x86_64-linux-gnu/libicui18n.so.48
/usr/lib/x86_64-linux-gnu/libicui18n.so.48.1.1
/usr/lib/x86_64-linux-gnu/libicuio.so.48
/usr/lib/x86_64-linux-gnu/libicuio.so.48.1.1
/usr/lib/x86_64-linux-gnu/libicule.so.48
/usr/lib/x86_64-linux-gnu/libicule.so.48.1.1
/usr/lib/x86_64-linux-gnu/libiculx.so.48
/usr/lib/x86_64-linux-gnu/libiculx.so.48.1.1
/usr/lib/x86_64-linux-gnu/libicutest.so.48
/usr/lib/x86_64-linux-gnu/libicutest.so.48.1.1
/usr/lib/x86_64-linux-gnu/libicutu.so.48
/usr/lib/x86_64-linux-gnu/libicutu.so.48.1.1
/usr/lib/x86_64-linux-gnu/libicuuc.so.48
/usr/lib/x86_64-linux-gnu/libicuuc.so.48.1.1

有没有人知道如何将版本从icu_48升级到icu_53至少?

1 个答案:

答案 0 :(得分:0)

似乎'udat_parse_53'位于libicui18n.so.53库中。尝试使用'-licui18n'选项编译项目。