Android NDK 中的 ICU 库

发布于 2024-10-02 08:20:26 字数 2459 浏览 4 评论 0原文

我正在尝试为依赖于 ICU 库(libicuuc.so 和 libicui18n.so)的 C 库创建 JNI 包装器。

我尝试在我的 NDK(标准版本和 CrystaX 版本,在 Mac OS X 机器上)中构建 ICU4C,并不断遇到这样的链接问题:

/Users/kyip/KyVmShared/KyAndroid/myproject/obj/local/armeabi/objs/icuuc/udata.o: In function `openCommonData':
/Users/kyip/KyVmShared/KyAndroid/myproject/jni/icu4c/common/udata.c:836: undefined reference to `icudt42_dat'
/Users/kyip/KyVmShared/KyAndroid/myproject/obj/local/armeabi/objs/icuuc/ustr_wcs.o: In function `_strFromWCS':
/Users/kyip/KyVmShared/KyAndroid/myproject/jni/icu4c/common/ustr_wcs.c:365: undefined reference to `wcstombs'
/Users/kyip/KyVmShared/KyAndroid/myproject/jni/icu4c/common/ustr_wcs.c:415: undefined reference to `wcstombs'
/Users/kyip/KyVmShared/KyAndroid/myproject/jni/icu4c/common/ustr_wcs.c:314: undefined reference to `wcstombs'
/Users/kyip/KyVmShared/KyAndroid/myproject/obj/local/armeabi/objs/icuuc/ustr_wcs.o: In function `_strToWCS':
/Users/kyip/KyVmShared/KyAndroid/myproject/jni/icu4c/common/ustr_wcs.c:164: undefined reference to `mbstowcs'
collect2: ld returned 1 exit status

我还尝试了 android ndk 中的 unicode 支持 但没有运气。我陷入困境:

arm-eabi-g++ -I/ky/crystax/android-ndk-r4-crystax/build/platforms/android-8/arch-arm/usr/include/ -O3 -fno-short-wchar -DU_USING_ICU_NAMESPACE=0 -DU_GNUC_UTF16_STRING=0 -fno-short-enums -nostdlib -fPIC -DU_COMMON_IMPLEMENTATION  -D_REENTRANT -I../common -I../../icu/source/common -I../../icu/source/i18n   "-DDEFAULT_ICU_PLUGINS=\"/usr/local/lib/icu\" "  -DU_COMMON_IMPLEMENTATION -DHAVE_CONFIG_H  -I/ky/crystax/android-ndk-r4-crystax/build/platforms/android-8/arch-arm/usr/include/ -O3 -fno-short-wchar -DU_USING_ICU_NAMESPACE=0 -DU_GNUC_UTF16_STRING=0 -fno-short-enums -nostdlib -fPIC -DU_COMMON_IMPLEMENTATION  -std=c++0x  -fvisibility=hidden -c   -o errorcode.ao ../../icu/source/common/errorcode.cpp
In file included from ../../icu/source/common/unicode/ptypes.h:23,
                 from ../../icu/source/common/unicode/umachine.h:52,
                 from ../../icu/source/common/unicode/utypes.h:36,
                 from ../../icu/source/common/errorcode.cpp:17:
/ky/crystax/android-ndk-r4-crystax/build/platforms/android-8/arch-arm/usr/include/sys/types.h:122: error: 'uint64_t' does not name a type
make[1]: *** [errorcode.ao] Error 1
make: *** [all-recursive] Error 2

任何帮助将不胜感激。

I am trying to create a JNI wrapper for a C library that depends on the ICU libraries (libicuuc.so and libicui18n.so).

I tried building ICU4C in my NDK (both standard and CrystaX versions, on a Mac OS X machine) and kept running into linking issues like this:

/Users/kyip/KyVmShared/KyAndroid/myproject/obj/local/armeabi/objs/icuuc/udata.o: In function `openCommonData':
/Users/kyip/KyVmShared/KyAndroid/myproject/jni/icu4c/common/udata.c:836: undefined reference to `icudt42_dat'
/Users/kyip/KyVmShared/KyAndroid/myproject/obj/local/armeabi/objs/icuuc/ustr_wcs.o: In function `_strFromWCS':
/Users/kyip/KyVmShared/KyAndroid/myproject/jni/icu4c/common/ustr_wcs.c:365: undefined reference to `wcstombs'
/Users/kyip/KyVmShared/KyAndroid/myproject/jni/icu4c/common/ustr_wcs.c:415: undefined reference to `wcstombs'
/Users/kyip/KyVmShared/KyAndroid/myproject/jni/icu4c/common/ustr_wcs.c:314: undefined reference to `wcstombs'
/Users/kyip/KyVmShared/KyAndroid/myproject/obj/local/armeabi/objs/icuuc/ustr_wcs.o: In function `_strToWCS':
/Users/kyip/KyVmShared/KyAndroid/myproject/jni/icu4c/common/ustr_wcs.c:164: undefined reference to `mbstowcs'
collect2: ld returned 1 exit status

