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

מבוא

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

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

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

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

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

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

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

התיעוד לגבי מצביעי SAPI זמין כאן.

מבנה SAPI

התבנית ::sapi::v::Struct מתועדת ב-var_struct.h. היא מספקת בנאי שיכול לשמש לארוז מבנים קיימים. ב-SAPI Struct יש את כל השיטות שמפורטות במצביעי SAPI להשגת אובייקט ::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. היא מספקת שני בנאים, אחד שאפשר להשתמש בו כדי לעטוף מערכים קיימים של אלמנטים, ואחד כדי ליצור מערך באופן דינמי.

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

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 להשגת אובייקט ::sapi::v::Ptr שניתן להשתמש בו לקריאות לספרייה בארגז חול.