מדריך למשתנים

מבוא

כפי שמוסבר בדף Overview, קוד המארח מבצע קריאות RPC לספרייה בתוך ארגז החול. ארגז חול גורם להפרדה בזיכרון בין התהליכים, ולכן קוד המארח לא יכול לגשת ישירות לזיכרון בספריית ארגז החול.

כדי לוודא שקוד המארח יכול לגשת למשתנים ולבלוקים של זיכרון בתהליך מרוחק, וכדי לפשט את ההטמעה של קוד הלוגיקה הראשי, SAPI מספקת קבוצה מקיפה של מחלקות C++‎. עם זאת, במקרים רבים תוכלו להשתמש גם בסוגי C מקוריים.

הצורך בסוגים המיוחדים (SAPI Types) מתעורר כשמעבירים מצביעים לסוגים פשוטים ולבלוקים של זיכרון (מבנים, מערכים).

לדוגמה, כשקוראים לפונקציה שמקבלת מצביע, צריך להמיר את המצביע למצביע תואם בזיכרון של הספרייה בתוך ארגז החול. קטע הקוד הבא ממחיש את התרחיש הזה. במקום מערך של שלושה מספרים שלמים, נוצר אובייקט ::sapi::v::Array<int> שאפשר להעביר אותו לקריאה ל-API של הספרייה המוגנת בארגז חול:

int arr[3] = {1, 2, 3};
sapi::v::Array<int> sarr(arr, ABSL_ARRAYSIZE(arr));

סקירה מקיפה של כל סוגי ה-SAPI הזמינים מופיעה בקובצי הכותרת בvar_*.h קוד המקור של פרויקט ה-SAPI. קבצי הכותרת האלה מספקים מחלקות ותבניות שמייצגות סוגים שונים של נתונים, למשל:

  • ::sapi::v::UChar מייצג תווים לא חתומים מוכרים
  • ::sapi::v::Array<int> מייצג מערך של מספרים שלמים

סוגי SAPI

בקטע הזה מוצגים שלושה סוגי SAPI שמופיעים בדרך כלל בקוד המארח.

SAPI Pointers

אם פונקציה שצריך להריץ בסביבת ארגז חול דורשת העברת מצביע, המצביע הזה צריך להתקבל מאחת משיטות PtrXXX() שמופיעות בהמשך. השיטות האלה מיושמות על ידי מחלקות משתני SAPI.

סוגי מצביעים
::PtrNone() לא מסנכרן את הזיכרון הבסיסי בין תהליך קוד המארח לבין תהליך ספריית ארגז החול כשמעבירים אותו לפונקציית API בארגז חול.
::PtrBefore() מסנכרן את הזיכרון של האובייקט שאליו הוא מצביע לפני הקריאה לפונקציית ה-API של ארגז החול. כלומר, הזיכרון המקומי של המשתנה שאליו מצביעים יועבר לתהליך של ספריית ארגז החול לפני שהקריאה תתחיל.
::PtrAfter() מסנכרן את הזיכרון של האובייקט שאליו הוא מצביע אחרי שהתבצעה קריאה לפונקציית ה-API בארגז החול. המשמעות היא שהזיכרון המרוחק של המשתנה שאליו מצביעים יועבר לזיכרון של תהליך קוד המארח אחרי שהשיחה תושלם.
::PtrBoth() משולבות בו הפונקציונליות של ::PtrBefore() ושל ::PtrAfter().

אפשר למצוא את התיעוד של מצביעים ב-SAPI כאן.

SAPI Struct

התבנית ::sapi::v::Struct מתועדת בקובץ var_struct.h. היא מספקת בנאי שאפשר להשתמש בו כדי לעטוף מבנים קיימים. ‫SAPI Struct מספק את כל השיטות שמפורטות בSAPI Pointers כדי לקבל אובייקט ::sapi::v::Ptr שאפשר להשתמש בו לקריאות לספרייה בסביבת ארגז חול.

בקטע הקוד הבא מוצג מבנה שמופעל ואז מועבר לקריאה לפונקציה בסביבת ארגז חול בדוגמה של zlib:

sapi::v::Struct<sapi::zlib::z_stream> strm;

if (ret = api.deflateInit_(strm.PtrBoth(), Z_DEFAULT_COMPRESSION,
                             version.PtrBefore(), sizeof(sapi::zlib::z_stream));

אם המבנה הקיים מכיל מצביעים, המצביעים האלה יצביעו על כתובות ב-Sandboxee. לכן, תצטרכו להעביר את הנתונים של Sandboxee לפני שהם יהיו נגישים לקוד המארח.

מערכי SAPI

התבנית ::sapi::v::Array מתועדת בקובץ var_array.h. היא מספקת שני בנאים, שאחד מהם יכול לשמש לעיטוף של מערכים קיימים של רכיבים, והשני ליצירה דינמית של מערך.

בקטע הקוד הזה (שנלקח מדוגמת sum) מוצג השימוש בבונה שעוטף מערך שלא נמצא בבעלות האובייקט הזה:

int arr[10];
sapi::v::Array<int> iarr(arr, ABSL_ARRAYSIZE(arr));

בקטע הקוד הבא מוצגת דוגמה של בנאי שמשמש ליצירה דינמית של מערך:

sapi::v::Array<uint8_t> buffer(PNG_IMAGE_SIZE(*image.mutable_data()));

מערך SAPI מספק את כל השיטות שמפורטות בSAPI Pointers כדי לקבל אובייקט ::sapi::v::Ptr שאפשר להשתמש בו לקריאות לספרייה בסביבת ארגז חול.