使用js-ctypes——聲明類型

原文:https://developer.mozilla.org/en/js-ctypes/Using_js-ctypes/Declaring_types
原文標明,本文尚未完成。如有疑問請參照原文。
Ctypes對象提供了許多聲明類型的方法,每種類型都由一個CType對象表示,CType對象提供了一個構造方法,可以通過調用該方法來定義這些類型的值。使用js-ctypes聲明的類型相對於相關的C聲明。
類型以其他已經定義的類型進行聲明。其所有的核心就是由js-ctypes提供的一系列預定義類型。這些都是基本類型,基於這些類型之上的所有其他類型也可以用來聲明類型。

基礎類型

基礎類型是那些代表內存中簡單值的類型,與數組、結構體、函數不同。基礎類型的值可以不用聲明新的類型而直接進行定義。例如,要定義一個新的32位整型變量,其值爲5:var i = ctypes.int32_t(5);
然後你可以傳遞一個指向該值的指針到一個需要指向32位整型值的C函數,像這樣:some_c_function(i.address());

聲明新的基礎類型

有時候需要創建新的類型,且只是簡單的對已有的基礎類型賦予新的名稱。例如,在windows中,你可能想要使用windows標準的DWORD類型名來表示32位無符號整型。要聲明這個類型,可以簡單的這樣做:const DWORD = ctypes.uint32_t;
這樣,DWORD是一個CType可以用來代表32位無符號整型。

結構體

結構體的聲明用ctypes.StructType()構造。該方法接受結構體的名稱和一個字段描述符爲輸入參數。每個描述符描述結構體中的一個字段。你可以不寫字段描述符數組,這樣會創建一個不透明結構體,其內容是未定義。

字段描述符

每個字段描述符由一個字段名和其數據類型組成,由一個字符串和一個CType對象表示。格式如下:
[
{ field1: type1 },
{ field2: type2 },
...
{ fieldN: typeN }
]

例子

例如,要支持C的tm結構,使用js-ctypes,你可以使用下面的代碼:
const struct_tm = new ctypes.StructType("tm",
[ { "tm_sec": ctypes.int },
{ "tm_min": ctypes.int },
{ "tm_hour": ctypes.int },
{ "tm_mday": ctypes.int },
{ "tm_mon": ctypes.int },
{ "tm_year": ctypes.int },
{ "tm_wday": ctypes.int },
{ "tm_yday": ctypes.int },
{ "tm_isdst": ctypes.int } ]);


然後就可以聲明並用一個函數來使用這個結構了,像這樣:
// Declare the libc asctime() function, which returns a char * and accepts a pointer to a tm structure.

const asctime = lib.declare("asctime", ctypes.default_abi, ctypes.char.ptr, struct_tm.ptr);

var theTime = new struct_tm;
theTime.tm_hour = 3;
theTime.tm_min = 15;
...

var timeStr = asctime(theTime.address()); // Pass a pointer to the tm struct

var jsString = timeStr.readString(); // Convert the C string to JavaScript


最後一行調用CData的readString()方法將由libc的asctime()函數返回的C字符串轉換爲javascript字符串。

不透明結構體

一個不透明結構體是一個內容字段未知的結構體,或者不可以直接訪問。用它們可以處理一些先進的聲明。通過聲明一個結構體爲不透明,如果需要保護一個尚未定義的結構體。你可以在以後通過調用CType對象的define()方法來對不透明結構體中的字段進行定義。例如:
var someStructure = ctypes.StructType("someStructure");
var anotherStruct = ctypes.StructType("anotherStruct", [ {field1: opaque.ptr} ]);
someStructure.define([ { ptrToAnotherStruct: anotherStruct.ptr } ]);


這兩個結構體類型包含有相互指向的指針,首先使其中一個爲不透明,你就可以定義另外一個,然後再定義第一個的字段。這便於在javascript中石油前向引用。

數組

要聲明一個新的數組類型,可以石油ctypes.ArrayType()方法。當聲明新的數組類型的時候,你可以提供一個CType表明數組中的元素類型以及一個可選的數組長度。你可以指定數組長度也可以不指定數組長度。

不指定長度聲明數組類型

要聲明一個新的數組類型而不指定長度,你可以在調用ctypes. ArrayType()的時候簡單的傳遞一個CType指定的元素類型。例如,創建一個C標準I/O FILE指針的數組(或許用於跟蹤硬盤上一些活動文件):
const FILE = new ctypes.StructType("FILE").ptr; // Create FILE as a FILE * type
const FileArray = new ctypes.ArrayType(FILE); // Create a FileArray type


在這個例子中FILE是一個不透明指針我們用了參考C的FILE記錄,定義在stdio.h中。FielArray是一個新的類型,代表一個沒指定長度的數組,其中美國條目都是一個指向FILE記錄的指針。

指定長度聲明數組類型

定義一個指定長度的數組類型只需要簡單的在調用ctypes. ArrayType()的時候添加一個長度即可,像這樣:const FileArray = new ctypes.ArrayType(FILE, 20);
這聲明瞭FileArray作爲一個數組類型,可以存儲20個元素。

指針

聲明一個指針類型指向一個特定的類型可以通過傳遞一個CType對象作爲參數到ctypes.PointerType()方法即可實現。這個CType類型表明了該指針需要指向的類型:
const IntPtr = new ctypes.PointerType(ctypes.int);
這裏IntPtr與C中如下的聲明等效:
typedef int *intPtr;
你可以類似的聲明一個指針類型左右任何用戶所定義的類型的指針,包括結構:
const UserRecord = new ctypes.StructType("UserRecord",
[{"name": ctypes.char.ptr},
{"id": ctypes.int32}]);
const UserRecordPtr = new ctypes.PointerType(UserRecord);


在這個例子中,定義了一個新的UserRecord類型,這樣就可以使用一個新的指針類型來引用它,等效的C代碼是這樣:
typedef struct UserRecord {
char *name;
int id; // Assuming int is 32-bit here
} UserRecord;

typedef UserRecordPtr *UserRecord;


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章