Hướng dẫn về biến

Giới thiệu

Như giải thích trên trang Tổng quan, Mã máy chủ thực hiện lệnh gọi RPC đến Thư viện hộp cát. Hộp cát sẽ dẫn đến sự tách biệt bộ nhớ giữa các quy trình, do đó, Mã máy chủ lưu trữ không thể truy cập trực tiếp vào bộ nhớ trong Thư viện hộp cát.

Để đảm bảo Mã máy chủ có thể truy cập các biến và khối bộ nhớ trong quá trình từ xa, đồng thời đơn giản hoá việc triển khai mã logic chính, SAPI cung cấp một tập hợp toàn diện các lớp C++. Tuy nhiên, trong nhiều trường hợp, bạn cũng có thể sử dụng kiểu C gốc.

Nhu cầu đối với các loại đặc biệt (Loại SAPI) phát sinh khi truyền con trỏ đến các loại và khối bộ nhớ đơn giản (cấu trúc, mảng).

Ví dụ: khi gọi một hàm nhận con trỏ, con trỏ phải được chuyển đổi thành con trỏ tương ứng bên trong bộ nhớ của Thư viện hộp cát. Đoạn mã dưới đây minh hoạ trường hợp này. Thay vì một mảng gồm ba số nguyên, một đối tượng ::sapi::v::Array<int> sẽ được tạo, sau đó có thể được truyền vào lệnh gọi API của Thư viện hộp cát:

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

Để biết thông tin tổng quan toàn diện về tất cả các Loại SAPI hiện có, hãy xem các tệp tiêu đề var_*.h trong mã nguồn dự án SAPI. Các tệp tiêu đề này cung cấp các lớp và mẫu đại diện cho nhiều loại dữ liệu, ví dụ:

  • ::sapi::v::UChar đại diện cho các ký tự chưa ký phổ biến
  • ::sapi::v::Array<int> đại diện cho một mảng số nguyên

Các loại SAPI

Phần này giới thiệu ba Loại SAPI thường thấy trong Mã máy chủ.

Con trỏ SAPI

Nếu một hàm đưa vào hộp cát yêu cầu truyền con trỏ, thì con trỏ này phải được lấy qua một trong các phương thức PtrXXX() dưới đây. Các phương thức này do các lớp biến SAPI triển khai.

Các loại con trỏ
::PtrNone() Không đồng bộ hoá bộ nhớ cơ bản giữa quy trình Mã máy chủ và quy trình Thư viện hộp cát khi được chuyển vào hàm API có hộp cát.
::PtrBefore() Đồng bộ hoá bộ nhớ của đối tượng mà đối tượng trỏ đến trước khi thực hiện lệnh gọi hàm API có hộp cát. Điều này có nghĩa là bộ nhớ cục bộ của biến được trỏ sẽ được chuyển sang quy trình Thư viện hộp cát trước khi bắt đầu lệnh gọi.
::PtrAfter() Đồng bộ hoá bộ nhớ của đối tượng mà đối tượng này trỏ đến sau khi lệnh gọi hàm API có hộp cát diễn ra. Điều này có nghĩa là bộ nhớ từ xa của biến được trỏ sẽ được chuyển sang bộ nhớ xử lý Mã máy chủ sau khi lệnh gọi hoàn tất.
::PtrBoth() Kết hợp chức năng của ::PtrBefore()::PtrAfter().

Bạn có thể tìm thấy tài liệu về con trỏ SAPI tại đây.

Cấu trúc SAPI

Mẫu ::sapi::v::Struct được ghi lại trong var_struct.h. Mẫu này cung cấp một hàm khởi tạo có thể dùng để gói các cấu trúc hiện có. SAPI Struct cung cấp tất cả các phương thức được nêu trong Con trỏ SAPI để lấy đối tượng ::sapi::v::Ptr có thể dùng cho các lệnh gọi thư viện hộp cát.

Đoạn mã dưới đây cho thấy một cấu trúc đang được bắt đầu rồi được chuyển vào lệnh gọi hàm có hộp cát trong ví dụ về 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));
…

Nếu cấu trúc hiện có của bạn chứa con trỏ, thì các con trỏ đó sẽ trỏ đến địa chỉ trong Sandboxee. Do đó, bạn sẽ phải chuyển dữ liệu của Sandboxee trước khi Mã máy chủ có thể truy cập được.

Mảng SAPI

Mẫu ::sapi::v::Array được ghi lại trong var_array.h. Mẫu này cung cấp hai hàm khởi tạo, một hàm có thể dùng để gói các mảng phần tử hiện có và một hàm còn lại để tạo mảng một cách linh động.

Đoạn mã này (lấy từ ví dụ tổng) cho thấy cách sử dụng hàm khởi tạo bao bọc một mảng không thuộc sở hữu của đối tượng này:

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

Đoạn mã này cho thấy ví dụ về hàm khởi tạo được dùng để tạo một mảng theo phương thức động:

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

Mảng SAPI cung cấp tất cả phương thức được nêu trong Con trỏ SAPI để lấy đối tượng ::sapi::v::Ptr có thể dùng cho các lệnh gọi thư viện hộp cát.