مشکلات و راه حل های رایج

این سند فهرستی جزئی از متداول‌ترین اشکال‌هایی است که ممکن است هنگام استفاده از 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های ناهمخوان، اگر دقت زیادی به کار گرفته شود، می توان از مشکلات ناشی از آن جلوگیری کرد، اما بهتر است فقط از بروز مشکل جلوگیری کنید. بهترین راه برای جلوگیری از این مشکل این است که از داشتن چندین کتابخانه مشترک در برنامه خود اجتناب کنید.