Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Gambaran Umum
Xamarin memungkinkan pengembang membuat aplikasi seluler asli lintas platform dengan Visual Studio. Umumnya, pengikatan C# digunakan untuk mengekspos komponen platform yang ada kepada pengembang. Namun, ada kalanya aplikasi Xamarin perlu bekerja dengan basis kode yang ada. Terkadang tim tidak memiliki waktu, anggaran, atau sumber daya untuk memindahkan basis kode besar, teruji dengan baik, dan sangat dioptimalkan ke C#.
Visual C++ untuk pengembangan seluler lintas platform memungkinkan kode C/C++ dan C# dibangun sebagai bagian dari solusi yang sama, menawarkan banyak keuntungan termasuk pengalaman debugging terpadu. Microsoft telah menggunakan C/C++ dan Xamarin dengan cara ini untuk mengirimkan aplikasi seperti Hyperlapse Mobile dan Pix Kamera.
Namun, dalam beberapa kasus ada keinginan (atau persyaratan) untuk menjaga alat dan proses C/C++ yang ada dan untuk menjaga kode pustaka dipisahkan dari aplikasi, memperlakukan pustaka seolah-olah mirip dengan komponen pihak ketiga. Dalam situasi ini, tantangannya tidak hanya mengekspos anggota yang relevan dengan C# tetapi mengelola pustaka sebagai dependensi. Dan, tentu saja, mengotomatiskan sebanyak mungkin proses ini.
Posting ini menguraikan pendekatan tingkat tinggi untuk skenario ini dan menelusuri contoh sederhana.
Latar belakang
C/C++ dianggap sebagai bahasa lintas platform, tetapi sangat hati-hati harus diambil untuk memastikan bahwa kode sumber memang lintas platform, hanya menggunakan C/C++ yang didukung oleh semua pengkompilasi target dan berisi platform kecil atau tanpa kondisional atau kode khusus kompilator.
Pada akhirnya kode harus dikompilasi dan berjalan dengan sukses di semua platform target oleh karena itu ini bermuara pada kesamaan di seluruh platform (dan kompilator) yang ditargetkan. Masalah mungkin masih muncul dari perbedaan kecil antara kompilator dan pengujian menyeluruh (sebaiknya otomatis) pada setiap platform target menjadi semakin penting.
Pendekatan tingkat tinggi
Ilustrasi di bawah ini mewakili pendekatan empat tahap yang digunakan untuk mengubah kode sumber C/C++ menjadi pustaka Xamarin lintas platform yang dibagikan melalui NuGet dan kemudian digunakan dalam aplikasi Xamarin.Forms.

