FFI
این سند مشخصات FFI (واسطه توابع خارجی) برای فراخوانی توابع پیادهسازی شده در خارج از زبان Wave را توضیح میدهد. از طریق FFI، برنامههای Wave میتوانند به طور مستقیم با کتابخانههای بومی نوشته شده به زبانهای دیگر تعامل داشته باشند.
خلاصه
FFI در Wave براساس اعلانها عمل میکند. توابع خارجی در کد Wave پیادهسازی نمیشوند و فقط مشخص میشود که تابع مربوطه از چه ABI (واسطه باینری برنامه) پیروی میکند. پیادهسازی واقعی در مرحله لینک از کتابخانههای خارجی به دست میآید.
FFI در زمان کامپایل تنها وجود تابع را اعلام میکند و در زمان ایجاد فایل اجرایی، لینککننده به نماد واقعی متصل میشود.
اعلان extern
توابع خارجی با استفاده از کلمه کلیدی extern اعلان میشوند.
در حال حاضر در ویو مشخص کردن ABI ضروری است و فقط extern(c) پشتیبانی میشود.
extern(c) fun function_name(args...) -> return_type;
تعیین کردن ABI
در اعلان extern باید ABI را مشخص کنید.
در حال حاضر ABI پشتیبانی شده تنها c است.
extern(c) fun printf(fmt: ptr<u8>);
اعلان هایی مانند extern(rust) ممکن است تجزیه شوند اما در مرحله تحلیل معنایی خطا رخ میدهد.
اعلان extern در سطح تابع
برای اعلام یک تابع خارجی به صورت زیر عمل میکنیم.
extern(c) fun InitWindow(width: i32, height: i32, title: ptr<u8>);
این اعلان به معنای وجود نماد InitWindow که از ABI C پیروی میکند در کتابخانه خارجی است.
اعلان extern در سطح بلوک
در صورتی که چندین تابع خارجی از همان ABI استفاده کنند، میتوان اعلامیهها را به صورت بلوکی گروهبندی کرد.
extern(c) {
fun InitWindow(width: i32, height: i32, title: ptr<u8>);
fun CloseWindow();
fun BeginDrawing();
fun EndDrawing();
}
اعلانهای سطح بلاک از نظر معنایی کاملاً با اعلانهای سطح تابع یکسان هستند و صرفاً از نظر خوانایی و ساختاردهی برای قواعد دستوری استفاده میشوند.
تعیین نام نماد
در برخی ABIها، نام تابع Wave ممکن است با نام نماد لینک شده واقعی مطابقت نداشته باشد. در این حالت، میتوان نام نماد واقعی که تابع خارجی به آن متصل میشود را به صورت رشتهای مشخص کرد.
تعیین نماد سطح تابع
extern(c, "puts")
fun rust_func(i32);
این اعلان مشخص میکند که در هنگام فراخوانی rust_func از نماد لینک واقعی puts استفاده شود.
تعیین نماد سطح بلاک
در اعلان سطح بلاک، میتوان نام نماد را به صورت جداگانه پس از هر تابع مشخص کرد.
extern(c) {
fun my_puts(ptr<i8>) "puts";
fun my_strlen(ptr<i8>) "strlen";
}