I also tried the suggestion given at unicode support in android ndk but no luck. I got stuck at:

arm-eabi-g++ -I/ky/crystax/android-ndk-r4-crystax/build/platforms/android-8/arch-arm/usr/include/ -O3 -fno-short-wchar -DU_USING_ICU_NAMESPACE=0 -DU_GNUC_UTF16_STRING=0 -fno-short-enums -nostdlib -fPIC -DU_COMMON_IMPLEMENTATION  -D_REENTRANT -I../common -I../../icu/source/common -I../../icu/source/i18n   "-DDEFAULT_ICU_PLUGINS=\"/usr/local/lib/icu\" "  -DU_COMMON_IMPLEMENTATION -DHAVE_CONFIG_H  -I/ky/crystax/android-ndk-r4-crystax/build/platforms/android-8/arch-arm/usr/include/ -O3 -fno-short-wchar -DU_USING_ICU_NAMESPACE=0 -DU_GNUC_UTF16_STRING=0 -fno-short-enums -nostdlib -fPIC -DU_COMMON_IMPLEMENTATION  -std=c++0x  -fvisibility=hidden -c   -o errorcode.ao ../../icu/source/common/errorcode.cpp
In file included from ../../icu/source/common/unicode/ptypes.h:23,
                 from ../../icu/source/common/unicode/umachine.h:52,
                 from ../../icu/source/common/unicode/utypes.h:36,
                 from ../../icu/source/common/errorcode.cpp:17:
/ky/crystax/android-ndk-r4-crystax/build/platforms/android-8/arch-arm/usr/include/sys/types.h:122: error: 'uint64_t' does not name a type
make[1]: *** [errorcode.ao] Error 1
make: *** [all-recursive] Error 2

Any help would be appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

请恋爱 2024-10-09 08:20:26

看来这个问题涉及到两个文件。调用sys/types.h的icu/source/common/unicode/ptypes.h包含

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

通过包含来自Android的sys/types.h,我们涉及(接近第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

似乎uint64_t在分配时尚未声明到 u_int64_t。事实上,sys/types.h 包含 stdint.h,其中包含以下内容:

#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

可能未定义 STRICT_ANSI。看起来这是 sys/types.h 中 Android 代码中的一个错误。如果未定义STDC_INT64,则不会定义uint64_t,因此无法定义u_int64_t。也许真正的解决方案是修改 sys/types.h,使其具有

#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

如果您修复此问题,则下一个错误将出现在 cstring.h:109

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

如果您改为 #define STDC_INT64 in common/unicode /ptypes.h 它将走得更远,但将在此处结束

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

更多信息:http://groups.google.com/group/android-ndk/browse_thread/thread/2ec9dc289d815ba3?pli=1 但没有真正的解决方案

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

和我恋爱吧 2024-10-09 08:20:26

我也遇到了这个问题:
未定义对“mbstowcs”的引用

您应该构建并链接更高版本的android api。

笔记:
我尝试将它与 android-ndk/platforms/android-4 中的库链接起来...我原以为 4 是 Android 版本,但 4 是 Android API 版本。 Android API 4对应于Android 1.6,巫婆非常非常老,libc中确实没有mbstowcs函数

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

笙痞 2024-10-09 08:20:26

这是我解决问题的方法。它很脏,但很有效。 lib 已编译:

1. 文件:/icu4c/common/cwchar.h

注释掉 #if U_HAVE_WCHAR_H 和相应的 #endif,因此 始终包含在内。

将之前的 uprv_wcstombs 定义替换为:

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

将之前的 uprv_mbstowcs 定义替换为:

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

2. 文件:/icu4c/common/ustr_wcs.cpp

位于顶部某处,位于已存在的包含文件下添加行:

#include "../wcsmbs.h"

3.创建新文件“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));
}

希望有帮助。

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.

油焖大侠 2024-10-09 08:20:26

我们一直在努力为系统中的 ICU 库提供 NDK 包装器:https ://android-review.googlesource.com/c/153001/

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/.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文