برنامه نویسی

افزودن NDK به یک برنامه اندروید موجود و استفاده از C++ برای ورود

Summarize this content to 400 words in Persian Lang

فهرست مطالب

هدف از این پست وبلاگ؟
NDK و CMake را نصب کنید
Gradle را به کد بومی خود پیوند دهید
یک اسکریپت ساخت CMake ایجاد کنید
JNI (رابط بومی جاوا.)
کد ++C
JNI (رابط بومی جاوا.)
در حال اجرای کد

منابع

برنامه من در فروشگاه Google Play

کد GitHub برنامه من

هدف این پست وبلاگ

هدف این پست وبلاگ ساده است. از کد ++C برای ثبت یک عبارت در Logcat Android Studio استفاده کنید

NDK و CMake را نصب کنید

مستندات
اولین کاری که باید انجام دهیم این است که Android Native Development Kit (NDK) و CMake (ابزار ساخت خارجی که در کنار Gradle کار می کند) را نصب کنیم.
شما می‌توانید نسخه دقیق‌تری را در داخل مستندات بخوانید، اما اساساً در داخل استودیو اندروید می‌رویم،
Tools > SDK Manager > SDK Tools tab > Select the NDK (Side by side) and CMake checkboxes > select ok

Gradle را به کد بومی خود پیوند دهید

مستندات
حال برای اینکه بتوانیم از کد ++C خود با Gradle استفاده کنیم، باید به Gradle بگوییم که فایل ساخت CMake ما کجاست. سپس Gradle می‌تواند از دستورالعمل‌هایی که در داخل این فایل ارائه می‌دهیم استفاده کند و کد ++C ما را بسازد
می‌توانیم به Gradle در داخل فایل build.gradle برنامه اطلاع دهیم:

