简体   繁体   中英

Libicu, undefined reference while compiling

I'm trying to use the lib icu in my shared library. So i generate my .so who use libicu functions, this parts works well.

Then i try to compile my main program, using the shared library that i created before. But i get the following error:

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'

I have installed the libicu with this help.

I compile my shared library with -licuuc, as well as my main program compile only with -l:libstring.so and -licuuc.

When i do ldd libstring.so, i don't have the .so of the libicu on the list of dependencies.

The problem probably come from this.

Thx

EDIT: I have create a little test:

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();
}

Makefile:

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"

Note: even with -licuuc instead of -licui18n i got the same error.

Output:

$> 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

If i do ldd on my shared library:

$> 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:

Ok, seems that the problem is easier to solve than expected. My program need function in icu_53, but i got icu_48 installed on my computer dunno why.

$> 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

Does anyone know how to upgrade the version from icu_48 to icu_53 at least ?

Seems 'udat_parse_53' is located inside libicui18n.so.53 library. Try to compile your project with '-licui18n' option.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM