ICU library in Android NDK

泪湿孤枕 提交于 2019-12-01 10:47:01

It seems that two files are involved in this issue. icu/source/common/unicode/ptypes.h which calls sys/types.h includes

#if ! U_HAVE_UINT64_T
    typedef unsigned long long uint64_t;
/* else we may not have a 64-bit type */
#endif

By including sys/types.h from Android, we involve (near line 122/124)

#ifdef __BSD_VISIBLE
typedef unsigned char   u_char;
typedef unsigned short  u_short;
typedef unsigned int    u_int;
typedef unsigned long   u_long;

typedef uint32_t       u_int32_t;
typedef uint16_t       u_int16_t;
typedef uint8_t        u_int8_t;
typedef uint64_t       u_int64_t;
#endif

It seems that uint64_t has not been declared when it is assigned to u_int64_t. Indeed, sys/types.h includes stdint.h which has the following:

#if !defined __STRICT_ANSI__ || __STDC_VERSION__ >= 199901L
#  define __STDC_INT64__
#endif

typedef __int8_t      int8_t;
typedef __uint8_t     uint8_t;
typedef __int16_t     int16_t;
typedef __uint16_t    uint16_t;
typedef __int32_t     int32_t;
typedef __uint32_t    uint32_t;
#if defined(__STDC_INT64__)
typedef __int64_t     int64_t;
typedef __uint64_t    uint64_t;
#endif

Likely STRICT_ANSI is not defined. Seems like this is a bug in the Android code in sys/types.h. If STDC_INT64 is not defined, it will not define uint64_t so it can't define u_int64_t. Perhaps the real solution is to have sys/types.h modified so that it has

#ifdef __BSD_VISIBLE
typedef unsigned char   u_char;
typedef unsigned short  u_short;
typedef unsigned int    u_int;
typedef unsigned long   u_long;

typedef uint32_t       u_int32_t;
typedef uint16_t       u_int16_t;
typedef uint8_t        u_int8_t;
$if defined(__STDC_INT64__)
typedef uint64_t       u_int64_t;
#endif
#endif

If you fix this, the next error will be in cstring.h:109

icu/source/common/cstring.h:109: error: 'int64_t' has not been declared

If you instead #define STDC_INT64 in common/unicode/ptypes.h it will go substantially farther, but will end at

icu/source/common/ustrenum.cpp:118: error: must #include <typeinfo> before using typeid

with more info here: http://groups.google.com/group/android-ndk/browse_thread/thread/2ec9dc289d815ba3?pli=1 but no real solutions

I also had this issue: undefined reference to `mbstowcs'

You should build and link with higher version of android api.

Note: I tried to link it with libraries from android-ndk/platforms/android-4... I had thought that 4 is version of Android, but 4 is version of Android API. And Android API 4 corresponds to Android 1.6 witch is very very old there is really no mbstowcs function in libc

Here is how i solved the problem. It is dirty but it works. The lib got compiled:

1. file: /icu4c/common/cwchar.h

comment out the #if U_HAVE_WCHAR_H and the respective #endif so the <wchar.h> is always included.

replace the previous uprv_wcstombs definition with:

#define uprv_wcstombs(mbstr, wcstr, count) U_STANDARD_CPP_NAMESPACE wcs2mbs(mbstr, wcstr, count)

replace the previous uprv_mbstowcs definition with:

#define uprv_mbstowcs(wcstr, mbstr, count) U_STANDARD_CPP_NAMESPACE mbs2wcs(wcstr, mbstr, count)

2. file: /icu4c/common/ustr_wcs.cpp

somewhere at the top, under the already existing includes add the line:

#include "../wcsmbs.h"

3. create new file "icu4c/wcsmbs.h"

size_t mbs2wcs(wchar_t * __ restrict pwcs, const char * __ restrict s, size_t n)
{

   mbstate_t mbs;
   const char *sp;
   memset(&mbs, 0, sizeof(mbs));
   sp=s;
   return (mbsrtowcs(pwcs,&sp,n,&mbs));
}


size_t wcs2mbs(char * __restrict s, const wchar_t * __restrict pwcs, size_t n)
{
   mbstate_t mbs;
   const wchar_t *pwcsp;
   memset(&mbs,0,sizeof(mbs));
   pwcsp = pwcs;
   return (wcsrtombs(s,&pwcsp,n,&mbs));
}

Hope it helps.

There has been an effort to provide NDK wrappers for the ICU libraries that are part of the system: https://android-review.googlesource.com/c/153001/.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!