使用js-ctypes——處理數據

原文:
https://developer.mozilla.org/en/js-ctypes/Using_js-ctypes/Working_with_data

創建CData對象

使用js-ctypes的數據類型的由CType對象表示的。這些都是javascript構造函數。它們都是可調用的函數,你可以用來創建新的這種類型的CData對象。有幾種方式進行創建新的CData對象。

創建CData對象不初始化

不立即指定初始值有三種形式的語法來創建CData對象。
var myCDataObj = new type;
var myCDataObj = new type();
var myCDataObj = type();
這些做了同樣的事情:它們返回一個新的指定類型的CData對象,其數據緩存全部由0填充。
注:如果type.size是undefined,這種方式創建新對象將會拋出一個TypeError的異常。

創建CData對象並初始化

類似的,你可以用指定的值在類型創建的時候初始化CData對象,這可以通過調用CType的構造函數時指定它們爲一個參數,像這樣:
var myCDataObj = new type(value);
var myCDataObj = type(value);
如果指定類型的大小不是undefined,該指定的值將會轉換爲給定的類型。如果轉換無法進行,將會拋出TypeError異常。結果會複製到一個新的CData對象中。如果初始值已經是一個CData對象,原來的對象就會簡單的直接複製到新的中去。
如type是一個沒指定長度的數組類型,將會執行下面的步驟:
如果value是一個大小值,則創建一個以該值爲長度的數組,其每個單元已經可以接受相同的類型作爲指定的數組。這與使用new ArrayType(type.elementType, value)是一樣的。
如果type表示的是一個javascript字符串(也就是說,一個jschar數組,末尾跟着null),則創建該字符串的拷貝並返回。
如果type是一個8位字符數組並且value是一個UTF-16字符串,新的CData對象是將UTF-16字符串轉換爲UTF-8的結果,以null結尾。
如果value是一個javascript數組對象且長度非負,則創建一個新的數組並且value指定的數組內容轉換爲CData對象並複製到新的數組中,然後返回這個新的數組。
如果上述都不滿足,則拋出TypeError異常。如果type是ctypes.void_t,拋出TypeError異常。

例:創建一個數組

let arrayType = ctypes.ArrayType(ctypes.int32_t);
let myArray = new arrayType(5);

這裏,myArray.length是5;數組中有5個項。myArray.constructor.size是20.數組的數據緩存的總大小是20byte(5項,每項4byte)

類型轉換

你可以通過使用ctypes.cast()函數將數據從一種類型轉換爲另一種類型:
var newObj = ctypes.cast(origObj, newType);
這會返回一個新的對象,其數據塊與原始對象共享,但是其類型是newType。如果新類型的大小是undefined或者比原始對象的數據塊大,則拋出TypeError異常。
這與標準C類型轉換或者C++的reinterpret_cast非常相似。

數據與指針

一個CData對象表示了內存中一個C的值。你總是可以通過CData對象的address()方法獲取一個指向這個C值的指針。

對象可以共享內存

牢記兩個(或更多)CData對象可以共享同一片內存塊作爲它們的內容非常重要。例如,在類型轉換的時候會發生。這叫做別名混淆(aliasing)。共享的內存可以是全部也可以是一部分。例如:
const Point = new ctypes.StructType("Point", [{x: ctypes.int32_t}, {y: ctypes.int32_t}]);
const Rect = new ctypes.StructType("Rect", [{topLeft: Point}, {bottomRight: Point}]);

var r = Rect();
var p = r.topLeft;
r.topLeft.x = 100;

這裏,p是Rect對象r的一個指向topLeft的引用。設置p.x的值將會影響r.topLeft.x的值。

相等的怪現象Quirks in equality

Javascript中判斷相等與否與C中有着很大的不同,詳細說明見原文。

例:檢查一個整型值

例如,在需要檢查一個整型值是不是5的時候可以這樣做:
var t = ctypes.int32_t(5);
if (t.toString() == "ctypes.int32_t(5)") {
// it's 5
}

