این سند فهرستی جزئی از متداولترین اشکالهایی است که ممکن است هنگام استفاده از NDK با آنها مواجه شوید و راهحلهای آنها (در صورت موجود بودن).
استفاده از _FILE_OFFSET_BITS=64
با سطوح API قدیمی تر
قبل از هدرهای یکپارچه ، NDK از _FILE_OFFSET_BITS=64
پشتیبانی نمی کرد. اگر هنگام ساخت برنامه خود آن را تعریف کرده باشید، بی سر و صدا نادیده گرفته می شود. گزینه _FILE_OFFSET_BITS=64
اکنون با هدرهای یکپارچه پشتیبانی میشود، اما در نسخههای قدیمی اندروید، تعداد کمی از APIهای off_t
به عنوان یک نوع off64_t
در دسترس بودند. بنابراین، استفاده از این ویژگی با سطوح API قدیمی منجر به در دسترس بودن توابع کمتری می شود.
این مشکل به طور مفصل در پست وبلاگ r16 و در مستندات بیونیک توضیح داده شده است.
مشکل : ساخت شما APIهایی را می خواهد که در minSdkVersion
شما وجود ندارند.
راه حل : _FILE_OFFSET_BITS=64
را غیرفعال کنید یا minSdkVersion
خود را افزایش دهید.
تعریف نامعلوم یا ضمنی mmap
ممکن است خطای زیر را در C++ مشاهده کنید:
خطا: استفاده از شناسه اعلام نشده "mmap"
یا خطای زیر در C:
هشدار: اعلان ضمنی تابع 'mmap' در C99 نامعتبر است
استفاده از _FILE_OFFSET_BITS=64
به کتابخانه C دستور می دهد که به جای mmap
از mmap64
استفاده کند. mmap64
تا android-21
در دسترس نبود. اگر مقدار minSdkVersion
شما کمتر از 21 باشد، کتابخانه C حاوی mmap
نیست که با _FILE_OFFSET_BITS=64
سازگار باشد، بنابراین تابع در دسترس نیست.
minSdkVersion
بالاتر از سطح API دستگاه تنظیم شده است
سطح API که با NDK میسازید، معنای بسیار متفاوتی با compileSdkVersion
برای جاوا دارد. سطح API NDK حداقل سطح API پشتیبانی شده برنامه شما است. در ndk-build، این تنظیمات APP_PLATFORM
شما است. با CMake، این -DANDROID_PLATFORM
است.
از آنجایی که ارجاعات به توابع معمولاً هنگام بارگیری کتابخانه ها به جای زمانی که برای اولین بار فراخوانی می شوند حل می شوند، نمی توانید به API هایی که همیشه وجود ندارند ارجاع دهید و از استفاده آنها با بررسی سطح API محافظت کنید. اگر اصلاً به آنها ارجاع داده شود باید حضور داشته باشند.
مشکل : سطح API NDK شما بالاتر از API پشتیبانی شده توسط دستگاه شما است.
راه حل : سطح NDK API ( APP_PLATFORM
) خود را روی حداقل نسخه اندرویدی که برنامه شما پشتیبانی می کند، تنظیم کنید.
ساخت سیستم | تنظیم |
---|---|
ndk-build | APP_PLATFORM |
CMake | ANDROID_PLATFORM |
externalNativeBuild | android.minSdkVersion |
برای سایر سیستمهای ساخت، استفاده از NDK با سایر سیستمهای ساخت را ببینید.
نمی توان نمادهای __aeabi
را پیدا کرد
پیام زیر:
UnsatisfiedLinkError: dlopen ناموفق: نمی توان نماد "
__aeabi_memcpy
" را پیدا کرد
نمونه ای از خطاهای احتمالی زمان اجرا است. این خطاها زمانی که می خواهید کتابخانه های بومی خود را بارگیری کنید، در گزارش ظاهر می شوند. نماد ممکن است یکی از __aeabi_*
باشد. به نظر می رسد __aeabi_memcpy
و __aeabi_memclr
رایج ترین هستند.
این مشکل در شماره 126 ذکر شده است
نمی توان نماد rand
پیدا کرد
برای پیغام ثبت خطای زیر:
UnsatisfiedLinkError: dlopen ناموفق بود: نمی توان نماد "
rand
" را پیدا کرد
این پاسخ دقیق Stack Overflow را ببینید.
ارجاع تعریف نشده به __atomic_*
مشکل : برخی از ABI ها برای ارائه برخی پیاده سازی ها برای عملیات اتمی نیاز به libatomic
دارند.
راه حل : هنگام پیوند دادن -latomic
را اضافه کنید.
برای پیغام خطای زیر:
خطا: ارجاع تعریف نشده به "
__atomic_exchange_4
"
نماد واقعی در اینجا ممکن است هر چیزی با پیشوند __atomic_
باشد.
RTTI/ استثناها در سراسر مرزهای کتابخانه کار نمی کنند
مشکل : زمانی که از مرزهای کتابخانه مشترک پرتاب می شود، استثناها ثبت نمی شوند یا dynamic_cast
ناموفق است.
راه حل : یک تابع کلیدی را به انواع خود اضافه کنید. یک تابع کلیدی اولین تابع مجازی غیر خالص و خارج از خط برای یک نوع است. برای مثال به بحث در شماره 533 مراجعه کنید.
C++ ABI بیان میکند که دو شیء دارای نوع یکسانی هستند اگر و فقط در صورتی که نشانگرهای type_info
آنها یکسان باشد. استثناها فقط در صورتی قابل دریافت هستند که type_info
برای catch با استثنای پرتاب شده مطابقت داشته باشد. همین قانون برای dynamic_cast
نیز صدق می کند.
وقتی یک نوع تابع کلیدی ندارد، typeinfo
آن به عنوان یک نماد ضعیف منتشر می شود و اطلاعات نوع مطابق با بارگیری کتابخانه ها ادغام می شوند. هنگامی که کتابخانه ها به صورت پویا پس از بارگیری فایل اجرایی بارگیری می شوند (به عبارت دیگر، از طریق dlopen
یا System.loadLibrary
)، ممکن است بارکننده امکان ادغام اطلاعات نوع برای کتابخانه های بارگذاری شده را نداشته باشد. وقتی این اتفاق می افتد، این دو نوع برابر در نظر گرفته نمی شوند.
استفاده از کتابخانه های از پیش ساخته شده ناهماهنگ
استفاده از کتابخانه های از پیش ساخته شده - اینها معمولاً کتابخانه های شخص ثالث هستند - در برنامه شما نیاز به کمی دقت بیشتری دارد. به طور کلی از قوانین زیر آگاه باشید:
حداقل سطح API برنامه حاصل حداکثر
minSdkVersion
های همه کتابخانه های برنامه است.اگر
minSdkVersion
شما 16 است، اما از یک کتابخانه از پیش ساخته شده استفاده می کنید که در برابر 21 ساخته شده است، حداقل سطح API برنامه حاصل 21 است. اگر کتابخانه از پیش ساخته شده ثابت باشد، رعایت نکردن آن در زمان ساخت قابل مشاهده خواهد بود، اما ممکن است نباشد. تا زمان اجرا برای کتابخانه های مشترک از پیش ساخته شده ظاهر می شود.همه کتابخانه ها باید با همان نسخه NDK تولید شوند.
این قانون کمی انعطافپذیرتر از بسیاری از قوانین است، زیرا شکستگیها نادر است، اما سازگاری بین کتابخانههایی که با نسخههای اصلی مختلف NDK ساخته شدهاند تضمین نمیشود. C++ ABI پایدار نیست و در گذشته تغییر کرده است.
برنامههای دارای چندین کتابخانه مشترک باید از STL مشترک استفاده کنند.
مانند STLهای ناهمخوان، اگر دقت زیادی به کار گرفته شود، می توان از مشکلات ناشی از آن جلوگیری کرد، اما بهتر است فقط از بروز مشکل جلوگیری کنید. بهترین راه برای جلوگیری از این مشکل این است که از داشتن چندین کتابخانه مشترک در برنامه خود اجتناب کنید.
این سند فهرستی جزئی از متداولترین اشکالهایی است که ممکن است هنگام استفاده از NDK با آنها مواجه شوید و راهحلهای آنها (در صورت موجود بودن).
استفاده از _FILE_OFFSET_BITS=64
با سطوح API قدیمی تر
قبل از هدرهای یکپارچه ، NDK از _FILE_OFFSET_BITS=64
پشتیبانی نمی کرد. اگر هنگام ساخت برنامه خود آن را تعریف کرده باشید، بی سر و صدا نادیده گرفته می شود. گزینه _FILE_OFFSET_BITS=64
اکنون با هدرهای یکپارچه پشتیبانی میشود، اما در نسخههای قدیمی اندروید، تعداد کمی از APIهای off_t
به عنوان یک نوع off64_t
در دسترس بودند. بنابراین، استفاده از این ویژگی با سطوح API قدیمی منجر به در دسترس بودن توابع کمتری می شود.
این مشکل به طور مفصل در پست وبلاگ r16 و در مستندات بیونیک توضیح داده شده است.
مشکل : ساخت شما APIهایی را می خواهد که در minSdkVersion
شما وجود ندارند.
راه حل : _FILE_OFFSET_BITS=64
را غیرفعال کنید یا minSdkVersion
خود را افزایش دهید.
تعریف نامعلوم یا ضمنی mmap
ممکن است خطای زیر را در C++ مشاهده کنید:
خطا: استفاده از شناسه اعلام نشده "mmap"
یا خطای زیر در C:
هشدار: اعلان ضمنی تابع 'mmap' در C99 نامعتبر است
استفاده از _FILE_OFFSET_BITS=64
به کتابخانه C دستور می دهد که به جای mmap
از mmap64
استفاده کند. mmap64
تا android-21
در دسترس نبود. اگر مقدار minSdkVersion
شما کمتر از 21 باشد، کتابخانه C حاوی mmap
نیست که با _FILE_OFFSET_BITS=64
سازگار باشد، بنابراین تابع در دسترس نیست.
minSdkVersion
بالاتر از سطح API دستگاه تنظیم شده است
سطح API که با NDK میسازید، معنای بسیار متفاوتی با compileSdkVersion
برای جاوا دارد. سطح API NDK حداقل سطح API پشتیبانی شده برنامه شما است. در ndk-build، این تنظیمات APP_PLATFORM
شما است. با CMake، این -DANDROID_PLATFORM
است.
از آنجایی که ارجاعات به توابع معمولاً هنگام بارگیری کتابخانه ها به جای زمانی که برای اولین بار فراخوانی می شوند حل می شوند، نمی توانید به API هایی که همیشه وجود ندارند ارجاع دهید و از استفاده آنها با بررسی سطح API محافظت کنید. اگر اصلاً به آنها ارجاع داده شود باید حضور داشته باشند.
مشکل : سطح API NDK شما بالاتر از API پشتیبانی شده توسط دستگاه شما است.
راه حل : سطح NDK API ( APP_PLATFORM
) خود را روی حداقل نسخه اندرویدی که برنامه شما پشتیبانی می کند، تنظیم کنید.
ساخت سیستم | تنظیم |
---|---|
ndk-build | APP_PLATFORM |
CMake | ANDROID_PLATFORM |
externalNativeBuild | android.minSdkVersion |
برای سایر سیستمهای ساخت، استفاده از NDK با سایر سیستمهای ساخت را ببینید.
نمی توان نمادهای __aeabi
را پیدا کرد
پیام زیر:
UnsatisfiedLinkError: dlopen ناموفق: نمی توان نماد "
__aeabi_memcpy
" را پیدا کرد
نمونه ای از خطاهای احتمالی زمان اجرا است. این خطاها زمانی که می خواهید کتابخانه های بومی خود را بارگیری کنید، در گزارش ظاهر می شوند. نماد ممکن است یکی از __aeabi_*
باشد. به نظر می رسد __aeabi_memcpy
و __aeabi_memclr
رایج ترین هستند.
این مشکل در شماره 126 ذکر شده است
نمی توان نماد rand
پیدا کرد
برای پیغام ثبت خطای زیر:
UnsatisfiedLinkError: dlopen ناموفق بود: نمی توان نماد "
rand
" را پیدا کرد
این پاسخ دقیق Stack Overflow را ببینید.
ارجاع تعریف نشده به __atomic_*
مشکل : برخی از ABI ها برای ارائه برخی پیاده سازی ها برای عملیات اتمی نیاز به libatomic
دارند.
راه حل : هنگام پیوند دادن -latomic
را اضافه کنید.
برای پیغام خطای زیر:
خطا: ارجاع تعریف نشده به "
__atomic_exchange_4
"
نماد واقعی در اینجا ممکن است هر چیزی با پیشوند __atomic_
باشد.
RTTI/ استثناها در سراسر مرزهای کتابخانه کار نمی کنند
مشکل : زمانی که از مرزهای کتابخانه مشترک پرتاب می شود، استثناها ثبت نمی شوند یا dynamic_cast
ناموفق است.
راه حل : یک تابع کلیدی را به انواع خود اضافه کنید. یک تابع کلیدی اولین تابع مجازی غیر خالص و خارج از خط برای یک نوع است. برای مثال به بحث در شماره 533 مراجعه کنید.
C++ ABI بیان میکند که دو شیء دارای نوع یکسانی هستند اگر و فقط در صورتی که نشانگرهای type_info
آنها یکسان باشد. استثناها فقط در صورتی قابل دریافت هستند که type_info
برای catch با استثنای پرتاب شده مطابقت داشته باشد. همین قانون برای dynamic_cast
نیز صدق می کند.
وقتی یک نوع تابع کلیدی ندارد، typeinfo
آن به عنوان یک نماد ضعیف منتشر می شود و اطلاعات نوع مطابق با بارگیری کتابخانه ها ادغام می شوند. هنگامی که کتابخانه ها به صورت پویا پس از بارگیری فایل اجرایی بارگیری می شوند (به عبارت دیگر، از طریق dlopen
یا System.loadLibrary
)، ممکن است بارکننده امکان ادغام اطلاعات نوع برای کتابخانه های بارگذاری شده را نداشته باشد. وقتی این اتفاق می افتد، این دو نوع برابر در نظر گرفته نمی شوند.
استفاده از کتابخانه های از پیش ساخته شده ناهماهنگ
استفاده از کتابخانه های از پیش ساخته شده - اینها معمولاً کتابخانه های شخص ثالث هستند - در برنامه شما نیاز به کمی دقت بیشتری دارد. به طور کلی از قوانین زیر آگاه باشید:
حداقل سطح API برنامه حاصل حداکثر
minSdkVersion
های همه کتابخانه های برنامه است.اگر
minSdkVersion
شما 16 است، اما از یک کتابخانه از پیش ساخته شده استفاده می کنید که در برابر 21 ساخته شده است، حداقل سطح API برنامه حاصل 21 است. اگر کتابخانه از پیش ساخته شده ثابت باشد، رعایت نکردن آن در زمان ساخت قابل مشاهده خواهد بود، اما ممکن است نباشد. تا زمان اجرا برای کتابخانه های مشترک از پیش ساخته شده ظاهر می شود.همه کتابخانه ها باید با همان نسخه NDK تولید شوند.
این قانون کمی انعطافپذیرتر از بسیاری از قوانین است، زیرا شکستگیها نادر است، اما سازگاری بین کتابخانههایی که با نسخههای اصلی مختلف NDK ساخته شدهاند تضمین نمیشود. C++ ABI پایدار نیست و در گذشته تغییر کرده است.
برنامههای دارای چندین کتابخانه مشترک باید از STL مشترک استفاده کنند.
مانند STLهای ناهمخوان، اگر دقت زیادی به کار گرفته شود، می توان از مشکلات ناشی از آن جلوگیری کرد، اما بهتر است فقط از بروز مشکل جلوگیری کنید. بهترین راه برای جلوگیری از این مشکل این است که از داشتن چندین کتابخانه مشترک در برنامه خود اجتناب کنید.
این سند فهرستی جزئی از متداولترین اشکالهایی است که ممکن است هنگام استفاده از NDK با آنها مواجه شوید و راهحلهای آنها (در صورت موجود بودن).
استفاده از _FILE_OFFSET_BITS=64
با سطوح API قدیمی تر
قبل از هدرهای یکپارچه ، NDK از _FILE_OFFSET_BITS=64
پشتیبانی نمی کرد. اگر هنگام ساخت برنامه خود آن را تعریف کرده باشید، بی سر و صدا نادیده گرفته می شود. گزینه _FILE_OFFSET_BITS=64
اکنون با هدرهای یکپارچه پشتیبانی میشود، اما در نسخههای قدیمی اندروید، تعداد کمی از APIهای off_t
به عنوان یک نوع off64_t
در دسترس بودند. بنابراین، استفاده از این ویژگی با سطوح API قدیمی منجر به در دسترس بودن توابع کمتری می شود.
این مشکل به طور مفصل در پست وبلاگ r16 و در مستندات بیونیک توضیح داده شده است.
مشکل : ساخت شما APIهایی را می خواهد که در minSdkVersion
شما وجود ندارند.
راه حل : _FILE_OFFSET_BITS=64
را غیرفعال کنید یا minSdkVersion
خود را افزایش دهید.
تعریف نامعلوم یا ضمنی mmap
ممکن است خطای زیر را در C++ مشاهده کنید:
خطا: استفاده از شناسه اعلام نشده "mmap"
یا خطای زیر در C:
هشدار: اعلان ضمنی تابع 'mmap' در C99 نامعتبر است
استفاده از _FILE_OFFSET_BITS=64
به کتابخانه C دستور می دهد که به جای mmap
از mmap64
استفاده کند. mmap64
تا android-21
در دسترس نبود. اگر مقدار minSdkVersion
شما کمتر از 21 باشد، کتابخانه C حاوی mmap
نیست که با _FILE_OFFSET_BITS=64
سازگار باشد، بنابراین تابع در دسترس نیست.
minSdkVersion
بالاتر از سطح API دستگاه تنظیم شده است
سطح API که با NDK میسازید، معنای بسیار متفاوتی با compileSdkVersion
برای جاوا دارد. سطح API NDK حداقل سطح API پشتیبانی شده برنامه شما است. در ndk-build، این تنظیمات APP_PLATFORM
شما است. با CMake، این -DANDROID_PLATFORM
است.
از آنجایی که ارجاعات به توابع معمولاً هنگام بارگیری کتابخانه ها به جای زمانی که برای اولین بار فراخوانی می شوند حل می شوند، نمی توانید به API هایی که همیشه وجود ندارند ارجاع دهید و از استفاده آنها با بررسی سطح API محافظت کنید. اگر اصلاً به آنها ارجاع داده شود باید حضور داشته باشند.
مشکل : سطح API NDK شما بالاتر از API پشتیبانی شده توسط دستگاه شما است.
راه حل : سطح NDK API ( APP_PLATFORM
) خود را روی حداقل نسخه اندرویدی که برنامه شما پشتیبانی می کند، تنظیم کنید.
ساخت سیستم | تنظیم |
---|---|
ndk-build | APP_PLATFORM |
CMake | ANDROID_PLATFORM |
externalNativeBuild | android.minSdkVersion |
برای سایر سیستمهای ساخت، استفاده از NDK با سایر سیستمهای ساخت را ببینید.
نمی توان نمادهای __aeabi
را پیدا کرد
پیام زیر:
UnsatisfiedLinkError: dlopen ناموفق: نمی توان نماد "
__aeabi_memcpy
" را پیدا کرد
نمونه ای از خطاهای احتمالی زمان اجرا است. این خطاها زمانی که می خواهید کتابخانه های بومی خود را بارگیری کنید، در گزارش ظاهر می شوند. نماد ممکن است یکی از __aeabi_*
باشد. به نظر می رسد __aeabi_memcpy
و __aeabi_memclr
رایج ترین هستند.
این مشکل در شماره 126 ذکر شده است
نمی توان نماد rand
پیدا کرد
برای پیغام ثبت خطای زیر:
UnsatisfiedLinkError: dlopen ناموفق بود: نمی توان نماد "
rand
" را پیدا کرد
این پاسخ دقیق Stack Overflow را ببینید.
ارجاع تعریف نشده به __atomic_*
مشکل : برخی از ABI ها برای ارائه برخی پیاده سازی ها برای عملیات اتمی نیاز به libatomic
دارند.
راه حل : هنگام پیوند دادن -latomic
را اضافه کنید.
برای پیغام خطای زیر:
خطا: ارجاع تعریف نشده به "
__atomic_exchange_4
"
نماد واقعی در اینجا ممکن است هر چیزی با پیشوند __atomic_
باشد.
RTTI/ استثناها در سراسر مرزهای کتابخانه کار نمی کنند
مشکل : زمانی که از مرزهای کتابخانه مشترک پرتاب می شود، استثناها ثبت نمی شوند یا dynamic_cast
ناموفق است.
راه حل : یک تابع کلیدی را به انواع خود اضافه کنید. یک تابع کلیدی اولین تابع مجازی غیر خالص و خارج از خط برای یک نوع است. برای مثال به بحث در شماره 533 مراجعه کنید.
C++ ABI بیان میکند که دو شیء دارای نوع یکسانی هستند اگر و فقط در صورتی که نشانگرهای type_info
آنها یکسان باشد. استثناها فقط در صورتی قابل دریافت هستند که type_info
برای catch با استثنای پرتاب شده مطابقت داشته باشد. همین قانون برای dynamic_cast
نیز صدق می کند.
وقتی یک نوع تابع کلیدی ندارد، typeinfo
آن به عنوان یک نماد ضعیف منتشر می شود و اطلاعات نوع مطابق با بارگیری کتابخانه ها ادغام می شوند. هنگامی که کتابخانه ها به صورت پویا پس از بارگیری فایل اجرایی بارگیری می شوند (به عبارت دیگر، از طریق dlopen
یا System.loadLibrary
)، ممکن است بارکننده امکان ادغام اطلاعات نوع برای کتابخانه های بارگذاری شده را نداشته باشد. وقتی این اتفاق می افتد، این دو نوع برابر در نظر گرفته نمی شوند.
استفاده از کتابخانه های از پیش ساخته شده ناهماهنگ
استفاده از کتابخانه های از پیش ساخته شده - اینها معمولاً کتابخانه های شخص ثالث هستند - در برنامه شما نیاز به کمی دقت بیشتری دارد. به طور کلی از قوانین زیر آگاه باشید:
حداقل سطح API برنامه حاصل حداکثر
minSdkVersion
های همه کتابخانه های برنامه است.اگر
minSdkVersion
شما 16 است، اما از یک کتابخانه از پیش ساخته شده استفاده می کنید که در برابر 21 ساخته شده است، حداقل سطح API برنامه حاصل 21 است. اگر کتابخانه از پیش ساخته شده ثابت باشد، رعایت نکردن آن در زمان ساخت قابل مشاهده خواهد بود، اما ممکن است نباشد. تا زمان اجرا برای کتابخانه های مشترک از پیش ساخته شده ظاهر می شود.همه کتابخانه ها باید با همان نسخه NDK تولید شوند.
این قانون کمی انعطافپذیرتر از بسیاری از قوانین است، زیرا شکستگیها نادر است، اما سازگاری بین کتابخانههایی که با نسخههای اصلی مختلف NDK ساخته شدهاند تضمین نمیشود. C++ ABI پایدار نیست و در گذشته تغییر کرده است.
برنامههای دارای چندین کتابخانه مشترک باید از STL مشترک استفاده کنند.
مانند STLهای ناهمخوان، اگر دقت زیادی به کار گرفته شود، می توان از مشکلات ناشی از آن جلوگیری کرد، اما بهتر است فقط از بروز مشکل جلوگیری کنید. بهترین راه برای جلوگیری از این مشکل این است که از داشتن چندین کتابخانه مشترک در برنامه خود اجتناب کنید.