1. ভূমিকা
ডার্টের এফএফআই (বিদেশী ফাংশন ইন্টারফেস) ফ্লটার অ্যাপগুলিকে বিদ্যমান নেটিভ লাইব্রেরি ব্যবহার করতে দেয় যা একটি C API প্রকাশ করে । ডার্ট অ্যান্ড্রয়েড, আইওএস, উইন্ডোজ, ম্যাকওএস এবং লিনাক্সে এফএফআই সমর্থন করে। ওয়েবের জন্য, ডার্ট জাভাস্ক্রিপ্ট ইন্টারপ সমর্থন করে, কিন্তু সেই বিষয় এই কোডল্যাবে কভার করা হয় না।
আপনি কি নির্মাণ করবেন
এই কোডল্যাবে, আপনি একটি মোবাইল এবং ডেস্কটপ প্লাগইন তৈরি করেন যা একটি সি লাইব্রেরি ব্যবহার করে। এই API এর সাথে, আপনি একটি সহজ উদাহরণ অ্যাপ লিখবেন যা প্লাগইন ব্যবহার করে। আপনার প্লাগইন এবং অ্যাপ হবে:
- আপনার নতুন ফ্লাটার প্লাগইনে সি লাইব্রেরি সোর্স কোড আমদানি করুন
- উইন্ডোজ, ম্যাকওএস, লিনাক্স, অ্যান্ড্রয়েড এবং আইওএসে তৈরি করার জন্য প্লাগইনটিকে কাস্টমাইজ করুন
- একটি জাভাস্ক্রিপ্ট REPL এর জন্য প্লাগইন ব্যবহার করে এমন একটি অ্যাপ্লিকেশন তৈরি করুন (পড়ুন রিভিল প্রিন্ট লুপ)
আপনি কি শিখবেন
এই কোডল্যাবে আপনি ডেস্কটপ এবং মোবাইল উভয় প্ল্যাটফর্মে একটি FFI-ভিত্তিক ফ্লাটার প্লাগইন তৈরি করার জন্য প্রয়োজনীয় ব্যবহারিক জ্ঞান শিখবেন, যার মধ্যে রয়েছে:
- একটি ডার্ট এফএফআই ভিত্তিক ফ্লাটার প্লাগইন টেমপ্লেট তৈরি করা হচ্ছে
- একটি C লাইব্রেরির জন্য বাইন্ডিং কোড তৈরি করতে
ffigen
প্যাকেজ ব্যবহার করে - অ্যান্ড্রয়েড, উইন্ডোজ এবং লিনাক্সের জন্য একটি ফ্লটার এফএফআই প্লাগইন তৈরি করতে CMake ব্যবহার করে
- iOS এবং macOS-এর জন্য একটি Flutter FFI প্লাগইন তৈরি করতে CocoaPods ব্যবহার করা
আপনি কি প্রয়োজন হবে
- অ্যান্ড্রয়েড ডেভেলপমেন্টের জন্য অ্যান্ড্রয়েড স্টুডিও 4.1 বা তার পরে
- iOS এবং macOS ডেভেলপমেন্টের জন্য Xcode 13 বা তার পরে
- উইন্ডোজ ডেস্কটপ ডেভেলপমেন্টের জন্য "C++ এর সাথে ডেস্কটপ ডেভেলপমেন্ট" ওয়ার্কলোড সহ ভিজ্যুয়াল স্টুডিও 2022 বা ভিজ্যুয়াল স্টুডিও বিল্ড টুল 2022
- ফ্লটার SDK
- আপনি যে প্ল্যাটফর্মগুলিতে বিকাশ করবেন তার জন্য যে কোনও প্রয়োজনীয় বিল্ড সরঞ্জাম (উদাহরণস্বরূপ, CMake, CocoaPods, এবং তাই)।
- আপনি যে প্ল্যাটফর্মগুলিতে বিকাশ করবেন তার জন্য LLVM । LLVM কম্পাইলার টুল স্যুটটি ডার্টে উন্মুক্ত এফএফআই বাইন্ডিং তৈরি করতে সি হেডার ফাইল পার্স করতে
ffigen
ব্যবহার করে। - একটি কোড সম্পাদক, যেমন ভিজ্যুয়াল স্টুডিও কোড ।
2. শুরু করা
ffigen
টুলিং হল ফ্লটারের সাম্প্রতিক সংযোজন। আপনি নিশ্চিত করতে পারেন যে আপনার ফ্লাটার ইনস্টলেশনটি নিম্নলিখিত কমান্ডটি চালিয়ে বর্তমান স্থিতিশীল রিলিজ চালাচ্ছে।
$ flutter doctor Doctor summary (to see all details, run flutter doctor -v): [✓] Flutter (Channel stable, 3.3.9, on macOS 13.1 22C65 darwin-arm, locale en) [✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0) [✓] Xcode - develop for iOS and macOS (Xcode 14.1) [✓] Chrome - develop for the web [✓] Android Studio (version 2021.2) [✓] IntelliJ IDEA Community Edition (version 2022.2.2) [✓] VS Code (version 1.74.0) [✓] Connected device (2 available) [✓] HTTP Host Availability • No issues found!
নিশ্চিত করুন যে flutter doctor
আউটপুট বলে যে আপনি স্থিতিশীল চ্যানেলে আছেন এবং সাম্প্রতিক স্থিতিশীল ফ্লাটার রিলিজ উপলব্ধ নেই। আপনি যদি স্থিতিশীল না থাকেন, বা আরও সাম্প্রতিক রিলিজ পাওয়া যায়, তাহলে আপনার ফ্লাটার টুলিংকে গতিতে আনতে নিম্নলিখিত দুটি কমান্ড চালান।
$ flutter channel stable $ flutter upgrade
আপনি এই কোডল্যাবে এই ডিভাইসগুলির যেকোনো একটি ব্যবহার করে কোডটি চালাতে পারেন:
- আপনার ডেভেলপমেন্ট কম্পিউটার (আপনার প্লাগইন এবং উদাহরণ অ্যাপের ডেস্কটপ বিল্ডের জন্য)
- আপনার কম্পিউটারের সাথে সংযুক্ত এবং বিকাশকারী মোডে সেট করা একটি শারীরিক Android বা iOS ডিভাইস৷
- আইওএস সিমুলেটর (এক্সকোড সরঞ্জামগুলি ইনস্টল করা প্রয়োজন)
- অ্যান্ড্রয়েড এমুলেটর (অ্যান্ড্রয়েড স্টুডিওতে সেটআপ প্রয়োজন)
3. প্লাগইন টেমপ্লেট তৈরি করুন
Flutter প্লাগইন বিকাশের সাথে শুরু করা
প্লাগইনগুলির জন্য টেমপ্লেট সহ ফ্লাটার জাহাজ যা শুরু করা সহজ করে। আপনি যখন প্লাগইন টেমপ্লেট তৈরি করেন, আপনি কোন ভাষা ব্যবহার করতে চান তা নির্দিষ্ট করতে পারেন।
প্লাগইন টেমপ্লেট ব্যবহার করে আপনার প্রকল্প তৈরি করতে আপনার কাজের ডিরেক্টরিতে নিম্নলিখিত কমান্ডটি চালান:
$ flutter create --template=plugin_ffi \ --platforms=android,ios,linux,macos,windows ffigen_app
--platforms
প্যারামিটার নির্দিষ্ট করে যে আপনার প্লাগইন কোন প্ল্যাটফর্ম সমর্থন করবে।
আপনি tree
কমান্ড বা আপনার অপারেটিং সিস্টেমের ফাইল এক্সপ্লোরার ব্যবহার করে উত্পন্ন প্রকল্পের বিন্যাস পরিদর্শন করতে পারেন।
$ tree -L 2 ffigen_app ffigen_app ├── CHANGELOG.md ├── LICENSE ├── README.md ├── analysis_options.yaml ├── android │ ├── build.gradle │ ├── ffigen_app_android.iml │ ├── local.properties │ ├── settings.gradle │ └── src ├── example │ ├── README.md │ ├── analysis_options.yaml │ ├── android │ ├── ffigen_app_example.iml │ ├── ios │ ├── lib │ ├── linux │ ├── macos │ ├── pubspec.lock │ ├── pubspec.yaml │ └── windows ├── ffigen.yaml ├── ffigen_app.iml ├── ios │ ├── Classes │ └── ffigen_app.podspec ├── lib │ ├── ffigen_app.dart │ └── ffigen_app_bindings_generated.dart ├── linux │ └── CMakeLists.txt ├── macos │ ├── Classes │ └── ffigen_app.podspec ├── pubspec.lock ├── pubspec.yaml ├── src │ ├── CMakeLists.txt │ ├── ffigen_app.c │ └── ffigen_app.h └── windows └── CMakeLists.txt 17 directories, 26 files
কী তৈরি করা হয়েছে এবং এটি কোথায় অবস্থিত তার অনুভূতি পেতে ডিরেক্টরি কাঠামোর দিকে তাকিয়ে একটি মুহূর্ত ব্যয় করা মূল্যবান। plugin_ffi
টেমপ্লেটটি lib
, android
, ios
, linux
, macos
, এবং windows
নামে প্লাটফর্ম-নির্দিষ্ট ডিরেক্টরি এবং সবচেয়ে গুরুত্বপূর্ণভাবে, একটি example
ডিরেক্টরির অধীনে প্লাগইনের জন্য ডার্ট কোড রাখে।
স্বাভাবিক ফ্লাটার ডেভেলপমেন্টে অভ্যস্ত একজন ডেভেলপারের জন্য, এই কাঠামোটি অদ্ভুত মনে হতে পারে, কারণ শীর্ষ স্তরে কোন এক্সিকিউটেবল সংজ্ঞায়িত নেই। একটি প্লাগইনকে অন্যান্য ফ্লাটার প্রকল্পে অন্তর্ভুক্ত করার জন্য বোঝানো হয়, তবে আপনার প্লাগইন কোড কাজ করছে কিনা তা নিশ্চিত করতে আপনি example
ডিরেক্টরিতে কোডটি বের করবেন।
এটা শুরু করার সময়!
4. উদাহরণ তৈরি করুন এবং চালান
বিল্ড সিস্টেম এবং পূর্বশর্তগুলি সঠিকভাবে ইনস্টল করা হয়েছে এবং প্রতিটি সমর্থিত প্ল্যাটফর্মের জন্য কাজ করছে তা নিশ্চিত করতে, প্রতিটি লক্ষ্যের জন্য জেনারেট করা উদাহরণ অ্যাপ তৈরি করুন এবং চালান।
উইন্ডোজ
আপনি Windows এর একটি সমর্থিত সংস্করণ ব্যবহার করছেন তা নিশ্চিত করুন। এই কোডল্যাবটি উইন্ডোজ 10 এবং উইন্ডোজ 11 এ কাজ করার জন্য পরিচিত।
আপনি হয় আপনার কোড এডিটর থেকে বা কমান্ড লাইনে অ্যাপ্লিকেশনটি তৈরি করতে পারেন।
PS C:\Users\brett\Documents> cd .\ffigen_app\example\ PS C:\Users\brett\Documents\ffigen_app\example> flutter run -d windows Launching lib\main.dart on Windows in debug mode...Building Windows application... Syncing files to device Windows... 160ms Flutter run key commands. r Hot reload. R Hot restart. h List all available interactive commands. d Detach (terminate "flutter run" but leave application running). c Clear the screen q Quit (terminate the application on the device). Running with sound null safety An Observatory debugger and profiler on Windows is available at: http://127.0.0.1:53317/OiKWpyHXxHI=/ The Flutter DevTools debugger and profiler on Windows is available at: http://127.0.0.1:9100?uri=http://127.0.0.1:53317/OiKWpyHXxHI=/
আপনি নিম্নলিখিত মত একটি চলমান অ্যাপ্লিকেশন উইন্ডো দেখতে হবে:
লিনাক্স
নিশ্চিত করুন যে আপনি লিনাক্সের একটি সমর্থিত সংস্করণ ব্যবহার করছেন। এই কোডল্যাবটি Ubuntu 22.04.1
ব্যবহার করে।
একবার আপনি ধাপ 2 এ তালিকাভুক্ত সমস্ত পূর্বশর্ত ইনস্টল করার পরে, একটি টার্মিনালে নিম্নলিখিত কমান্ডগুলি চালান:
$ cd ffigen_app/example $ flutter run -d linux Launching lib/main.dart on Linux in debug mode... Building Linux application... Syncing files to device Linux... 504ms Flutter run key commands. r Hot reload. 🔥🔥🔥 R Hot restart. h List all available interactive commands. d Detach (terminate "flutter run" but leave application running). c Clear the screen q Quit (terminate the application on the device). 💪 Running with sound null safety 💪 An Observatory debugger and profiler on Linux is available at: http://127.0.0.1:36653/Wgek1JGag48=/ The Flutter DevTools debugger and profiler on Linux is available at: http://127.0.0.1:9103?uri=http://127.0.0.1:36653/Wgek1JGag48=/
আপনি নিম্নলিখিত মত একটি চলমান অ্যাপ্লিকেশন উইন্ডো দেখতে হবে:
অ্যান্ড্রয়েড
অ্যান্ড্রয়েডের জন্য আপনি সংকলনের জন্য উইন্ডোজ, ম্যাকওএস বা লিনাক্স ব্যবহার করতে পারেন। প্রথমে, নিশ্চিত করুন যে আপনার ডেভেলপমেন্ট কম্পিউটারের সাথে সংযুক্ত একটি Android ডিভাইস আছে বা আপনি একটি Android এমুলেটর (AVD) উদাহরণ চালাচ্ছেন। নিশ্চিত করুন যে Flutter নিম্নলিখিতগুলি চালিয়ে Android ডিভাইস বা এমুলেটরের সাথে সংযোগ করতে সক্ষম:
$ flutter devices 3 connected devices: sdk gphone64 arm64 (mobile) • emulator-5554 • android-arm64 • Android 12 (API 32) (emulator) macOS (desktop) • macos • darwin-arm64 • macOS 13.1 22C65 darwin-arm Chrome (web) • chrome • web-javascript • Google Chrome 108.0.5359.98
macOS এবং iOS
macOS এবং iOS Flutter বিকাশের জন্য, আপনাকে অবশ্যই একটি macOS কম্পিউটার ব্যবহার করতে হবে।
ম্যাকওএস-এ উদাহরণ অ্যাপটি চালানোর সাথে শুরু করুন। Flutter যে ডিভাইসগুলি দেখে সেগুলি আবার নিশ্চিত করুন:
$ flutter devices 2 connected devices: macOS (desktop) • macos • darwin-arm64 • macOS 13.1 22C65 darwin-arm Chrome (web) • chrome • web-javascript • Google Chrome 108.0.5359.98
উত্পন্ন প্লাগইন প্রকল্প ব্যবহার করে উদাহরণ অ্যাপ্লিকেশন চালান:
$ cd ffigen_app/example $ flutter run -d macos
আপনি নিম্নলিখিত মত একটি চলমান অ্যাপ্লিকেশন উইন্ডো দেখতে হবে:
iOS এর জন্য আপনি সিমুলেটর বা একটি বাস্তব হার্ডওয়্যার ডিভাইস ব্যবহার করতে পারেন। সিমুলেটর ব্যবহার করলে, প্রথমে সিমুলেটর চালু করুন। flutter devices
কমান্ড এখন সিমুলেটরটিকে তার উপলব্ধ ডিভাইসগুলির মধ্যে একটি হিসাবে তালিকাভুক্ত করে।
$ flutter devices 3 connected devices: iPhone SE (3rd generation) (mobile) • 1BCBE334-7EC4-433A-90FD-1BC14F3BA41F • ios • com.apple.CoreSimulator.SimRuntime.iOS-16-1 (simulator) macOS (desktop) • macos • darwin-arm64 • macOS 13.1 22C65 darwin-arm Chrome (web) • chrome • web-javascript • Google Chrome 108.0.5359.98
সিমুলেটর চালু হয়ে গেলে রান করুন: flutter run
।
$ cd ffigen_app/example $ flutter run -d iphone
iOS সিমুলেটরটি macOS টার্গেটের উপর অগ্রাধিকার নেয়, তাই আপনি -d
প্যারামিটার সহ একটি ডিভাইস নির্দিষ্ট করা এড়িয়ে যেতে পারেন।
অভিনন্দন, আপনি সফলভাবে পাঁচটি ভিন্ন অপারেটিং সিস্টেমে একটি অ্যাপ্লিকেশন তৈরি ও চালান করেছেন। পরবর্তীতে, নেটিভ প্লাগইন তৈরি করা এবং এফএফআই ব্যবহার করে ডার্ট থেকে এটির সাথে ইন্টারফেস করা।
5. Windows, Linux, এবং Android-এ Duktape ব্যবহার করা
আপনি এই কোডল্যাবে যে সি লাইব্রেরিটি ব্যবহার করবেন তা হল Duktape । Duktape হল একটি এমবেডযোগ্য জাভাস্ক্রিপ্ট ইঞ্জিন, যা বহনযোগ্যতা এবং একটি কমপ্যাক্ট পদচিহ্নের উপর ফোকাস সহ। এই ধাপে, আপনি Duktape লাইব্রেরি কম্পাইল করার জন্য প্লাগইনটি কনফিগার করবেন, এটিকে আপনার প্লাগইনের সাথে লিঙ্ক করবেন এবং তারপর ডার্টের FFI ব্যবহার করে এটি অ্যাক্সেস করবেন।
এই ধাপটি Windows, Linux, এবং Android-এ কাজ করার জন্য ইন্টিগ্রেশন কনফিগার করে। iOS এবং macOS ইন্টিগ্রেশনের জন্য অতিরিক্ত কনফিগারেশন প্রয়োজন (এই ধাপে বিস্তারিত যা আছে তার বাইরে) কম্পাইল করা লাইব্রেরীকে চূড়ান্ত ফ্লাটার এক্সিকিউটেবলে অন্তর্ভুক্ত করতে। পরবর্তী ধাপে অতিরিক্ত প্রয়োজনীয় কনফিগারেশন কভার করা হয়েছে।
ডুকটেপ পুনরুদ্ধার করা হচ্ছে
প্রথমে, duktape.org ওয়েবসাইট থেকে ডাউনলোড করে duktape
সোর্স কোডের একটি অনুলিপি পান।
উইন্ডোজের জন্য আপনি Invoke-WebRequest
সহ PowerShell ব্যবহার করতে পারেন:
PS> Invoke-WebRequest -Uri https://duktape.org/duktape-2.7.0.tar.xz -OutFile duktape-2.7.0.tar.xz
লিনাক্সের জন্য, wget
একটি ভাল পছন্দ।
$ wget https://duktape.org/duktape-2.7.0.tar.xz --2022-12-22 16:21:39-- https://duktape.org/duktape-2.7.0.tar.xz Resolving duktape.org (duktape.org)... 104.198.14.52 Connecting to duktape.org (duktape.org)|104.198.14.52|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 1026524 (1002K) [application/x-xz] Saving to: ‘duktape-2.7.0.tar.xz' duktape-2.7.0.tar.x 100%[===================>] 1002K 1.01MB/s in 1.0s 2022-12-22 16:21:41 (1.01 MB/s) - ‘duktape-2.7.0.tar.xz' saved [1026524/1026524]
ফাইলটি একটি tar.xz
সংরক্ষণাগার। উইন্ডোজে, একটি বিকল্প হল 7Zip টুলগুলি ডাউনলোড করা এবং এটি নিম্নরূপ ব্যবহার করা।
PS> 7z x .\duktape-2.7.0.tar.xz 7-Zip 22.01 (x64) : Copyright (c) 1999-2022 Igor Pavlov : 2022-07-15 Scanning the drive for archives: 1 file, 1026524 bytes (1003 KiB) Extracting archive: .\duktape-2.7.0.tar.xz -- Path = .\duktape-2.7.0.tar.xz Type = xz Physical Size = 1026524 Method = LZMA2:26 CRC64 Streams = 1 Blocks = 1 Everything is Ok Size: 19087360 Compressed: 1026524
আপনাকে দুইবার 7z চালাতে হবে, প্রথমে xz কম্প্রেশন আনআর্কাইভ করতে, দ্বিতীয়বার টার আর্কাইভ প্রসারিত করতে।
PS> 7z x .\duktape-2.7.0.tar 7-Zip 22.01 (x64) : Copyright (c) 1999-2022 Igor Pavlov : 2022-07-15 Scanning the drive for archives: 1 file, 19087360 bytes (19 MiB) Extracting archive: .\duktape-2.7.0.tar -- Path = .\duktape-2.7.0.tar Type = tar Physical Size = 19087360 Headers Size = 543232 Code Page = UTF-8 Characteristics = GNU ASCII Everything is Ok Folders: 46 Files: 1004 Size: 18281564 Compressed: 19087360
আধুনিক লিনাক্স পরিবেশে, tar
নিম্নরূপ এক ধাপে বিষয়বস্তু বের করে।
$ tar xvf duktape-2.7.0.tar.xz x duktape-2.7.0/ x duktape-2.7.0/README.rst x duktape-2.7.0/Makefile.sharedlibrary x duktape-2.7.0/Makefile.coffee x duktape-2.7.0/extras/ x duktape-2.7.0/extras/README.rst x duktape-2.7.0/extras/module-node/ x duktape-2.7.0/extras/module-node/README.rst x duktape-2.7.0/extras/module-node/duk_module_node.h x duktape-2.7.0/extras/module-node/Makefile [... and many more files]
LLVM ইনস্টল করা হচ্ছে
ffigen
ব্যবহার করার জন্য, আপনাকে LLVM ইনস্টল করতে হবে, যা ffigen
C শিরোনাম পার্স করতে ব্যবহার করে। উইন্ডোজে, নিম্নলিখিত কমান্ডটি চালান।
PS> winget install -e --id LLVM.LLVM Found LLVM [LLVM.LLVM] Version 15.0.5 This application is licensed to you by its owner. Microsoft is not responsible for, nor does it grant any licenses to, third-party packages. Downloading https://github.com/llvm/llvm-project/releases/download/llvmorg-15.0.5/LLVM-15.0.5-win64.exe ██████████████████████████████ 277 MB / 277 MB Successfully verified installer hash Starting package install... Successfully installed
আপনার উইন্ডোজ মেশিনে LLVM এর ইনস্টলেশন সম্পূর্ণ করতে আপনার বাইনারি অনুসন্ধান পাথে C:\Program Files\LLVM\bin
যোগ করতে আপনার সিস্টেম পাথগুলি কনফিগার করুন। আপনি এটি সঠিকভাবে ইনস্টল করা হয়েছে কিনা তা নিম্নরূপ পরীক্ষা করতে পারেন।
PS> clang --version clang version 15.0.5 Target: x86_64-pc-windows-msvc Thread model: posix InstalledDir: C:\Program Files\LLVM\bin
উবুন্টুর জন্য, এলএলভিএম নির্ভরতা নিম্নরূপ ইনস্টল করা যেতে পারে। অন্যান্য লিনাক্স ডিস্ট্রিবিউশনে এলএলভিএম এবং ক্ল্যাং-এর জন্য অনুরূপ নির্ভরতা রয়েছে।
$ sudo apt install libclang-dev [sudo] password for brett: Reading package lists... Done Building dependency tree... Done Reading state information... Done The following additional packages will be installed: libclang-15-dev The following NEW packages will be installed: libclang-15-dev libclang-dev 0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. Need to get 26.1 MB of archives. After this operation, 260 MB of additional disk space will be used. Do you want to continue? [Y/n] y Get:1 http://archive.ubuntu.com/ubuntu kinetic/universe amd64 libclang-15-dev amd64 1:15.0.2-1 [26.1 MB] Get:2 http://archive.ubuntu.com/ubuntu kinetic/universe amd64 libclang-dev amd64 1:15.0-55.1ubuntu1 [2962 B] Fetched 26.1 MB in 7s (3748 kB/s) Selecting previously unselected package libclang-15-dev. (Reading database ... 85898 files and directories currently installed.) Preparing to unpack .../libclang-15-dev_1%3a15.0.2-1_amd64.deb ... Unpacking libclang-15-dev (1:15.0.2-1) ... Selecting previously unselected package libclang-dev. Preparing to unpack .../libclang-dev_1%3a15.0-55.1ubuntu1_amd64.deb ... Unpacking libclang-dev (1:15.0-55.1ubuntu1) ... Setting up libclang-15-dev (1:15.0.2-1) ... Setting up libclang-dev (1:15.0-55.1ubuntu1) ...
উপরের হিসাবে, আপনি লিনাক্সে আপনার LLVM ইনস্টলেশনটি নিম্নরূপ পরীক্ষা করতে পারেন।
$ clang --version Ubuntu clang version 15.0.2-1 Target: x86_64-pc-linux-gnu Thread model: posix InstalledDir: /usr/bin
ffigen
কনফিগার করা হচ্ছে
শীর্ষ-স্তরের pubpsec.yaml
তৈরি করা টেমপ্লেটে ffigen
প্যাকেজের পুরানো সংস্করণ থাকতে পারে। প্লাগইন প্রকল্পে ডার্ট নির্ভরতা আপডেট করতে নিম্নলিখিত কমান্ডটি চালান:
$ flutter pub upgrade --major-versions
এখন যেহেতু ffigen
প্যাকেজ আপ-টু-ডেট, পরবর্তী কনফিগার করুন ffigen
কোন ফাইলগুলি বাইন্ডিং ফাইল তৈরি করতে ব্যবহার করবে। নিম্নলিখিতগুলির সাথে মেলে আপনার প্রকল্পের ffigen.yaml
ফাইলের বিষয়বস্তু পরিবর্তন করুন৷
ffigen.yaml
# Run with `flutter pub run ffigen --config ffigen.yaml`.
name: DuktapeBindings
description: |
Bindings for `src/duktape.h`.
Regenerate bindings with `flutter pub run ffigen --config ffigen.yaml`.
output: 'lib/duktape_bindings_generated.dart'
headers:
entry-points:
- 'src/duktape.h'
include-directives:
- 'src/duktape.h'
preamble: |
// ignore_for_file: always_specify_types
// ignore_for_file: camel_case_types
// ignore_for_file: non_constant_identifier_names
comments:
style: any
length: full
ignore-source-errors: true
এই কনফিগারেশনে LLVM-এ পাস করার জন্য C শিরোনাম ফাইল, তৈরি করার জন্য আউটপুট ফাইল, ফাইলের শীর্ষে রাখার বিবরণ এবং লিন্ট সতর্কতা যোগ করার জন্য ব্যবহৃত একটি প্রস্তাবনা বিভাগ অন্তর্ভুক্ত রয়েছে।
ফাইলের শেষে একটি কনফিগারেশন আইটেম রয়েছে যা আরও ব্যাখ্যার যোগ্য। ffigen
11.0.0 সংস্করণ অনুসারে বাইন্ডিং জেনারেটর ডিফল্টভাবে বাইন্ডিং তৈরি করবে না যদি হেডার ফাইলগুলি পার্স করার সময় clang
দ্বারা উত্পন্ন সতর্কতা বা ত্রুটি থাকে।
Duktape হেডার ফাইলগুলি, যেমন লেখা আছে, ম্যাকওএস-এ clang
ট্রিগার করে সতর্কতা জেনারেট করে কারণ Duktape-এর পয়েন্টারগুলিতে শূন্যতা টাইপ স্পেসিফায়ারের অভাব রয়েছে। macOS এবং iOS Duktape কে সম্পূর্ণভাবে সমর্থন করার জন্য Duktape কোডবেসে এই ধরনের স্পেসিফায়ার যোগ করা প্রয়োজন। ইতিমধ্যে, আমরা ignore-source-errors
পতাকাটিকে true
হিসাবে সেট করে এই সতর্কতাগুলি উপেক্ষা করার সিদ্ধান্ত নিচ্ছি৷
একটি প্রোডাকশন অ্যাপ্লিকেশানে, আপনার অ্যাপ্লিকেশন পাঠানোর আগে আপনার সমস্ত কম্পাইলার সতর্কতাগুলি মুছে ফেলা উচিত। যাইহোক, ডুকটেপের জন্য এটি করা এই কোডল্যাবের সুযোগের বাইরে।
অন্যান্য কী এবং মান সম্পর্কে আরও বিশদ বিবরণের জন্য ffigen
ডকুমেন্টেশন দেখুন।
আপনাকে Duktape ডিস্ট্রিবিউশন থেকে নির্দিষ্ট Duktape ফাইলগুলিকে সেই অবস্থানে অনুলিপি করতে হবে যেখানে ffigen
কনফিগার করা হয়েছে সেগুলি খুঁজে পেতে।
$ cp duktape-2.7.0/src/duktape.c src/ $ cp duktape-2.7.0/src/duktape.h src/ $ cp duktape-2.7.0/src/duk_config.h src/
প্রযুক্তিগতভাবে, আপনাকে শুধুমাত্র ffigen
এর জন্য duktape.h
জুড়ে কপি করতে হবে, কিন্তু আপনি লাইব্রেরি তৈরি করতে CMake কনফিগার করতে চলেছেন যার তিনটিরই প্রয়োজন। নতুন বাইন্ডিং তৈরি করতে ffigen
চালান:
$ flutter pub run ffigen --config ffigen.yaml Running in Directory: '/home/brett/GitHub/codelabs/ffigen_codelab/step_05' Input Headers: [./src/duktape.h] [WARNING]: No definition found for declaration - (Cursor) spelling: duk_hthread, kind: 2, kindSpelling: StructDecl, type: 105, typeSpelling: struct duk_hthread, usr: c:@S@duk_hthread [WARNING]: No definition found for declaration - (Cursor) spelling: duk_hthread, kind: 2, kindSpelling: StructDecl, type: 105, typeSpelling: struct duk_hthread, usr: c:@S@duk_hthread [WARNING]: Generated declaration '__va_list_tag' start's with '_' and therefore will be private. Finished, Bindings generated in /home/brett/GitHub/codelabs/ffigen_codelab/step_05/./lib/duktape_bindings_generated.dart
আপনি প্রতিটি অপারেটিং সিস্টেমে বিভিন্ন সতর্কতা দেখতে পাবেন। আপনি আপাতত এগুলি উপেক্ষা করতে পারেন, কারণ Duktape 2.7.0 Windows, Linux, এবং macOS-এ clang
এর সাথে কম্পাইল করার জন্য পরিচিত।
CMake কনফিগার করা হচ্ছে
CMake একটি বিল্ড সিস্টেম জেনারেশন সিস্টেম। এই প্লাগইনটি অ্যান্ড্রয়েড, উইন্ডোজ এবং লিনাক্সের জন্য বিল্ড সিস্টেম তৈরি করতে CMake ব্যবহার করে জেনারেট করা ফ্লাটার বাইনারিতে Duktape অন্তর্ভুক্ত করে। আপনাকে টেমপ্লেট জেনারেট করা CMake কনফিগারেশন ফাইলটি নিম্নরূপ পরিবর্তন করতে হবে।
src/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(ffigen_app_library VERSION 0.0.1 LANGUAGES C)
add_library(ffigen_app SHARED
duktape.c # Modify
)
set_target_properties(ffigen_app PROPERTIES
PUBLIC_HEADER duktape.h # Modify
PRIVATE_HEADER duk_config.h # Add
OUTPUT_NAME "ffigen_app" # Add
)
# Add from here...
if (WIN32)
set_target_properties(ffigen_app PROPERTIES
WINDOWS_EXPORT_ALL_SYMBOLS ON
)
endif (WIN32)
# ... to here.
target_compile_definitions(ffigen_app PUBLIC DART_SHARED_LIB)
CMake কনফিগারেশন সোর্স ফাইল যোগ করে, এবং আরও গুরুত্বপূর্ণভাবে, ডিফল্টরূপে সমস্ত C চিহ্ন রপ্তানি করতে উইন্ডোজে জেনারেট করা লাইব্রেরি ফাইলের ডিফল্ট আচরণ পরিবর্তন করে। এটি ইউনিক্স-স্টাইলের লাইব্রেরিগুলিকে সাহায্য করার জন্য একটি CMake কাজ, যা Duktape হল, উইন্ডোজের জগতে।
lib/ffigen_app.dart
এর বিষয়বস্তুকে নিম্নলিখিত দিয়ে প্রতিস্থাপন করুন।
lib/ffigen_app.dart
import 'dart:ffi';
import 'dart:io' show Platform;
import 'package:ffi/ffi.dart' as ffi;
import 'duktape_bindings_generated.dart';
const String _libName = 'ffigen_app';
final DynamicLibrary _dylib = () {
if (Platform.isMacOS || Platform.isIOS) {
return DynamicLibrary.open('$_libName.framework/$_libName');
}
if (Platform.isAndroid || Platform.isLinux) {
return DynamicLibrary.open('lib$_libName.so');
}
if (Platform.isWindows) {
return DynamicLibrary.open('$_libName.dll');
}
throw UnsupportedError('Unknown platform: ${Platform.operatingSystem}');
}();
final DuktapeBindings _bindings = DuktapeBindings(_dylib);
class Duktape {
Duktape() {
ctx =
_bindings.duk_create_heap(nullptr, nullptr, nullptr, nullptr, nullptr);
}
void evalString(String jsCode) {
var nativeUtf8 = jsCode.toNativeUtf8();
_bindings.duk_eval_raw(
ctx,
nativeUtf8.cast<Char>(),
0,
0 |
DUK_COMPILE_EVAL |
DUK_COMPILE_SAFE |
DUK_COMPILE_NOSOURCE |
DUK_COMPILE_STRLEN |
DUK_COMPILE_NOFILENAME);
ffi.malloc.free(nativeUtf8);
}
int getInt(int index) {
return _bindings.duk_get_int(ctx, index);
}
void dispose() {
_bindings.duk_destroy_heap(ctx);
ctx = nullptr;
}
late Pointer<duk_hthread> ctx;
}
এই ফাইলটি ডাইনামিক লিঙ্ক লাইব্রেরি ফাইল লোড করার জন্য দায়ী ( .so
লিনাক্স এবং অ্যান্ড্রয়েডের জন্য, উইন্ডোজের জন্য .dll
) এবং একটি মোড়ক প্রদানের জন্য যা অন্তর্নিহিত সি কোডে আরও ডার্ট ইডিওম্যাটিক ইন্টারফেস প্রকাশ করে।
যেহেতু এই ফাইলটি সরাসরি ffi
প্যাকেজ আমদানি করে, তাই আপনাকে প্যাকেজটিকে dev_dependencies
থেকে dependencies
সরাতে হবে। এটি করার একটি সহজ উপায় হল নিম্নলিখিত কমান্ডটি চালানো:
$ dart pub add ffi
উদাহরণের main.dart
এর বিষয়বস্তু নিচের দিয়ে প্রতিস্থাপন করুন।
example/lib/main.dart
import 'package:ffigen_app/ffigen_app.dart';
import 'package:flutter/material.dart';
const String jsCode = '1+2';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late Duktape duktape;
String output = '';
@override
void initState() {
super.initState();
duktape = Duktape();
setState(() {
output = 'Initialized Duktape';
});
}
@override
void dispose() {
duktape.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
const textStyle = TextStyle(fontSize: 25);
const spacerSmall = SizedBox(height: 10);
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Duktape Test'),
),
body: Center(
child: Container(
padding: const EdgeInsets.all(10),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
output,
style: textStyle,
textAlign: TextAlign.center,
),
spacerSmall,
ElevatedButton(
child: const Text('Run JavaScript'),
onPressed: () {
duktape.evalString(jsCode);
setState(() {
output = '$jsCode => ${duktape.getInt(-1)}';
});
},
),
],
),
),
),
),
);
}
}
আপনি এখন ব্যবহার করে আবার উদাহরণ অ্যাপ্লিকেশন চালাতে পারেন:
$ cd example $ flutter run
আপনি এই মত চলমান অ্যাপ্লিকেশন দেখতে হবে:
এই দুটি স্ক্রিনশট জাভাস্ক্রিপ্ট চালান বোতাম টিপে আগে এবং পরে দেখায়। এটি ডার্ট থেকে জাভাস্ক্রিপ্ট কোড কার্যকর করা এবং স্ক্রীনে ফলাফল প্রদর্শন করে।
অ্যান্ড্রয়েড
অ্যান্ড্রয়েড হল একটি লিনাক্স, কার্নেল-ভিত্তিক ওএস এবং এটি কিছুটা ডেস্কটপ লিনাক্স ডিস্ট্রিবিউশনের মতো। CMake বিল্ড সিস্টেম দুটি প্ল্যাটফর্মের মধ্যে বেশিরভাগ পার্থক্য লুকিয়ে রাখতে পারে। অ্যান্ড্রয়েড তৈরি এবং চালানোর জন্য, নিশ্চিত করুন যে অ্যান্ড্রয়েড এমুলেটর চলছে (বা অ্যান্ড্রয়েড ডিভাইস সংযুক্ত আছে)। অ্যাপটি চালান। যেমন:
$ cd example $ flutter run -d emulator-5554
আপনি এখন Android এ চলমান উদাহরণ অ্যাপ্লিকেশন দেখতে হবে:
6. MacOS এবং iOS-এ Duktape ব্যবহার করা
এখন আপনার প্লাগইন ম্যাকওএস এবং আইওএস, দুটি ঘনিষ্ঠভাবে সম্পর্কিত অপারেটিং সিস্টেমে কাজ করার সময়। macOS দিয়ে শুরু করুন। যদিও CMake macOS এবং iOS সমর্থন করে, আপনি Linux এবং Android এর জন্য যে কাজটি করেছেন তা পুনরায় ব্যবহার করবেন না, কারণ macOS এবং iOS-এ Flutter লাইব্রেরি আমদানির জন্য CocoaPods ব্যবহার করে।
ক্লিনিং আপ
পূর্ববর্তী ধাপে আপনি Android, Windows এবং Linux-এর জন্য একটি কার্যকরী অ্যাপ্লিকেশন তৈরি করেছেন। যাইহোক, মূল টেমপ্লেট থেকে কয়েকটি ফাইল অবশিষ্ট আছে যেগুলি এখন আপনাকে পরিষ্কার করতে হবে। নিম্নরূপ এখন তাদের সরান.
$ rm src/ffigen_app.c $ rm src/ffigen_app.h $ rm ios/Classes/ffigen_app.c $ rm macos/Classes/ffigen_app.c
macOS
macOS প্ল্যাটফর্মে ফ্লাটার C এবং C++ কোড আমদানি করতে CocoaPods ব্যবহার করে। এর মানে হল যে এই প্যাকেজটি CocoaPods নির্মাণ পরিকাঠামোতে একীভূত করা প্রয়োজন। পূর্ববর্তী ধাপে CMake-এর সাথে তৈরি করার জন্য আপনি ইতিমধ্যেই কনফিগার করা C কোডের পুনরায় ব্যবহার সক্ষম করতে, আপনাকে macOS প্ল্যাটফর্ম রানারে একটি একক ফরওয়ার্ডিং ফাইল যোগ করতে হবে।
macos/Classes/duktape.c
#include "../../src/duktape.c"
এই ফাইলটি সি প্রিপ্রসেসরের শক্তি ব্যবহার করে আপনার পূর্ববর্তী ধাপে সেট আপ করা নেটিভ সোর্স কোড থেকে সোর্স কোড অন্তর্ভুক্ত করতে। এটি কিভাবে কাজ করে তার আরো বিস্তারিত জানার জন্য macos/ffigen_app.podspec দেখুন।
এই অ্যাপ্লিকেশনটি চালানো এখন একই প্যাটার্ন অনুসরণ করে যা আপনি উইন্ডোজ এবং লিনাক্সে দেখেছেন।
$ cd example $ flutter run -d macos
iOS
MacOS সেটআপের মতো, iOS-এর জন্যও একটি একক ফরওয়ার্ডিং C ফাইল যোগ করা প্রয়োজন।
ios/Classes/duktape.c
#include "../../src/duktape.c"
এই একক ফাইলের সাথে, আপনার প্লাগইনটি এখন iOS-এ চালানোর জন্য কনফিগার করা হয়েছে। যথারীতি চালান।
$ flutter run -d iPhone
অভিনন্দন! আপনি সফলভাবে পাঁচটি প্ল্যাটফর্মে নেটিভ কোড একত্রিত করেছেন। এটি একটি উদযাপনের জন্য ভিত্তি! হয়তো আরও কার্যকরী ইউজার ইন্টারফেস, যা আপনি পরবর্তী ধাপে তৈরি করবেন।
7. রিড ইভাল প্রিন্ট লুপ প্রয়োগ করুন
একটি প্রোগ্রামিং ভাষার সাথে ইন্টারঅ্যাক্ট করা একটি দ্রুত ইন্টারেক্টিভ পরিবেশে অনেক বেশি মজাদার। এই ধরনের পরিবেশের মূল বাস্তবায়ন ছিল LISP-এর Read Eval Print Loop (REPL)। আপনি এই ধাপে Duktape এর সাথে অনুরূপ কিছু বাস্তবায়ন করতে যাচ্ছেন।
জিনিস উত্পাদন প্রস্তুত করা
বর্তমান কোড যা Duktape C লাইব্রেরির সাথে ইন্টারঅ্যাক্ট করে তা অনুমান করে যে কিছুই ভুল হতে পারে না। ওহ, এবং পরীক্ষা চলাকালীন এটি ডুকটেপ ডায়নামিক লিঙ্ক লাইব্রেরি লোড করে না। এই ইন্টিগ্রেশন প্রোডাকশন প্রস্তুত করতে, আপনাকে lib/ffigen_app.dart
এ কিছু পরিবর্তন করতে হবে।
lib/ffigen_app.dart
import 'dart:ffi';
import 'dart:io' show Platform;
import 'package:ffi/ffi.dart' as ffi;
import 'package:path/path.dart' as p; // Add this import
import 'duktape_bindings_generated.dart';
const String _libName = 'ffigen_app';
final DynamicLibrary _dylib = () {
if (Platform.isMacOS || Platform.isIOS) {
// Add from here...
if (Platform.environment.containsKey('FLUTTER_TEST')) {
return DynamicLibrary.open('build/macos/Build/Products/Debug'
'/$_libName/$_libName.framework/$_libName');
}
// ...to here.
return DynamicLibrary.open('$_libName.framework/$_libName');
}
if (Platform.isAndroid || Platform.isLinux) {
// Add from here...
if (Platform.environment.containsKey('FLUTTER_TEST')) {
return DynamicLibrary.open(
'build/linux/x64/debug/bundle/lib/lib$_libName.so');
}
// ...to here.
return DynamicLibrary.open('lib$_libName.so');
}
if (Platform.isWindows) {
// Add from here...
if (Platform.environment.containsKey('FLUTTER_TEST')) {
return DynamicLibrary.open(p.canonicalize(
p.join(r'build\windows\runner\Debug', '$_libName.dll')));
}
// ...to here.
return DynamicLibrary.open('$_libName.dll');
}
throw UnsupportedError('Unknown platform: ${Platform.operatingSystem}');
}();
final DuktapeBindings _bindings = DuktapeBindings(_dylib);
class Duktape {
Duktape() {
ctx =
_bindings.duk_create_heap(nullptr, nullptr, nullptr, nullptr, nullptr);
}
// Modify this function
String evalString(String jsCode) {
var nativeUtf8 = jsCode.toNativeUtf8();
final evalResult = _bindings.duk_eval_raw(
ctx,
nativeUtf8.cast<Char>(),
0,
0 |
DUK_COMPILE_EVAL |
DUK_COMPILE_SAFE |
DUK_COMPILE_NOSOURCE |
DUK_COMPILE_STRLEN |
DUK_COMPILE_NOFILENAME);
ffi.malloc.free(nativeUtf8);
if (evalResult != 0) {
throw _retrieveTopOfStackAsString();
}
return _retrieveTopOfStackAsString();
}
// Add this function
String _retrieveTopOfStackAsString() {
Pointer<Size> outLengthPtr = ffi.calloc<Size>();
final errorStrPtr = _bindings.duk_safe_to_lstring(ctx, -1, outLengthPtr);
final returnVal =
errorStrPtr.cast<ffi.Utf8>().toDartString(length: outLengthPtr.value);
ffi.calloc.free(outLengthPtr);
return returnVal;
}
void dispose() {
_bindings.duk_destroy_heap(ctx);
ctx = nullptr;
}
late Pointer<duk_hthread> ctx;
}
ডায়নামিক লিঙ্ক লাইব্রেরি লোড করার কোডটি কেসটি পরিচালনা করার জন্য প্রসারিত করা হয়েছে যেখানে প্লাগইনটি একটি টেস্ট রানারে ব্যবহার করা হচ্ছে। এটি একটি ইন্টিগ্রেশন পরীক্ষা লিখতে সক্ষম করে যা এই APIটিকে একটি ফ্লাটার পরীক্ষা হিসাবে ব্যবহার করে৷ জাভাস্ক্রিপ্ট কোডের একটি স্ট্রিং মূল্যায়ন করার কোডটি সঠিকভাবে ত্রুটির শর্তগুলি পরিচালনা করার জন্য প্রসারিত করা হয়েছে, উদাহরণস্বরূপ অসম্পূর্ণ বা ভুল কোড৷ এই অতিরিক্ত কোডটি দেখায় যে কীভাবে স্ট্রিংগুলিকে বাইট অ্যারে হিসাবে ফেরত দেওয়া হয় এবং ডার্ট স্ট্রিংগুলিতে রূপান্তরিত করা প্রয়োজন এমন পরিস্থিতিতে কীভাবে পরিচালনা করা যায়।
প্যাকেজ যোগ করা হচ্ছে
একটি REPL তৈরি করার সময়, আপনি ব্যবহারকারী এবং Duktape JavaScript ইঞ্জিনের মধ্যে একটি মিথস্ক্রিয়া প্রদর্শন করবেন। ব্যবহারকারী কোডের লাইনে প্রবেশ করে, এবং Duktape হয় গণনার ফলাফল, বা একটি ব্যতিক্রম সহ প্রতিক্রিয়া জানায়। আপনার লিখতে প্রয়োজন বয়লারপ্লেট কোডের পরিমাণ কমাতে আপনি freezed
ব্যবহার করবেন। আপনি থিমে প্রদর্শিত বিষয়বস্তুকে আরও একটু বেশি করতে google_fonts
এবং রাষ্ট্রীয় ব্যবস্থাপনার জন্য flutter_riverpod
ব্যবহার করবেন।
উদাহরণ অ্যাপে প্রয়োজনীয় নির্ভরতা যোগ করুন:
$ cd example $ dart pub add flutter_riverpod freezed_annotation google_fonts $ dart pub add -d build_runner freezed
পরবর্তী, REPL মিথস্ক্রিয়া রেকর্ড করতে একটি ফাইল তৈরি করুন:
example/lib/duktape_message.dart
import 'package:freezed_annotation/freezed_annotation.dart';
part 'duktape_message.freezed.dart';
@freezed
class DuktapeMessage with _$DuktapeMessage {
factory DuktapeMessage.evaluate(String code) = DuktapeMessageCode;
factory DuktapeMessage.response(String result) = DuktapeMessageResponse;
factory DuktapeMessage.error(String log) = DuktapeMessageError;
}
এই ক্লাসটি freezed
ইউনিয়ন টাইপ বৈশিষ্ট্য ব্যবহার করে REPL-এ প্রদর্শিত প্রতিটি লাইনের আকারের তিনটি প্রকারের মধ্যে একটি হিসাবে সহজে প্রকাশ করতে সক্ষম হয়। এই মুহুর্তে, আপনার কোড সম্ভবত এই কোডে কিছু ত্রুটি দেখাচ্ছে, কারণ অতিরিক্ত কোড তৈরি করা দরকার। নিচের মত করে এখন সেটা করুন।
$ flutter pub run build_runner build
এটি example/lib/duktape_message.freezed.dart
ফাইল তৈরি করে, যে কোডটি আপনি এইমাত্র টাইপ করেছেন তার উপর নির্ভর করে।
এর পরে, ফন্ট ডেটার জন্য নেটওয়ার্ক অনুরোধ করতে google_fonts
সক্ষম করতে আপনাকে macOS কনফিগারেশন ফাইলগুলিতে এক জোড়া পরিবর্তন করতে হবে।
example/macos/Runner/DebugProfile.entitlements
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>
<!-- Add from here... -->
<key>com.apple.security.network.client</key>
<true/>
<!-- ...to here -->
</dict>
</plist>
example/macos/Runner/Release.entitlements
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<!-- Add from here... -->
<key>com.apple.security.network.client</key>
<true/>
<!-- ...to here -->
</dict>
</plist>
REPL নির্মাণ
এখন যেহেতু আপনি ত্রুটিগুলি পরিচালনা করতে ইন্টিগ্রেশন লেয়ার আপডেট করেছেন, এবং আপনি ইন্টারঅ্যাকশনের জন্য একটি ডেটা উপস্থাপনা তৈরি করেছেন, এটি উদাহরণ অ্যাপের ইউজার ইন্টারফেস তৈরি করার সময়।
example/lib/main.dart
import 'package:ffigen_app/ffigen_app.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_fonts/google_fonts.dart';
import 'duktape_message.dart';
void main() {
runApp(const ProviderScope(child: DuktapeApp()));
}
final duktapeMessagesProvider =
StateNotifierProvider<DuktapeMessageNotifier, List<DuktapeMessage>>((ref) {
return DuktapeMessageNotifier(messages: <DuktapeMessage>[]);
});
class DuktapeMessageNotifier extends StateNotifier<List<DuktapeMessage>> {
DuktapeMessageNotifier({required List<DuktapeMessage> messages})
: duktape = Duktape(),
super(messages);
final Duktape duktape;
void eval(String code) {
state = [
DuktapeMessage.evaluate(code),
...state,
];
try {
final response = duktape.evalString(code);
state = [
DuktapeMessage.response(response),
...state,
];
} catch (e) {
state = [
DuktapeMessage.error('$e'),
...state,
];
}
}
}
class DuktapeApp extends StatelessWidget {
const DuktapeApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Duktape App',
home: DuktapeRepl(),
);
}
}
class DuktapeRepl extends ConsumerStatefulWidget {
const DuktapeRepl({
super.key,
});
@override
ConsumerState<DuktapeRepl> createState() => _DuktapeReplState();
}
class _DuktapeReplState extends ConsumerState<DuktapeRepl> {
final _controller = TextEditingController();
final _focusNode = FocusNode();
var _isComposing = false;
void _handleSubmitted(String text) {
_controller.clear();
setState(() {
_isComposing = false;
});
setState(() {
ref.read(duktapeMessagesProvider.notifier).eval(text);
});
_focusNode.requestFocus();
}
@override
Widget build(BuildContext context) {
final messages = ref.watch(duktapeMessagesProvider);
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: const Text('Duktape REPL'),
elevation: Theme.of(context).platform == TargetPlatform.iOS ? 0.0 : 4.0,
),
body: Column(
children: [
Flexible(
child: Ink(
color: Theme.of(context).scaffoldBackgroundColor,
child: SafeArea(
bottom: false,
child: ListView.builder(
padding: const EdgeInsets.all(8.0),
reverse: true,
itemBuilder: (context, idx) => messages[idx].when(
evaluate: (str) => Padding(
padding: const EdgeInsets.symmetric(vertical: 2),
child: Text(
'> $str',
style: GoogleFonts.firaCode(
textStyle: Theme.of(context).textTheme.titleMedium,
),
),
),
response: (str) => Padding(
padding: const EdgeInsets.symmetric(vertical: 2),
child: Text(
'= $str',
style: GoogleFonts.firaCode(
textStyle: Theme.of(context).textTheme.titleMedium,
color: Colors.blue[800],
),
),
),
error: (str) => Padding(
padding: const EdgeInsets.symmetric(vertical: 2),
child: Text(
str,
style: GoogleFonts.firaCode(
textStyle: Theme.of(context).textTheme.titleSmall,
color: Colors.red[800],
fontWeight: FontWeight.bold,
),
),
),
),
itemCount: messages.length,
),
),
),
),
const Divider(height: 1.0),
SafeArea(
top: false,
child: Container(
decoration: BoxDecoration(color: Theme.of(context).cardColor),
child: _buildTextComposer(),
),
),
],
),
);
}
Widget _buildTextComposer() {
return IconTheme(
data: IconThemeData(color: Theme.of(context).colorScheme.secondary),
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 8.0),
child: Row(
children: [
Text('>', style: Theme.of(context).textTheme.titleMedium),
const SizedBox(width: 4),
Flexible(
child: TextField(
controller: _controller,
decoration: const InputDecoration(
border: InputBorder.none,
),
onChanged: (text) {
setState(() {
_isComposing = text.isNotEmpty;
});
},
onSubmitted: _isComposing ? _handleSubmitted : null,
focusNode: _focusNode,
),
),
Container(
margin: const EdgeInsets.symmetric(horizontal: 4.0),
child: IconButton(
icon: const Icon(Icons.send),
onPressed: _isComposing
? () => _handleSubmitted(_controller.text)
: null,
),
),
],
),
),
);
}
}
এই কোডটিতে অনেক কিছু চলছে, তবে এটি সমস্ত ব্যাখ্যা করা এই কোডল্যাবের সুযোগের বাইরে। আমি আপনাকে কোডটি চালানোর পরামর্শ দিচ্ছি, এবং তারপরে যথাযথ ডকুমেন্টেশন পর্যালোচনা করার পরে কোডে পরিবর্তন করুন।
$ cd example $ flutter run
8. অভিনন্দন
অভিনন্দন! আপনি Windows, macOS, Linux, Android, এবং iOS-এর জন্য সফলভাবে একটি Flutter FFI-ভিত্তিক প্লাগইন তৈরি করেছেন!
আপনি একটি প্লাগইন তৈরি করার পরে, আপনি এটি অনলাইনে শেয়ার করতে চাইতে পারেন যাতে অন্যরা এটি ব্যবহার করতে পারে। আপনি ডেভেলপিং প্লাগইন প্যাকেজে pub.dev- তে আপনার প্লাগইন প্রকাশ করার সম্পূর্ণ ডকুমেন্টেশন পেতে পারেন।