android {

defaultConfig {…}
buildTypes {…}

// Encapsulates your external native build configurations.
externalNativeBuild {

// Encapsulates your CMake build configurations.
cmake {

// Provides a relative path to your CMake build script.
path ‘src/main/cpp/CMakeLists.txt’
}
}
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

را externalNativeBuild بخش بخش مهمی است در این مرحله باید بتوانید بیلد Gradle را اجرا کنید و خطای مبنی بر اینکه فایل: src/main/cpp/CMakeLists.txt پیدا نمی شود. این خطای خوبی است، ما در مسیر درستی هستیم

یک اسکریپت ساخت CMake ایجاد کنید

# Sets the minimum version of CMake required to build your native library.
# This ensures that a certain set of CMake features is available to
# your build.

cmake_minimum_required(VERSION 3.4.1)

# Specifies a library name, specifies whether the library is STATIC or
# SHARED, and provides relative paths to the source code. You can
# define multiple libraries by adding multiple add_library() commands,
# and CMake builds them for you. When you build your app, Gradle
# automatically packages shared libraries with your APK.

#Add a library to the project using the specified source files.
add_library(gl_code SHARED
gl_code.cpp)

# add lib dependencies
target_link_libraries(gl_code
android
log
EGL
GLESv2)

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

بخش مهم این کد عبارت است از add_library(gl_code SHARED gl_code.cpp). بنابراین اجازه دهید آن را کاهش دهیم:
add_library(): به عنوان در مستندات آمده است: Adding a library to the project using the specified source files. که اساساً به این معنی است که ما در حال ایجاد مکانی برای کد ++C خود هستیم
gl_code: باید یک شناسه منحصر به فرد جهانی باشد و به این صورت است که ما به کد ++C خود در سراسر برنامه مراجعه می کنیم. اگر این نام را تغییر دهید، باید پروژه خود را پاک کنید و سپس آن را دوباره بسازید تا دوباره کار کند
SHARED: فقط به این معنی است که یک کتابخانه پویا است که ممکن است توسط سایر اهداف مرتبط شود و در زمان اجرا بارگذاری شود.
gl_code.cpp: این فایل منبعی است که در کتابخانه کامپایل می شود (فایلی که کد C++ ما را در خود نگه می دارد).

JNI (رابط بومی جاوا.)

مستندات
همانطور که در مستندات آمده است: It defines a way for the bytecode that Android compiles from managed code (written in the Java or Kotlin programming languages) to interact with native code (written in C/C++). JNI is vendor-neutral, has support for loading code from dynamic shared libraries, and while cumbersome at times is reasonably efficient.

که واقعاً فقط برای صحبت های نادر است: ما می توانیم یک کلاس Kotlin/Java ایجاد کنیم و از کلاس مذکور برای اجرای برخی از کدهای ++C استفاده کنیم.
ما می توانیم این کار را به صورت زیر انجام دهیم:

class NativeLoading {

init {
System.loadLibrary(“gl_code”);
}

external fun init()
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

را System.loadLibrary(“gl_code”) چیزی است که به ما امکان دسترسی به آن را می دهد gl_code.cpp فایلی که قبلا ذکر کردیم و شناسه آن را به صورت زیر تعریف کردیم: gl_code

کد C++ واقعی

بنابراین اکنون می‌توانیم چند کد C++ ایجاد کنیم که یک عبارت را برای ما ثبت کند:

#include

#include

#define LOGI(…) ((void)__android_log_print(ANDROID_LOG_INFO, “native-lib”, __VA_ARGS__))

extern “C”
JNIEXPORT void JNICALL
Java_com_example_clicker_nativeLibraryClasses_NativeLoading_init(JNIEnv *env, jobject thiz) {

LOGI(“int %s,”, “————–THIS IS A LOG FROM THE NATIVE SIDE ———————-“);

}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

من عذرخواهی می کنم

وقت من برای نوشتن این پست وبلاگ تمام شده است (من یک ساعت زمان تعیین کردم) بنابراین از اینجا به بعد، Chat GPT کد را برای شما توضیح می دهد:

1. فایل های هدر

#include
#include
#include :

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این شامل فایل هدر JNI است که توابع و انواع لازم را برای تعامل بین Java/Kotlin و C++ فراهم می کند. JNI اجازه می دهد تا کد بومی (C/C++) با اشیاء و متدهای جاوا در ماشین مجازی ارتباط برقرار کند. #include : این شامل ابزار ورود به سیستم Android است که برای چاپ پیام ها در گزارش استفاده می شود. هدر android/log.h توابعی را برای ثبت پیام‌ها در کد بومی ارائه می‌کند (مشابه Log.d() در Java/Kotlin).

2. ثبت تعریف ماکرو

#define LOGI(…) ((void)__android_log_print(ANDROID_LOG_INFO, “native-lib”, __VA_ARGS__))

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

LOGI: یک ماکرو برای ثبت پیام های اطلاعاتی تعریف می کند. ماکروها در C/C++ مانند کدهای مختصر هستند که با کامپایل شدن برنامه گسترش می یابند.android_log_print(): این تابع یک پیام را ثبت می کند. این یک سطح اولویت (ANDROID_LOG_INFO برای پیام های اطلاعاتی)، یک برچسب (“native-lib” در این مورد، که به شناسایی منبع گزارش کمک می کند) و پیام (VA_ARGS__ به آرگومان های متغیر اجازه می دهد).ماکرو ثبت پیام‌ها را بدون تایپ کردن تابع کامل در هر بار، با استفاده از LOGI (…) آسان می‌کند.

3. C++ خارجی “C” اعلامیه

extern “C”

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

خارجی “C” به کامپایلر می گوید که از پیوند C برای کد زیر استفاده کند. از آنجایی که توابع JNI باید با قراردادهای فراخوانی جاوا (که از پیوند C پیروی می کنند) سازگار باشند، این تضمین می کند که نام تابع توسط کامپایلر C++ مخدوش نشود.

4. JNIEXPORT و JNICALL

JNIEXPORT void JNICALL

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

JNIEXPORT: یک ماکرو نشان می دهد که این تابع به عنوان بخشی از رابط JNI استفاده می شود و آن را از جاوا/کوتلین قابل دسترسی می کند.

JNICALL: یک ماکرو که تضمین می کند تابع از قرارداد فراخوانی صحیح برای JNI استفاده می کند (برای مدیریت تعامل بین جاوا و C++ استفاده می شود).

5. اعلامیه عملکرد JNI

Java_com_example_clicker_nativeLibraryClasses_NativeLoading_init(JNIEnv *env, jobject thiz)

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این پیاده سازی بومی متد ()init است که شما در Kotlin به عنوان init () سرگرم کننده خارجی اعلام کردید.نام تابع از یک قرارداد نامگذاری سختگیرانه JNI پیروی می کند: Java_packageName_className_methodName. در این مورد:Java_com_example_clicker_nativeLibraryClasses_NativeLoading_init مربوط به تابع init() در کلاس NativeLoading واقع در بسته com.example.clicker.nativeLibraryClasses است.تابع دارای دو پارامتر است:JNIEnv *env: اشاره گر به محیط JNI است که به توابع JNI مانند ایجاد اشیاء جاوا، روش های فراخوانی و غیره دسترسی می دهد.jobject thiz: اشاره ای به نمونه فراخوانی شی جاوا/کوتلین (این).

6. ثبت یک پیام

LOGI(“int %s,”, “————–THIS IS A LOG FROM THE NATIVE SIDE ———————-“);

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این خط یک پیام اطلاعاتی را از کد اصلی ثبت می کند. از ماکرو LOGI که ​​قبلاً تعریف شده بود برای چاپ پیام استفاده می کند:”int %s,”: این یک رشته قالب بندی شده است. %s یک مکان نگهدار برای مقدار رشته است که با آرگومان دوم جایگزین می شود.”————– این سیاهه گزارش از سمت بومی است ————————————————————————————- در جایگیر درج شود.خلاصهاین تابع C++ زمانی که تابع init() از Kotlin فراخوانی می شود، پیامی را ثبت می کند.این تابع به استانداردهای JNI پایبند است و به آن اجازه می دهد با Kotlin/Java تعامل داشته باشد.ماکرو LOGI() ورود به کد بومی را ساده می‌کند و پیام‌ها را با تگ «native-lib» به لاگ اندروید ارسال می‌کند.این تنظیمات برای اشکال زدایی و ورود به سیستم از کد بومی در اندروید مفید است. هنگامی که NativeLoading.init() را از Kotlin فرا می خوانید، این کد C++ اجرا می شود و یک پیام گزارش در لاگ اندروید (logcat) با این پیام ظاهر می شود: “—————THIS سیاهه ای است از سمت بومی ———————–.

اجرای کد:

برای اجرای کد، آن را مانند هر نوع کلاس کاتلین ساده پیاده سازی می کنیم:

val nativeCode= NativeLoading()
nativeCode.init()

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

با انجام این کار یک لاگ مانند هر لاگ دیگر تولید می شود

نتیجه گیری

از اینکه وقت خود را برای خواندن این پست وبلاگ من اختصاص دادید متشکرم. اگر سوال یا ابهامی دارید لطفا در زیر کامنت بگذارید یا با من تماس بگیرید توییتر.

فهرست مطالب

  1. هدف از این پست وبلاگ؟
  2. NDK و CMake را نصب کنید
  3. Gradle را به کد بومی خود پیوند دهید
  4. یک اسکریپت ساخت CMake ایجاد کنید
  5. JNI (رابط بومی جاوا.)
  6. کد ++C
  7. JNI (رابط بومی جاوا.)
  8. در حال اجرای کد

منابع

برنامه من در فروشگاه Google Play

کد GitHub برنامه من

هدف این پست وبلاگ

  • هدف این پست وبلاگ ساده است. از کد ++C برای ثبت یک عبارت در Logcat Android Studio استفاده کنید

NDK و CMake را نصب کنید

Gradle را به کد بومی خود پیوند دهید

یک اسکریپت ساخت CMake ایجاد کنید

JNI (رابط بومی جاوا.)

کد C++ واقعی

من عذرخواهی می کنم

1. فایل های هدر

2. ثبت تعریف ماکرو

LOGI: یک ماکرو برای ثبت پیام های اطلاعاتی تعریف می کند. ماکروها در C/C++ مانند کدهای مختصر هستند که با کامپایل شدن برنامه گسترش می یابند.
android_log_print(): این تابع یک پیام را ثبت می کند. این یک سطح اولویت (ANDROID_LOG_INFO برای پیام های اطلاعاتی)، یک برچسب (“native-lib” در این مورد، که به شناسایی منبع گزارش کمک می کند) و پیام (VA_ARGS__ به آرگومان های متغیر اجازه می دهد).
ماکرو ثبت پیام‌ها را بدون تایپ کردن تابع کامل در هر بار، با استفاده از LOGI (…) آسان می‌کند.

3. C++ خارجی “C” اعلامیه

خارجی “C” به کامپایلر می گوید که از پیوند C برای کد زیر استفاده کند. از آنجایی که توابع JNI باید با قراردادهای فراخوانی جاوا (که از پیوند C پیروی می کنند) سازگار باشند، این تضمین می کند که نام تابع توسط کامپایلر C++ مخدوش نشود.

4. JNIEXPORT و JNICALL

JNIEXPORT: یک ماکرو نشان می دهد که این تابع به عنوان بخشی از رابط JNI استفاده می شود و آن را از جاوا/کوتلین قابل دسترسی می کند.

JNICALL: یک ماکرو که تضمین می کند تابع از قرارداد فراخوانی صحیح برای JNI استفاده می کند (برای مدیریت تعامل بین جاوا و C++ استفاده می شود).

5. اعلامیه عملکرد JNI

این پیاده سازی بومی متد ()init است که شما در Kotlin به عنوان init () سرگرم کننده خارجی اعلام کردید.
نام تابع از یک قرارداد نامگذاری سختگیرانه JNI پیروی می کند: Java_packageName_className_methodName. در این مورد:
Java_com_example_clicker_nativeLibraryClasses_NativeLoading_init مربوط به تابع init() در کلاس NativeLoading واقع در بسته com.example.clicker.nativeLibraryClasses است.
تابع دارای دو پارامتر است:
JNIEnv *env: اشاره گر به محیط JNI است که به توابع JNI مانند ایجاد اشیاء جاوا، روش های فراخوانی و غیره دسترسی می دهد.
jobject thiz: اشاره ای به نمونه فراخوانی شی جاوا/کوتلین (این).

6. ثبت یک پیام

این خط یک پیام اطلاعاتی را از کد اصلی ثبت می کند. از ماکرو LOGI که ​​قبلاً تعریف شده بود برای چاپ پیام استفاده می کند:
“int %s,”: این یک رشته قالب بندی شده است. %s یک مکان نگهدار برای مقدار رشته است که با آرگومان دوم جایگزین می شود.
“————– این سیاهه گزارش از سمت بومی است ————————————————————————————- در جایگیر درج شود.
خلاصه
این تابع C++ زمانی که تابع init() از Kotlin فراخوانی می شود، پیامی را ثبت می کند.
این تابع به استانداردهای JNI پایبند است و به آن اجازه می دهد با Kotlin/Java تعامل داشته باشد.
ماکرو LOGI() ورود به کد بومی را ساده می‌کند و پیام‌ها را با تگ «native-lib» به لاگ اندروید ارسال می‌کند.
این تنظیمات برای اشکال زدایی و ورود به سیستم از کد بومی در اندروید مفید است. هنگامی که NativeLoading.init() را از Kotlin فرا می خوانید، این کد C++ اجرا می شود و یک پیام گزارش در لاگ اندروید (logcat) با این پیام ظاهر می شود: “—————THIS سیاهه ای است از سمت بومی ———————–.

اجرای کد:

نتیجه گیری

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

همچنین ببینید
بستن
دکمه بازگشت به بالا