處理字符串

C函數需要的字符串是字符數組,字符串的末尾由一個null字符標誌。然而,在javascript中,使用String對象來表示字符串。

將C字符串轉換爲javascript的字符串

CData對提供了readString()方法來從指定的字符串讀取字節並返回一個新的javascriptString對象表示那個字符串。
注意:源代碼中的C字符串認爲是UTF-8的,且認爲其以null結尾。如果你需要轉換不滿足這個條件的字符串,則需要你自己來實現。
例如:var jsString = timeStr.readString();

將javascript字符串轉換爲C字符串

將javascript字符串轉換爲C格式的字符串非常簡單,只需要創建一個包含這個javascript字符串的字符數組。
var myUTF8String = ctypes.char.array()("Original string.");
這創建一個UTF-8格式的null結尾的字符串在字符數組中,名爲myUTF8String。
如果你需要一個UTF-16字符串,可以這樣:
var myUTF16String = ctypes.jschar.array()("Original string.");
注意:這裏,沒有指定編碼方式;你可以只檢索UTF-8或UTF-16的字符串。

C函數中使用字符串

你在使用它們作爲C函數的輸入參數的時候甚至不需要進行字符串轉換。它們自動爲你進行了轉換。只需要傳遞javascript的String對象。
但是,當C函數返回的時候,它們返回的是一個char.ptr或者jschar.ptr(也就是一個指向8位或16位字符數組)。你不得不自己對其進行轉換,如上面所描述的那樣。

處理指針

讀取指針所引用的數據

這個例子創建一個指向整型數據的指針,然後使用PointerType對象的contents屬性來獲取指針指向的數據。
var i = ctypes.int32_t(9); // Create a C integer whose value is 9
var p = i.address(); // Create a pointer to the integer variable i
if (p.contents == 9) { // Look at the contents of the pointer
// the value is 9
} else {
// the value isn't 9
}

設置指針引用的數據

你也可以使用contents屬性來設置指針指向的變量的值。
var i = ctypes.int32_t(9); // Create a C integer variable whose value is 9
var p = i.address(); // Get a pointer to i
p.contents = 12; // Change the value of i to 12

檢查指針是否爲空

這個例子說明了使用isNull()方法來確定一個指針是否爲空。
var p = someCDataObject.address();

if (p.isNull()) {
// the pointer is null
} else {
// the pointer isn't null
}


檢查兩個指針是否相等

由於在javascript中檢測相等的特殊,檢查兩個指針是否相等的最好方式是將它們轉換成字符串,然後比較字符串。
if (i.address().toString() == ctypes.int32_t.ptr(5).toString()) {
// the integer i's address is 5
}

上面這個例子不僅僅比較了地址,還比較了類型,因此,如果i的地址是5並且i確實是ctypes.int32_t類型,上面的比較才成功。
if (ctypes.cast(p, ctypes.uintptr_t).value.toString() == "5") {
// the pointer p's address is 5
}

這裏將指針轉換爲一個ctypes.uintptr_t類型,其value屬性返回一個ctypes.UInt64的值。調用toString()返回十進制整數值。

使用指針數組

如果你需要處理C函數接收的是指針數組作爲輸入,你可以構造一個指針的數組,像這樣:
var ptrArrayType = ctypes.char.ptr.array(5);
var myArray = ptrArrayType();
var someCFunction = library.declare("someCFunction", ctypes.default_abi, ctypes.void_t, ctypes.char.ptr.array());
someCFunction(myArray);

第一行聲明瞭一個新的數組類型,可以容納5個指向C字符數組的指針。這可能是一個字符串數組。接下來的一行實例化了一個該類型的對象,創建了一個新的數組。這個數組中每個指針都初始化爲null。第三行聲明瞭一個接受這個數組爲輸入參數的C函數。最後一行調用這個函數。

64-bit integers

略之,請參考原文。

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