使用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;


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