4 tahap tersebut adalah:
- Mengkompilasi kode sumber C/C++ ke dalam pustaka asli khusus platform.
- Membungkus pustaka asli dengan solusi Visual Studio.
- Mengemas dan mendorong paket NuGet untuk pembungkus .NET.
- Mengkonsumsi paket NuGet dari aplikasi Xamarin.
Tahap 1: Mengkompilasi kode sumber C/C++ ke dalam pustaka asli khusus platform
Tujuan dari tahap ini adalah untuk membuat pustaka asli yang dapat dipanggil oleh pembungkus C#. Ini mungkin atau mungkin tidak relevan tergantung pada situasi Anda. Banyak alat dan proses yang dapat dibawa untuk menanggung dalam skenario umum ini berada di luar cakupan artikel ini. Pertimbangan utama adalah menjaga basis kode C/C++ tetap sinkron dengan kode pembungkus asli, pengujian unit yang memadai, dan otomatisasi build.
Pustaka dalam panduan dibuat menggunakan Visual Studio Code dengan skrip shell yang menyertainya. Versi yang diperluas dari panduan ini dapat ditemukan di repositori GitHub Mobile CAT yang membahas bagian sampel ini secara lebih mendalam. Pustaka asli diperlakukan sebagai dependensi pihak ketiga dalam hal ini namun tahap ini diilustrasikan untuk konteks.
Untuk kesederhanaan, panduan hanya menargetkan subset arsitektur. Untuk iOS, ia menggunakan utilitas lipo untuk membuat biner lemak tunggal dari biner khusus arsitektur individu. Android akan menggunakan biner dinamis dengan ekstensi .so dan iOS akan menggunakan biner lemak statis dengan ekstensi .a.
Tahap 2: Membungkus pustaka asli dengan solusi Visual Studio
Tahap selanjutnya adalah membungkus pustaka asli sehingga mudah digunakan dari .NET. Ini dilakukan dengan solusi Visual Studio dengan empat proyek. Proyek bersama berisi kode umum. Proyek yang menargetkan masing-masing Xamarin.Android, Xamarin.iOS, dan .NET Standard memungkinkan pustaka direferensikan dengan cara platform-agnostik.
Pembungkus menggunakan 'umpan dan trik switch,'. Ini bukan satu-satunya cara, tetapi memudahkan untuk mereferensikan pustaka dan menghindari kebutuhan untuk mengelola implementasi khusus platform secara eksplisit dalam aplikasi yang mengonsumsi itu sendiri. Trik ini pada dasarnya memastikan bahwa target (.NET Standard, Android, iOS) memiliki namespace, nama rakitan, dan struktur kelas yang sama. Karena NuGet akan selalu lebih memilih pustaka khusus platform, versi .NET Standard tidak pernah digunakan saat runtime.
Sebagian besar pekerjaan dalam langkah ini akan fokus pada penggunaan P/Invoke untuk memanggil metode pustaka asli dan mengelola referensi ke objek yang mendasar. Tujuannya adalah untuk mengekspos fungsionalitas pustaka kepada konsumen sambil mengabstraksi kompleksitas apa pun. Pengembang Xamarin.Forms tidak perlu memiliki pengetahuan kerja tentang pekerjaan dalam pustaka yang tidak dikelola. Ini akan terasa seperti mereka menggunakan pustaka C# terkelola lainnya.
Pada akhirnya, output dari tahap ini adalah sekumpulan pustaka .NET, satu per target, bersama dengan dokumen nuspec yang berisi informasi yang diperlukan untuk membangun paket di langkah berikutnya.
Tahap 3: Mengemas dan mendorong paket NuGet untuk pembungkus .NET
Tahap ketiga adalah membuat paket NuGet menggunakan artefak build dari langkah sebelumnya. Hasil dari langkah ini adalah paket NuGet yang dapat dikonsumsi dari aplikasi Xamarin. Panduan ini menggunakan direktori lokal untuk berfungsi sebagai umpan NuGet. Dalam produksi, langkah ini harus menerbitkan paket ke umpan NuGet publik atau privat dan harus sepenuhnya otomatis.
Tahap 4: Mengkonsumsi paket NuGet dari aplikasi Xamarin.Forms
Langkah terakhir adalah mereferensikan dan menggunakan paket NuGet dari aplikasi Xamarin.Forms. Ini mengharuskan mengonfigurasi umpan NuGet di Visual Studio untuk menggunakan umpan yang ditentukan pada langkah sebelumnya.
Setelah umpan dikonfigurasi, paket perlu dirujuk dari setiap proyek di aplikasi Xamarin.Forms lintas platform. 'Trik umpan dan sakelar' menyediakan antarmuka yang identik, sehingga fungsionalitas pustaka asli dapat dipanggil menggunakan kode yang ditentukan dalam satu lokasi.
Repositori kode sumber berisi daftar pembacaan lebih lanjut yang mencakup artikel tentang cara menyiapkan umpan NuGet privat di Azure DevOps dan cara mendorong paket ke umpan tersebut. Meskipun membutuhkan sedikit lebih banyak waktu penyiapan daripada direktori lokal, jenis umpan ini lebih baik di lingkungan pengembangan tim.
Video panduan
Langkah-langkah yang disediakan khusus untuk Visual Studio untuk Mac, tetapi strukturnya juga berfungsi di Visual Studio 2017 .
Prasyarat
Untuk mengikutinya, pengembang akan membutuhkan:
Catatan
Akun Pengembang Apple aktif diperlukan untuk menyebarkan aplikasi ke i Telepon.
Membuat pustaka asli (Tahap 1)
Fungsionalitas pustaka asli didasarkan pada contoh dari Panduan: Membuat dan Menggunakan Pustaka Statis (C++).
Panduan ini melewati tahap pertama, membangun pustaka asli, karena pustaka disediakan sebagai dependensi pihak ketiga dalam skenario ini. Pustaka asli yang telah dikompilasi disertakan bersama kode sampel atau dapat diunduh secara langsung.
Bekerja dengan pustaka asli
Contoh MathFuncsLib asli mencakup satu kelas yang disebut MyMathFuncs dengan definisi berikut:
namespace MathFuncs
{
class MyMathFuncs
{
public:
double Add(double a, double b);
double Subtract(double a, double b);
double Multiply(double a, double b);
double Divide(double a, double b);
};
}
Kelas tambahan mendefinisikan fungsi pembungkus yang memungkinkan konsumen .NET untuk membuat, membuang, dan berinteraksi dengan kelas asli MyMathFuncs yang mendasar.
#include "MyMathFuncs.h"
using namespace MathFuncs;
extern "C" {
MyMathFuncs* CreateMyMathFuncsClass();
void DisposeMyMathFuncsClass(MyMathFuncs* ptr);
double MyMathFuncsAdd(MyMathFuncs *ptr, double a, double b);
double MyMathFuncsSubtract(MyMathFuncs *ptr, double a, double b);
double MyMathFuncsMultiply(MyMathFuncs *ptr, double a, double b);
double MyMathFuncsDivide(MyMathFuncs *ptr, double a, double b);
}
Ini akan menjadi fungsi pembungkus ini yang digunakan di sisi Xamarin .
Membungkus pustaka asli (Tahap 2)
Tahap ini memerlukan pustaka yang telah dikommpilasikan sebelumnya yang dijelaskan di bagian sebelumnya.
Membuat solusi Visual Studio
Di Visual Studio untuk Mac, klik Proyek Baru (dari Halaman Selamat Datang) atau Solusi Baru (dari menu File ).
Dari jendela Proyek Baru, pilih Proyek Bersama (dari dalam Pustaka Multiplatform>) lalu klik Berikutnya.
Perbarui bidang berikut lalu klik Buat:
- Nama Proyek: MathFuncs.Shared
- Nama Solusi: MathFuncs
- Lokasi: Gunakan lokasi penyimpanan default (atau pilih alternatif)
- Membuat proyek dalam direktori solusi: Atur ini ke diperiksa
Dari Penjelajah Solusi, klik dua kali pada proyek MathFuncs.Shared dan navigasikan ke Pengaturan Utama.
Hapus . Dibagikan dari Namespace Default sehingga diatur ke MathFuncs saja, lalu klik OK.
Buka MyClass.cs (dibuat oleh templat), lalu ganti nama kelas dan nama file menjadi MyMathFuncsWrapper dan ubah namespace menjadi MathFuncs.
CONTROL + CLICK pada solusi MathFuncs, lalu pilih Tambahkan Proyek Baru... dari menu Tambahkan .
Dari jendela Proyek Baru, pilih Pustaka Standar .NET (dari dalam Pustaka Multiplatform>) lalu klik Berikutnya.
Pilih .NET Standard 2.0 lalu klik Berikutnya.
Perbarui bidang berikut lalu klik Buat:
- Nama Proyek: MathFuncs.Standard
- Lokasi: Gunakan lokasi penyimpanan yang sama dengan proyek bersama
Dari Penjelajah Solusi, klik dua kali pada proyek MathFuncs.Standard.
Navigasi ke Pengaturan Utama, lalu perbarui Namespace Default ke MathFuncs.
Navigasikan ke pengaturan Output , lalu perbarui Nama assembly ke MathFuncs.
Navigasi ke pengaturan Pengkompilasi , ubah Konfigurasi menjadi Rilis, atur Informasi debug ke Simbol Saja lalu klik OK.
Hapus Class1.cs/Memulai dari proyek (jika salah satu dari ini telah disertakan sebagai bagian dari templat).
CONTROL + CLICK pada folder Dependensi/Referensi proyek, lalu pilih Edit Referensi.
Pilih MathFuncs.Shared dari tab Proyek , lalu klik OK.
Ulangi langkah 7-17 (mengabaikan langkah 9) menggunakan konfigurasi berikut:
NAMA PROYEK NAMA TEMPLAT MENU PROYEK BARU MathFuncs.Android Pustaka Kelas Pustaka Android > MathFuncs.iOS Pustaka Pengikatan Pustaka iOS > Dari Penjelajah Solusi, klik dua kali pada proyek MathFuncs.Android, lalu navigasikan ke pengaturan Compiler.
Dengan Konfigurasi diatur ke Debug, edit Tentukan Simbol untuk menyertakan Android;.
Ubah Konfigurasi menjadi Rilis, lalu edit Tentukan Simbol untuk juga menyertakan Android;.
Ulangi langkah 19-20 untuk MathFuncs.iOS, mengedit Definisikan Simbol untuk menyertakan iOS; bukan Android; dalam kedua kasus.
Buat solusi dalam konfigurasi Rilis (CONTROL + COMMAND + B) dan validasi bahwa ketiga rakitan output (Android, iOS, .NET Standard) (di masing-masing folder bin proyek) memiliki nama yang sama MathFuncs.dll.
Pada tahap ini, solusi harus memiliki tiga target, satu apiece untuk Android, iOS dan .NET Standard, dan proyek bersama yang dirujuk oleh masing-masing dari tiga target. Ini harus dikonfigurasi untuk menggunakan namespace dan rakitan output default yang sama dengan nama yang sama. Ini diperlukan untuk pendekatan 'umpan dan pengalihan' yang disebutkan sebelumnya.
Menambahkan pustaka asli
Proses penambahan pustaka asli ke solusi pembungkus sedikit bervariasi antara Android dan iOS.
Referensi asli untuk MathFuncs.Android
CONTROL + CLICK pada proyek MathFuncs.Android , lalu pilih Folder Baru dari menu Tambahkan penamaan lib.
Untuk setiap ABI (Antarmuka Biner Aplikasi), CONTROL + CLICK pada folder lib, lalu pilih Folder Baru dari menu Tambahkan, beri nama setelah ABI masing-masing. Dalam hal ini:
- arm64-v8a
- armeabi-v7a
- x86
- x86_64
Catatan
Untuk gambaran umum yang lebih rinci, lihat topik Arsitektur dan CPU dari panduan pengembang NDK, khususnya bagian tentang mengatasi kode asli dalam paket aplikasi.
Verifikasi struktur folder:
- lib - arm64-v8a - armeabi-v7a - x86 - x86_64Tambahkan pustaka .so yang sesuai ke setiap folder ABI berdasarkan pemetaan berikut:
arm64-v8a: lib/Android/arm64
armeabi-v7a: lib/Android/arm
x86: lib/Android/x86
x86_64: lib/Android/x86_64
Catatan
Untuk menambahkan file, CONTROL + CLICK pada folder yang mewakili ABI masing-masing, lalu pilih Tambahkan File... dari menu Tambahkan. Pilih pustaka yang sesuai (dari direktori PrecompiledLibs ) lalu klik Buka lalu klik OK meninggalkan opsi default untuk Menyalin file ke direktori.
Untuk setiap file .so , CONTROL + CLICK lalu pilih opsi EmbeddedNativeLibrary dari menu Tindakan Build.
Sekarang folder lib akan muncul sebagai berikut:
- lib
- arm64-v8a
- libMathFuncs.so
- armeabi-v7a
- libMathFuncs.so
- x86
- libMathFuncs.so
- x86_64
- libMathFuncs.so
Referensi asli untuk MathFuncs.iOS
CONTROL + CLICK pada proyek MathFuncs.iOS , lalu pilih Tambahkan Referensi Asli dari menu Tambahkan .
Pilih pustaka libMathFuncs.a (dari libs/ios di bawah direktori PrecompiledLibs) lalu klik Buka
CONTROL + CLICK pada file libMathFuncs (dalam folder Referensi Asli, lalu pilih opsi Properti dari menu
Konfigurasikan properti Referensi Asli sehingga dicentang (menampilkan ikon centang) di Properties Pad:
- Paksa Muat
- Apakah C++
- Tautan Cerdas
Catatan
Menggunakan jenis proyek pustaka pengikatan bersama dengan referensi asli menyematkan pustaka statis dan memungkinkannya untuk secara otomatis ditautkan dengan aplikasi Xamarin.iOS yang mereferensikannya (bahkan ketika disertakan melalui paket NuGet).
Buka ApiDefinition.cs, menghapus kode yang dikomentari templat (hanya
MathFuncsmenyisakan namespace), lalu lakukan langkah yang sama untuk Structs.csCatatan
Proyek pustaka Pengikatan memerlukan file-file ini (dengan tindakan build ObjCBindingApiDefinition dan ObjCBindingCoreSource ) untuk membangun. Namun, kami akan menulis kode, untuk memanggil pustaka asli kami, di luar file-file ini dengan cara yang dapat dibagikan antara target pustaka Android dan iOS menggunakan P/Invoke standar.
Menulis kode pustaka terkelola
Sekarang, tulis kode C# untuk memanggil pustaka asli. Tujuannya adalah untuk menyembunyikan kompleksitas yang mendasar. Konsumen tidak boleh memerlukan pengetahuan kerja tentang internal pustaka asli atau konsep P/Invoke.
Membuat Brankas Handle
CONTROL + KLIK pada proyek MathFuncs.Shared , lalu pilih Tambahkan File... dari menu Tambahkan .
Pilih Kelas Kosong dari jendela File Baru, beri nama MyMathFuncs Brankas Handle lalu klik Baru
Terapkan kelas MyMathFuncs Brankas Handle:
using System; using Microsoft.Win32.SafeHandles; namespace MathFuncs { internal class MyMathFuncsSafeHandle : SafeHandleZeroOrMinusOneIsInvalid { public MyMathFuncsSafeHandle() : base(true) { } public IntPtr Ptr => handle; protected override bool ReleaseHandle() { // TODO: Release the handle here return true; } } }Catatan
Brankas Handle adalah cara yang disukai untuk bekerja dengan sumber daya yang tidak dikelola dalam kode terkelola. Ini mengabstraksi banyak kode boilerplate yang terkait dengan finalisasi kritis dan siklus hidup objek. Pemilik handel ini kemudian dapat memperlakukannya seperti sumber daya terkelola lainnya dan tidak perlu menerapkan pola Sekali Pakai penuh.
Membuat kelas pembungkus internal
Buka MyMathFuncsWrapper.cs, ubah ke kelas statis internal
namespace MathFuncs { internal static class MyMathFuncsWrapper { } }Dalam file yang sama, tambahkan pernyataan kondisional berikut ke kelas :
#if Android const string DllName = "libMathFuncs.so"; #else const string DllName = "__Internal"; #endifCatatan
Ini menetapkan nilai konstanta DllName berdasarkan apakah pustaka sedang dibangun untuk Android atau iOS. Ini untuk mengatasi berbagai konvensi penamaan yang digunakan oleh setiap platform masing-masing tetapi juga jenis pustaka yang digunakan dalam kasus ini. Android menggunakan pustaka dinamis sehingga mengharapkan nama file termasuk ekstensi. Untuk iOS, '__Internal' diperlukan karena kami menggunakan pustaka statis.
Tambahkan referensi ke System.Runtime.InteropServices di bagian atas file MyMathFuncsWrapper.cs
using System.Runtime.InteropServices;Tambahkan metode pembungkus untuk menangani pembuatan dan pembuangan kelas MyMathFuncs :
[DllImport(DllName, EntryPoint = "CreateMyMathFuncsClass")] internal static extern MyMathFuncsSafeHandle CreateMyMathFuncs(); [DllImport(DllName, EntryPoint = "DisposeMyMathFuncsClass")] internal static extern void DisposeMyMathFuncs(MyMathFuncsSafeHandle ptr);Catatan
Kami meneruskan dllName konstan kami ke atribut DllImport bersama dengan EntryPoint yang secara eksplisit memberi tahu runtime .NET nama fungsi untuk dipanggil dalam pustaka tersebut. Secara teknis, kita tidak perlu memberikan nilai EntryPoint jika nama metode terkelola kita identik dengan yang tidak dikelola. Jika tidak disediakan, nama metode terkelola akan digunakan sebagai EntryPoint sebagai gantinya. Namun, lebih baik menjadi eksplisit.
Tambahkan metode pembungkus untuk memungkinkan kami bekerja dengan kelas MyMathFuncs menggunakan kode berikut:
[DllImport(DllName, EntryPoint = "MyMathFuncsAdd")] internal static extern double Add(MyMathFuncsSafeHandle ptr, double a, double b); [DllImport(DllName, EntryPoint = "MyMathFuncsSubtract")] internal static extern double Subtract(MyMathFuncsSafeHandle ptr, double a, double b); [DllImport(DllName, EntryPoint = "MyMathFuncsMultiply")] internal static extern double Multiply(MyMathFuncsSafeHandle ptr, double a, double b); [DllImport(DllName, EntryPoint = "MyMathFuncsDivide")] internal static extern double Divide(MyMathFuncsSafeHandle ptr, double a, double b);Catatan
Kami menggunakan jenis sederhana untuk parameter dalam contoh ini. Karena marshalling adalah salinan bitwise dalam hal ini tidak memerlukan pekerjaan tambahan di bagian kami. Perhatikan juga penggunaan kelas MyMathFuncs Brankas Handle alih-alih IntPtr standar. IntPtr secara otomatis dipetakan ke Brankas Handle sebagai bagian dari proses marshalling.
Verifikasi bahwa kelas MyMathFuncsWrapper yang sudah selesai muncul seperti di bawah ini:
using System.Runtime.InteropServices; namespace MathFuncs { internal static class MyMathFuncsWrapper { #if Android const string DllName = "libMathFuncs.so"; #else const string DllName = "__Internal"; #endif [DllImport(DllName, EntryPoint = "CreateMyMathFuncsClass")] internal static extern MyMathFuncsSafeHandle CreateMyMathFuncs(); [DllImport(DllName, EntryPoint = "DisposeMyMathFuncsClass")] internal static extern void DisposeMyMathFuncs(MyMathFuncsSafeHandle ptr); [DllImport(DllName, EntryPoint = "MyMathFuncsAdd")] internal static extern double Add(MyMathFuncsSafeHandle ptr, double a, double b); [DllImport(DllName, EntryPoint = "MyMathFuncsSubtract")] internal static extern double Subtract(MyMathFuncsSafeHandle ptr, double a, double b); [DllImport(DllName, EntryPoint = "MyMathFuncsMultiply")] internal static extern double Multiply(MyMathFuncsSafeHandle ptr, double a, double b); [DllImport(DllName, EntryPoint = "MyMathFuncsDivide")] internal static extern double Divide(MyMathFuncsSafeHandle ptr, double a, double b); } }
Menyelesaikan kelas MyMathFuncs Brankas Handle
Buka kelas MyMathFuncs Brankas Handle, buka komentar TODO tempat penampung dalam metode ReleaseHandle:
// TODO: Release the handle hereGanti baris TODO:
MyMathFuncsWrapper.DisposeMyMathFuncs(this);
Menulis kelas MyMathFuncs
Sekarang setelah pembungkus selesai, buat kelas MyMathFuncs yang akan mengelola referensi ke objek C++ MyMathFuncs yang tidak dikelola.
CONTROL + KLIK pada proyek MathFuncs.Shared , lalu pilih Tambahkan File... dari menu Tambahkan .
Pilih Kelas Kosong dari jendela File Baru, beri nama MyMathFuncs lalu klik Baru
Tambahkan anggota berikut ke kelas MyMathFuncs :
readonly MyMathFuncsSafeHandle handle;Terapkan konstruktor untuk kelas sehingga membuat dan menyimpan handel ke objek MyMathFuncs asli saat kelas dibuat:
public MyMathFuncs() { handle = MyMathFuncsWrapper.CreateMyMathFuncs(); }Terapkan antarmuka IDisposable menggunakan kode berikut:
public class MyMathFuncs : IDisposable { ... protected virtual void Dispose(bool disposing) { if (handle != null && !handle.IsInvalid) handle.Dispose(); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } // ... }Terapkan metode MyMathFuncs menggunakan kelas MyMathFuncsWrapper untuk melakukan pekerjaan nyata di bawah tenda dengan meneruskan pointer yang telah kami simpan ke objek yang tidak dikelola yang mendasar. Kode harus sebagai berikut:
public double Add(double a, double b) { return MyMathFuncsWrapper.Add(handle, a, b); } public double Subtract(double a, double b) { return MyMathFuncsWrapper.Subtract(handle, a, b); } public double Multiply(double a, double b) { return MyMathFuncsWrapper.Multiply(handle, a, b); } public double Divide(double a, double b) { return MyMathFuncsWrapper.Divide(handle, a, b); }
Membuat nuspec
Agar pustaka dikemas dan didistribusikan melalui NuGet, solusinya memerlukan file nuspec . Ini akan mengidentifikasi rakitan mana yang dihasilkan yang akan disertakan untuk setiap platform yang didukung.
CONTROL + CLICK pada solusi MathFuncs, lalu pilih Tambahkan Folder Solusi dari menu Tambahkan penamaan SolutionItems.
CONTROL + CLICK pada folder SolutionItems , lalu pilih File Baru... dari menu Tambahkan .
Pilih File XML Kosong dari jendela File Baru, beri nama MathFuncs.nuspec lalu klik Baru.
Perbarui MathFuncs.nuspec dengan metadata paket dasar untuk ditampilkan kepada konsumen NuGet . Contoh:
<?xml version="1.0"?> <package> <metadata> <id>MathFuncs</id> <version>$version$</version> <authors>Microsoft Mobile Customer Advisory Team</authors> <description>Sample C++ Wrapper Library</description> <requireLicenseAcceptance>false</requireLicenseAcceptance> <copyright>Copyright 2018</copyright> </metadata> </package>Catatan
Lihat dokumen referensi nuspec untuk detail lebih lanjut tentang skema yang digunakan untuk manifes ini.
<files>Tambahkan elemen sebagai anak dari<package>elemen (tepat di bawah<metadata>), mengidentifikasi setiap file dengan elemen terpisah<file>:<files> <!-- Android --> <!-- iOS --> <!-- netstandard2.0 --> </files>Catatan
Ketika paket diinstal ke dalam proyek, dan di mana ada beberapa rakitan yang ditentukan oleh nama yang sama, NuGet akan secara efektif memilih rakitan yang paling spesifik untuk platform yang diberikan.
<file>Tambahkan elemen untuk rakitan Android:<file src="MathFuncs.Android/bin/Release/MathFuncs.dll" target="lib/MonoAndroid81/MathFuncs.dll" /> <file src="MathFuncs.Android/bin/Release/MathFuncs.pdb" target="lib/MonoAndroid81/MathFuncs.pdb" /><file>Tambahkan elemen untuk rakitan iOS:<file src="MathFuncs.iOS/bin/Release/MathFuncs.dll" target="lib/Xamarin.iOS10/MathFuncs.dll" /> <file src="MathFuncs.iOS/bin/Release/MathFuncs.pdb" target="lib/Xamarin.iOS10/MathFuncs.pdb" /><file>Tambahkan elemen untuk rakitan netstandard2.0:<file src="MathFuncs.Standard/bin/Release/netstandard2.0/MathFuncs.dll" target="lib/netstandard2.0/MathFuncs.dll" /> <file src="MathFuncs.Standard/bin/Release/netstandard2.0/MathFuncs.pdb" target="lib/netstandard2.0/MathFuncs.pdb" />Verifikasi manifes nuspec:
<?xml version="1.0"?> <package> <metadata> <id>MathFuncs</id> <version>$version$</version> <authors>Microsoft Mobile Customer Advisory Team</authors> <description>Sample C++ Wrapper Library</description> <requireLicenseAcceptance>false</requireLicenseAcceptance> <copyright>Copyright 2018</copyright> </metadata> <files> <!-- Android --> <file src="MathFuncs.Android/bin/Release/MathFuncs.dll" target="lib/MonoAndroid81/MathFuncs.dll" /> <file src="MathFuncs.Android/bin/Release/MathFuncs.pdb" target="lib/MonoAndroid81/MathFuncs.pdb" /> <!-- iOS --> <file src="MathFuncs.iOS/bin/Release/MathFuncs.dll" target="lib/Xamarin.iOS10/MathFuncs.dll" /> <file src="MathFuncs.iOS/bin/Release/MathFuncs.pdb" target="lib/Xamarin.iOS10/MathFuncs.pdb" /> <!-- netstandard2.0 --> <file src="MathFuncs.Standard/bin/Release/netstandard2.0/MathFuncs.dll" target="lib/netstandard2.0/MathFuncs.dll" /> <file src="MathFuncs.Standard/bin/Release/netstandard2.0/MathFuncs.pdb" target="lib/netstandard2.0/MathFuncs.pdb" /> </files> </package>Catatan
File ini menentukan jalur output rakitan dari build Rilis , jadi pastikan untuk membangun solusi menggunakan konfigurasi tersebut.
Pada titik ini, solusi berisi 3 rakitan .NET dan manifes nuspec pendukung.
Mendistribusikan pembungkus .NET dengan NuGet
Langkah selanjutnya adalah mengemas dan mendistribusikan paket NuGet sehingga dapat dengan mudah digunakan oleh aplikasi dan dikelola sebagai dependensi. Pembungkusan dan konsumsi semuanya dapat dilakukan dalam satu solusi, tetapi mendistribusikan pustaka melalui bantuan NuGet dalam pemisahan dan memungkinkan kami mengelola basis kode ini secara independen.
Menyiapkan direktori paket lokal
Bentuk umpan NuGet yang paling sederhana adalah direktori lokal:
- Di Finder, navigasikan ke direktori yang nyaman. Misalnya, /Pengguna.
- Pilih Folder Baru dari menu File, yang menyediakan nama yang bermakna seperti local-nuget-feed.
Membuat paket
Atur Konfigurasi Build ke Rilis, dan jalankan build menggunakan COMMAND + B.
Buka Terminal dan ubah direktori ke folder yang berisi file nuspec .
Di Terminal, jalankan perintah paket nuget yang menentukan file nuspec , Versi (misalnya, 1.0.0), dan OutputDirectory menggunakan folder yang dibuat pada langkah sebelumnya, yaitu local-nuget-feed. Contohnya:
nuget pack MathFuncs.nuspec -Version 1.0.0 -OutputDirectory ~/local-nuget-feedKonfirmasikan bahwa MathFuncs.1.0.0.nupkg telah dibuat di direktori local-nuget-feed.
[OPSIONAL] Menggunakan umpan NuGet privat dengan Azure DevOps
Teknik yang lebih kuat dijelaskan dalam Memulai paket NuGet di Azure DevOps, yang menunjukkan cara membuat umpan privat dan mendorong paket (dihasilkan pada langkah sebelumnya) ke umpan tersebut.
Sangat ideal untuk memiliki alur kerja ini sepenuhnya otomatis, misalnya menggunakan Azure Pipelines. Untuk informasi selengkapnya, lihat Mulai menggunakan Azure Pipelines.
Mengonsumsi pembungkus .NET dari aplikasi Xamarin.Forms
Untuk menyelesaikan panduan, buat aplikasi Xamarin.Forms untuk menggunakan paket yang baru saja diterbitkan ke umpan NuGet lokal.
Membuat proyek Xamarin.Forms
Buka instans baru Visual Studio untuk Mac. Ini dapat dilakukan dari Terminal:
open -n -a "Visual Studio"Di Visual Studio untuk Mac, klik Proyek Baru (dari Halaman Selamat Datang) atau Solusi Baru (dari menu File ).
Dari jendela Proyek Baru, pilih Aplikasi Formulir Kosong (dari dalam Aplikasi Multiplatform>) lalu klik Berikutnya.
Perbarui bidang berikut lalu klik Berikutnya:
- Nama Aplikasi: MathFuncsApp.
- Pengidentifikasi Organisasi: Gunakan namespace layanan terbalik, misalnya, com.{your_org}.
- Platform Target: Gunakan default (target Android dan iOS).
- Kode Bersama: Atur ini ke .NET Standard (solusi "Pustaka Bersama" dimungkinkan, tetapi di luar cakupan panduan ini).
Perbarui bidang berikut lalu klik Buat:
- Nama Proyek: MathFuncsApp.
- Nama Solusi: MathFuncsApp.
- Lokasi: Gunakan lokasi penyimpanan default (atau pilih alternatif).
Di Penjelajah Solusi, CONTROL + CLICK pada target (MathFuncsApp.Android atau MathFuncs.iOS) untuk pengujian awal, lalu pilih Atur Sebagai Proyek Startup.
Pilih perangkat pilihan atau Simulator/Emulator.
Jalankan solusi (COMMAND + RETURN) untuk memvalidasi bahwa proyek Xamarin.Forms yang di-template membangun dan berjalan dengan baik.
Catatan
iOS (khususnya simulator) cenderung memiliki waktu build/deploy tercepat.
Menambahkan umpan NuGet lokal ke konfigurasi NuGet
Di Visual Studio, pilih Preferensi (dari menu Visual Studio ).
Pilih Sumber dari bawah bagian NuGet , lalu klik Tambahkan.
Perbarui bidang berikut lalu klik Tambahkan Sumber:
- Nama: Berikan nama yang bermakna, misalnya, Paket Lokal.
- Lokasi: Tentukan folder local-nuget-feed yang dibuat di langkah sebelumnya.
Catatan
Dalam hal ini tidak perlu menentukan Nama Pengguna dan Kata Sandi.
Klik OK.
Mereferensikan paket
Ulangi langkah-langkah berikut untuk setiap proyek (MathFuncsApp, MathFuncsApp.Android, dan MathFuncsApp.iOS).
- CONTROL + KLIK pada proyek, lalu pilih Tambahkan Paket NuGet... dari menu Tambahkan .
- Cari MathFuncs.
- Verifikasi Versi paket adalah 1.0.0 dan detail lainnya muncul seperti yang diharapkan seperti Judul dan Deskripsi, yaitu, MathFuncs dan Sampel Pustaka Pembungkus C++.
- Pilih paket MathFuncs , lalu klik Tambahkan Paket.
Menggunakan fungsi pustaka
Sekarang, dengan referensi ke paket MathFuncs di setiap proyek, fungsi tersedia untuk kode C#.
Buka MainPage.xaml.cs dari dalam proyek MathFuncsApp common Xamarin.Forms(dirujuk oleh MathFuncsApp.Android dan MathFuncsApp.iOS).
Tambahkan menggunakan pernyataan untuk System.Diagnostics dan MathFuncs di bagian atas file:
using System.Diagnostics; using MathFuncs;Deklarasikan instans
MyMathFuncskelas di bagianMainPageatas kelas:MyMathFuncs myMathFuncs;Ambil alih
OnAppearingmetode danOnDisappearingdariContentPagekelas dasar:protected override void OnAppearing() { base.OnAppearing(); } protected override void OnDisappearing() { base.OnDisappearing(); }OnAppearingPerbarui metode untuk menginisialisasi variabel yangmyMathFuncsdideklarasikan sebelumnya:protected override void OnAppearing() { base.OnAppearing(); myMathFuncs = new MyMathFuncs(); }OnDisappearingPerbarui metode untuk memanggilDisposemetode padamyMathFuncs:protected override void OnDisappearing() { base.OnAppearing(); myMathFuncs.Dispose(); }Terapkan metode privat yang disebut TestMathFuncs sebagai berikut:
private void TestMathFuncs() { var numberA = 1; var numberB = 2; // Test Add function var addResult = myMathFuncs.Add(numberA, numberB); // Test Subtract function var subtractResult = myMathFuncs.Subtract(numberA, numberB); // Test Multiply function var multiplyResult = myMathFuncs.Multiply(numberA, numberB); // Test Divide function var divideResult = myMathFuncs.Divide(numberA, numberB); // Output results Debug.WriteLine($"{numberA} + {numberB} = {addResult}"); Debug.WriteLine($"{numberA} - {numberB} = {subtractResult}"); Debug.WriteLine($"{numberA} * {numberB} = {multiplyResult}"); Debug.WriteLine($"{numberA} / {numberB} = {divideResult}"); }Terakhir, panggil
TestMathFuncsdi akhirOnAppearingmetode:TestMathFuncs();Jalankan aplikasi pada setiap platform target dan validasi output di Pad Output Aplikasi muncul sebagai berikut:
1 + 2 = 3 1 - 2 = -1 1 * 2 = 2 1 / 2 = 0.5Catatan
Jika Anda menemukan 'DLLNotFoundException' saat menguji di Android, atau kesalahan build di iOS, pastikan untuk memeriksa bahwa arsitektur CPU perangkat/emulator/simulator yang Anda gunakan kompatibel dengan subset yang kami pilih untuk didukung.
Ringkasan
Artikel ini menjelaskan cara membuat aplikasi Xamarin.Forms yang menggunakan pustaka asli melalui pembungkus .NET umum yang didistribusikan melalui paket NuGet. Contoh yang disediakan dalam panduan ini sengaja sangat sederhana untuk lebih mudah menunjukkan pendekatan. Aplikasi nyata harus berurusan dengan kompleksitas seperti penanganan pengecualian, panggilan balik, marshalling jenis yang lebih kompleks, dan menautkan dengan pustaka dependensi lainnya. Pertimbangan utama adalah proses di mana evolusi kode C++ dikoordinasikan dan disinkronkan dengan pembungkus dan aplikasi klien. Proses ini dapat bervariasi tergantung pada apakah salah satu atau kedua kekhawatiran tersebut adalah tanggung jawab satu tim. Bagaimanapun, otomatisasi adalah manfaat nyata. Di bawah ini adalah beberapa sumber daya yang menyediakan pembacaan lebih lanjut sekeliling beberapa konsep utama bersama dengan unduhan yang relevan.