зеркало из https://github.com/mozilla/pjs.git
Bug 558949 - Make ctypes functions FunctionType.ptr's. r=benjamn
This commit is contained in:
Родитель
ba38fac269
Коммит
14ec83f753
|
@ -146,8 +146,8 @@ namespace StructType {
|
|||
|
||||
namespace FunctionType {
|
||||
static JSBool Create(JSContext* cx, uintN argc, jsval* vp);
|
||||
static JSBool ConstructData(JSContext* cx, JSObject* obj, uintN argc,
|
||||
jsval* argv, jsval* rval);
|
||||
static JSBool ConstructData(JSContext* cx, JSObject* typeObj,
|
||||
JSObject* dataObj, JSObject* fnObj, JSObject* thisObj);
|
||||
|
||||
static JSBool Call(JSContext* cx, JSObject* obj, uintN argc, jsval* argv,
|
||||
jsval* rval);
|
||||
|
@ -1579,7 +1579,6 @@ ConvertToJS(JSContext* cx,
|
|||
break;
|
||||
}
|
||||
case TYPE_pointer:
|
||||
case TYPE_function:
|
||||
case TYPE_array:
|
||||
case TYPE_struct: {
|
||||
// We're about to create a new CData object to return. If the caller doesn't
|
||||
|
@ -1596,6 +1595,8 @@ ConvertToJS(JSContext* cx,
|
|||
*result = OBJECT_TO_JSVAL(obj);
|
||||
break;
|
||||
}
|
||||
case TYPE_function:
|
||||
JS_NOT_REACHED("cannot return a FunctionType");
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -1774,14 +1775,6 @@ ImplicitConvert(JSContext* cx,
|
|||
}
|
||||
return TypeError(cx, "pointer", val);
|
||||
}
|
||||
case TYPE_function: {
|
||||
if (JSVAL_IS_NULL(val)) {
|
||||
// Convert to a null function pointer.
|
||||
*static_cast<void**>(buffer) = NULL;
|
||||
break;
|
||||
}
|
||||
return TypeError(cx, "function", val);
|
||||
}
|
||||
case TYPE_array: {
|
||||
JSObject* baseType = ArrayType::GetBaseType(cx, targetType);
|
||||
size_t targetLength = ArrayType::GetLength(cx, targetType);
|
||||
|
@ -1937,6 +1930,7 @@ ImplicitConvert(JSContext* cx,
|
|||
return TypeError(cx, "struct", val);
|
||||
}
|
||||
case TYPE_void_t:
|
||||
case TYPE_function:
|
||||
JS_NOT_REACHED("invalid type");
|
||||
return false;
|
||||
}
|
||||
|
@ -1999,14 +1993,6 @@ ExplicitConvert(JSContext* cx, jsval val, JSObject* targetType, void* buffer)
|
|||
*static_cast<uintptr_t*>(buffer) = result;
|
||||
break;
|
||||
}
|
||||
case TYPE_function: {
|
||||
// Convert a number, Int64 object, or UInt64 object to a function pointer.
|
||||
uintptr_t result;
|
||||
if (!jsvalToPtrExplicit(cx, val, &result))
|
||||
return TypeError(cx, "function", val);
|
||||
*static_cast<uintptr_t*>(buffer) = result;
|
||||
break;
|
||||
}
|
||||
case TYPE_float32_t:
|
||||
case TYPE_float64_t:
|
||||
case TYPE_float:
|
||||
|
@ -2017,6 +2003,7 @@ ExplicitConvert(JSContext* cx, jsval val, JSObject* targetType, void* buffer)
|
|||
JS_SetPendingException(cx, ex.value());
|
||||
return false;
|
||||
case TYPE_void_t:
|
||||
case TYPE_function:
|
||||
JS_NOT_REACHED("invalid type");
|
||||
return false;
|
||||
}
|
||||
|
@ -2080,9 +2067,6 @@ BuildTypeName(JSContext* cx, JSObject* typeObj)
|
|||
case TYPE_function: {
|
||||
FunctionInfo* fninfo = FunctionType::GetFunctionInfo(cx, currentType);
|
||||
|
||||
// Function pointer goes on the left.
|
||||
PrependString(result, "*");
|
||||
|
||||
// Add in the calling convention, if it's not cdecl.
|
||||
if (GetABICode(cx, fninfo->mABI) == ABI_STDCALL)
|
||||
PrependString(result, "__stdcall ");
|
||||
|
@ -2105,8 +2089,9 @@ BuildTypeName(JSContext* cx, JSObject* typeObj)
|
|||
AppendString(result, ")");
|
||||
|
||||
// Set 'currentType' to the return type, and let the loop process it.
|
||||
// 'prevGrouping' doesn't matter here, because functions cannot return
|
||||
// arrays -- thus the parenthetical rules don't get tickled.
|
||||
currentType = fninfo->mReturnType;
|
||||
prevGrouping = currentGrouping;
|
||||
continue;
|
||||
}
|
||||
default:
|
||||
|
@ -2452,10 +2437,11 @@ CType::ConstructData(JSContext* cx,
|
|||
case TYPE_void_t:
|
||||
JS_ReportError(cx, "cannot construct from void_t");
|
||||
return JS_FALSE;
|
||||
case TYPE_function:
|
||||
JS_ReportError(cx, "cannot construct from FunctionType; use FunctionType.ptr instead");
|
||||
return JS_FALSE;
|
||||
case TYPE_pointer:
|
||||
return PointerType::ConstructData(cx, obj, argc, argv, rval);
|
||||
case TYPE_function:
|
||||
return FunctionType::ConstructData(cx, obj, argc, argv, rval);
|
||||
case TYPE_array:
|
||||
return ArrayType::ConstructData(cx, obj, argc, argv, rval);
|
||||
case TYPE_struct:
|
||||
|
@ -3179,8 +3165,8 @@ PointerType::ConstructData(JSContext* cx,
|
|||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (argc > 1) {
|
||||
JS_ReportError(cx, "constructor takes zero or one argument");
|
||||
if (argc > 2) {
|
||||
JS_ReportError(cx, "constructor takes 0, 1, or 2 arguments");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
|
@ -3190,12 +3176,39 @@ PointerType::ConstructData(JSContext* cx,
|
|||
|
||||
*rval = OBJECT_TO_JSVAL(result);
|
||||
|
||||
if (argc == 1) {
|
||||
if (!ExplicitConvert(cx, argv[0], obj, CData::GetData(cx, result)))
|
||||
return JS_FALSE;
|
||||
if (argc == 0) {
|
||||
// Construct a null pointer.
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
if (argc >= 1) {
|
||||
JSObject* baseObj = PointerType::GetBaseType(cx, obj);
|
||||
if (baseObj && CType::GetTypeCode(cx, baseObj) == TYPE_function &&
|
||||
JSVAL_IS_OBJECT(argv[0]) &&
|
||||
JS_ObjectIsFunction(cx, JSVAL_TO_OBJECT(argv[0]))) {
|
||||
// Construct a FunctionType.ptr from a JS function, and allow an
|
||||
// optional 'this' argument.
|
||||
JSObject* thisObj = NULL;
|
||||
if (argc == 2) {
|
||||
if (JSVAL_IS_OBJECT(argv[1])) {
|
||||
thisObj = JSVAL_TO_OBJECT(argv[1]);
|
||||
} else if (!JS_ValueToObject(cx, argv[1], &thisObj)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
JSObject* fnObj = JSVAL_TO_OBJECT(argv[0]);
|
||||
return FunctionType::ConstructData(cx, baseObj, result, fnObj, thisObj);
|
||||
}
|
||||
|
||||
if (argc == 2) {
|
||||
JS_ReportError(cx, "first argument must be a function");
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// Construct from a raw pointer value.
|
||||
return ExplicitConvert(cx, argv[0], obj, CData::GetData(cx, result));
|
||||
}
|
||||
|
||||
JSObject*
|
||||
|
@ -4336,9 +4349,9 @@ PrepareType(JSContext* cx, jsval type)
|
|||
if (!result)
|
||||
return NULL;
|
||||
|
||||
} else if (typeCode == TYPE_void_t) {
|
||||
// disallow void argument types
|
||||
JS_ReportError(cx, "Cannot have void argument type");
|
||||
} else if (typeCode == TYPE_void_t || typeCode == TYPE_function) {
|
||||
// disallow void or function argument types
|
||||
JS_ReportError(cx, "Cannot have void or function argument type");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -4360,9 +4373,9 @@ PrepareReturnType(JSContext* cx, jsval type)
|
|||
JSObject* result = JSVAL_TO_OBJECT(type);
|
||||
TypeCode typeCode = CType::GetTypeCode(cx, result);
|
||||
|
||||
// Arrays can never be return types.
|
||||
if (typeCode == TYPE_array) {
|
||||
JS_ReportError(cx, "Result type cannot be an array");
|
||||
// Arrays and functions can never be return types.
|
||||
if (typeCode == TYPE_array || typeCode == TYPE_function) {
|
||||
JS_ReportError(cx, "Return type cannot be an array or function");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -4431,6 +4444,11 @@ NewFunctionInfo(JSContext* cx,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
ffi_abi abi;
|
||||
if (!GetABI(cx, abiType, &abi)) {
|
||||
JS_ReportError(cx, "Invalid ABI specification");
|
||||
return NULL;
|
||||
}
|
||||
fninfo->mABI = JSVAL_TO_OBJECT(abiType);
|
||||
|
||||
// prepare the result type
|
||||
|
@ -4557,10 +4575,9 @@ FunctionType::CreateInternal(JSContext* cx,
|
|||
SLOT_FUNCTIONDATAPROTO);
|
||||
|
||||
// Create a new CType object with the common properties and slots.
|
||||
// We use ffi_type_void here in its capacity as "a type of undefined size".
|
||||
JSObject* typeObj = CType::Create(cx, typeProto, dataProto, TYPE_function,
|
||||
NULL, INT_TO_JSVAL(sizeof(void*)),
|
||||
INT_TO_JSVAL(ffi_type_pointer.alignment),
|
||||
&ffi_type_pointer, NULL);
|
||||
NULL, JSVAL_VOID, JSVAL_VOID, &ffi_type_void, NULL);
|
||||
if (!typeObj)
|
||||
return NULL;
|
||||
js::AutoValueRooter root(cx, typeObj);
|
||||
|
@ -4582,75 +4599,38 @@ FunctionType::CreateInternal(JSContext* cx,
|
|||
|
||||
JSBool
|
||||
FunctionType::ConstructData(JSContext* cx,
|
||||
JSObject* obj,
|
||||
uintN argc,
|
||||
jsval* argv,
|
||||
jsval* rval)
|
||||
JSObject* typeObj,
|
||||
JSObject* dataObj,
|
||||
JSObject* fnObj,
|
||||
JSObject* thisObj)
|
||||
{
|
||||
if (!CType::IsCType(cx, obj) || CType::GetTypeCode(cx, obj) != TYPE_function) {
|
||||
JS_ReportError(cx, "not a FunctionType");
|
||||
JS_ASSERT(CType::GetTypeCode(cx, typeObj) == TYPE_function);
|
||||
|
||||
PRFuncPtr* data = static_cast<PRFuncPtr*>(CData::GetData(cx, dataObj));
|
||||
|
||||
FunctionInfo* fninfo = FunctionType::GetFunctionInfo(cx, typeObj);
|
||||
if (fninfo->mIsVariadic) {
|
||||
JS_ReportError(cx, "Can't declare a variadic callback function");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JSObject* result = CData::Create(cx, obj, NULL, NULL, true);
|
||||
if (!result)
|
||||
JSObject* closureObj = CClosure::Create(cx, typeObj, fnObj, thisObj, data);
|
||||
if (!closureObj)
|
||||
return JS_FALSE;
|
||||
js::AutoValueRooter root(cx, closureObj);
|
||||
|
||||
// Set the closure object as the referent of the new CData object.
|
||||
if (!JS_SetReservedSlot(cx, dataObj, SLOT_REFERENT,
|
||||
OBJECT_TO_JSVAL(closureObj)))
|
||||
return JS_FALSE;
|
||||
|
||||
*rval = OBJECT_TO_JSVAL(result);
|
||||
|
||||
if (argc == 0) {
|
||||
// Construct a null pointer.
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
if (argc == 1 || argc == 2) {
|
||||
jsval arg = argv[0];
|
||||
PRFuncPtr* data = static_cast<PRFuncPtr*>(CData::GetData(cx, result));
|
||||
|
||||
if (JSVAL_IS_OBJECT(arg) && JS_ObjectIsFunction(cx, JSVAL_TO_OBJECT(arg))) {
|
||||
FunctionInfo* fninfo = FunctionType::GetFunctionInfo(cx, obj);
|
||||
if (fninfo->mIsVariadic) {
|
||||
JS_ReportError(cx, "Can't declare a variadic callback function");
|
||||
return JS_FALSE;
|
||||
}
|
||||
// Construct from a JS function, and allow an optional 'this' argument.
|
||||
JSObject* thisObj = NULL;
|
||||
if (argc == 2) {
|
||||
if (JSVAL_IS_OBJECT(argv[1])) {
|
||||
thisObj = JSVAL_TO_OBJECT(argv[1]);
|
||||
} else if (!JS_ValueToObject(cx, argv[1], &thisObj)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
JSObject* fnObj = JSVAL_TO_OBJECT(arg);
|
||||
JSObject* closureObj = CClosure::Create(cx, obj, fnObj, thisObj, data);
|
||||
if (!closureObj)
|
||||
return JS_FALSE;
|
||||
js::AutoValueRooter root(cx, closureObj);
|
||||
|
||||
// Set the closure object as the referent of the new CData object.
|
||||
if (!JS_SetReservedSlot(cx, result, SLOT_REFERENT,
|
||||
OBJECT_TO_JSVAL(closureObj)))
|
||||
return JS_FALSE;
|
||||
|
||||
// Seal the CData object, to prevent modification of the function pointer.
|
||||
// This permanently associates this object with the closure, and avoids
|
||||
// having to do things like reset SLOT_REFERENT when someone tries to
|
||||
// change the pointer value.
|
||||
// XXX This will need to change when bug 541212 is fixed -- CData::ValueSetter
|
||||
// could be called on a sealed object.
|
||||
return JS_SealObject(cx, result, JS_FALSE);
|
||||
}
|
||||
|
||||
if (argc == 1) {
|
||||
// Construct from a raw pointer value.
|
||||
return ExplicitConvert(cx, arg, obj, data);
|
||||
}
|
||||
}
|
||||
|
||||
JS_ReportError(cx, "constructor takes 0, 1, or 2 arguments");
|
||||
return JS_FALSE;
|
||||
// Seal the CData object, to prevent modification of the function pointer.
|
||||
// This permanently associates this object with the closure, and avoids
|
||||
// having to do things like reset SLOT_REFERENT when someone tries to
|
||||
// change the pointer value.
|
||||
// XXX This will need to change when bug 541212 is fixed -- CData::ValueSetter
|
||||
// could be called on a sealed object.
|
||||
return JS_SealObject(cx, dataObj, JS_FALSE);
|
||||
}
|
||||
|
||||
typedef Array<AutoValue, 16> AutoValueAutoArray;
|
||||
|
@ -4699,8 +4679,10 @@ FunctionType::Call(JSContext* cx,
|
|||
}
|
||||
|
||||
JSObject* typeObj = CData::GetCType(cx, obj);
|
||||
if (CType::GetTypeCode(cx, typeObj) != TYPE_function) {
|
||||
JS_ReportError(cx, "not a FunctionType");
|
||||
if (CType::GetTypeCode(cx, typeObj) != TYPE_pointer ||
|
||||
!(typeObj = PointerType::GetBaseType(cx, typeObj)) ||
|
||||
CType::GetTypeCode(cx, typeObj) != TYPE_function) {
|
||||
JS_ReportError(cx, "not a FunctionType.ptr");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -252,16 +252,26 @@ Library::Declare(JSContext* cx, uintN argc, jsval* vp)
|
|||
return JS_FALSE;
|
||||
root.setObject(typeObj);
|
||||
|
||||
// Make a function pointer type.
|
||||
typeObj = PointerType::CreateInternal(cx, NULL, typeObj, NULL);
|
||||
if (!typeObj)
|
||||
return JS_FALSE;
|
||||
root.setObject(typeObj);
|
||||
|
||||
} else {
|
||||
// Case 2).
|
||||
if (JSVAL_IS_PRIMITIVE(argv[1]) ||
|
||||
!CType::IsCType(cx, JSVAL_TO_OBJECT(argv[1]))) {
|
||||
JS_ReportError(cx, "second argument must be a type");
|
||||
!CType::IsCType(cx, JSVAL_TO_OBJECT(argv[1])) ||
|
||||
!CType::IsSizeDefined(cx, JSVAL_TO_OBJECT(argv[1]))) {
|
||||
JS_ReportError(cx, "second argument must be a type of defined size");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
typeObj = JSVAL_TO_OBJECT(argv[1]);
|
||||
isFunction = CType::GetTypeCode(cx, typeObj) == TYPE_function;
|
||||
if (CType::GetTypeCode(cx, typeObj) == TYPE_pointer) {
|
||||
JSObject* baseType = PointerType::GetBaseType(cx, typeObj);
|
||||
isFunction = baseType && CType::GetTypeCode(cx, baseType) == TYPE_function;
|
||||
}
|
||||
}
|
||||
|
||||
void* data;
|
||||
|
|
|
@ -1334,12 +1334,14 @@ function run_type_ctor_class_tests(c, t, t2, props, fns, instanceProps, instance
|
|||
do_check_throws(function() { t.prototype[p]; }, Error);
|
||||
|
||||
// Test that an instance 'd' of 't' is a CData.
|
||||
let d = t();
|
||||
do_check_class(d, "CData");
|
||||
do_check_true(d.__parent__ === ctypes);
|
||||
do_check_true(d.__proto__ === t.prototype);
|
||||
do_check_true(d instanceof t);
|
||||
do_check_true(d.constructor === t);
|
||||
if (t.__proto__ != ctypes.FunctionType.prototype) {
|
||||
let d = t();
|
||||
do_check_class(d, "CData");
|
||||
do_check_true(d.__parent__ === ctypes);
|
||||
do_check_true(d.__proto__ === t.prototype);
|
||||
do_check_true(d instanceof t);
|
||||
do_check_true(d.constructor === t);
|
||||
}
|
||||
}
|
||||
|
||||
function run_StructType_tests() {
|
||||
|
@ -1692,16 +1694,19 @@ function run_FunctionType_tests() {
|
|||
ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, null);
|
||||
}, Error);
|
||||
do_check_throws(function() {
|
||||
ctypes.FunctionType(ctypes.default_abi, ctypes.void_t());
|
||||
ctypes.FunctionType(ctypes.default_abi, ctypes.int32_t());
|
||||
}, Error);
|
||||
do_check_throws(function() {
|
||||
ctypes.FunctionType(ctypes.void_t, ctypes.void_t);
|
||||
}, Error);
|
||||
|
||||
let g_t = ctypes.StructType("g_t", [{ a: ctypes.int32_t }, { b: ctypes.double }]);
|
||||
let g = g_t(1, 2);
|
||||
|
||||
let f_t = ctypes.FunctionType(ctypes.default_abi, g_t);
|
||||
let name = "g_t(*)()";
|
||||
let name = "g_t()()";
|
||||
do_check_eq(f_t.name, name);
|
||||
do_check_eq(f_t.size, ctypes.uintptr_t.size);
|
||||
do_check_eq(f_t.size, undefined);
|
||||
do_check_true(f_t.abi === ctypes.default_abi);
|
||||
do_check_true(f_t.returnType === g_t);
|
||||
do_check_true(f_t.argTypes.length == 0);
|
||||
|
@ -1710,13 +1715,25 @@ function run_FunctionType_tests() {
|
|||
do_check_eq(f_t.toSource(),
|
||||
"ctypes.FunctionType(ctypes.default_abi, g_t)");
|
||||
|
||||
let fp_t = f_t.ptr;
|
||||
name = "g_t(*)()";
|
||||
do_check_eq(fp_t.name, name);
|
||||
do_check_eq(fp_t.size, ctypes.uintptr_t.size);
|
||||
|
||||
do_check_eq(fp_t.toString(), "type " + name);
|
||||
do_check_eq(fp_t.toSource(),
|
||||
"ctypes.FunctionType(ctypes.default_abi, g_t).ptr");
|
||||
|
||||
// Check that constructing a FunctionType CData directly throws.
|
||||
do_check_throws(function() { f_t(); }, Error);
|
||||
|
||||
// Test ExplicitConvert.
|
||||
let f = f_t();
|
||||
let f = fp_t();
|
||||
do_check_throws(function() { f.value; }, Error);
|
||||
do_check_eq(ptrValue(f), 0);
|
||||
f = f_t(5);
|
||||
f = fp_t(5);
|
||||
do_check_eq(ptrValue(f), 5);
|
||||
f = f_t(ctypes.UInt64(10));
|
||||
f = fp_t(ctypes.UInt64(10));
|
||||
do_check_eq(ptrValue(f), 10);
|
||||
|
||||
// Test ImplicitConvert.
|
||||
|
@ -1724,43 +1741,45 @@ function run_FunctionType_tests() {
|
|||
do_check_eq(ptrValue(f), 0);
|
||||
do_check_throws(function() { f.value = 5; }, Error);
|
||||
do_check_eq(f.toSource(),
|
||||
'ctypes.FunctionType(ctypes.default_abi, g_t)(ctypes.UInt64("0x0"))');
|
||||
'ctypes.FunctionType(ctypes.default_abi, g_t).ptr(ctypes.UInt64("0x0"))');
|
||||
|
||||
// Test ExplicitConvert from a function pointer of different type.
|
||||
let f2_t = ctypes.FunctionType(ctypes.default_abi, g_t, [ ctypes.int32_t ]);
|
||||
let f2 = f2_t();
|
||||
do_check_throws(function() { f_t(f2); }, Error);
|
||||
let f2 = f2_t.ptr();
|
||||
do_check_throws(function() { fp_t(f2); }, Error);
|
||||
do_check_throws(function() { f.value = f2; }, Error);
|
||||
do_check_throws(function() { f2.value = f; }, Error);
|
||||
|
||||
// Test that converting to a voidptr_t throws.
|
||||
do_check_throws(function() { ctypes.voidptr_t(f2); }, Error);
|
||||
// Test that converting to a voidptr_t works, but not the other way.
|
||||
let v = ctypes.voidptr_t(f2);
|
||||
do_check_eq(v.toSource(), 'ctypes.voidptr_t(ctypes.UInt64("0x0"))');
|
||||
do_check_throws(function() { f2_t.ptr(v); }, TypeError);
|
||||
|
||||
// Test some more complex names.
|
||||
do_check_eq(f_t.array().name, "g_t(*[])()");
|
||||
do_check_eq(f_t.array().ptr.name, "g_t(*(*)[])()");
|
||||
do_check_eq(fp_t.array().name, "g_t(*[])()");
|
||||
do_check_eq(fp_t.array().ptr.name, "g_t(*(*)[])()");
|
||||
|
||||
let f3_t = ctypes.FunctionType(ctypes.default_abi,
|
||||
ctypes.char.ptr.array().ptr).ptr.array(8).array();
|
||||
ctypes.char.ptr.array().ptr).ptr.ptr.array(8).array();
|
||||
do_check_eq(f3_t.name, "char*(*(**[][8])())[]");
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef _WIN64
|
||||
f3_t = ctypes.FunctionType(ctypes.stdcall_abi,
|
||||
ctypes.char.ptr.array().ptr).ptr.array(8).array();
|
||||
do_check_eq(f3_t.name, "char*(__stdcall *(**[][8])())[]");
|
||||
do_check_eq(f3_t.ptr.name, "char*(__stdcall *(**[][8])())[]");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
let f4_t = ctypes.FunctionType(ctypes.default_abi,
|
||||
ctypes.char.ptr.array().ptr, [ ctypes.int32_t, f_t ]);
|
||||
ctypes.char.ptr.array().ptr, [ ctypes.int32_t, fp_t ]);
|
||||
do_check_true(f4_t.argTypes.length == 2);
|
||||
do_check_true(f4_t.argTypes[0] === ctypes.int32_t);
|
||||
do_check_true(f4_t.argTypes[1] === f_t);
|
||||
do_check_true(f4_t.argTypes[1] === fp_t);
|
||||
do_check_throws(function() { f4_t.argTypes.z = 0; }, Error);
|
||||
do_check_throws(function() { f4_t.argTypes[0] = 0; }, Error);
|
||||
|
||||
let t4_t = f4_t.ptr.array(8).array();
|
||||
let t4_t = f4_t.ptr.ptr.array(8).array();
|
||||
do_check_eq(t4_t.name, "char*(*(**[][8])(int32_t, g_t(*)()))[]");
|
||||
}
|
||||
|
||||
|
@ -1908,7 +1927,7 @@ function run_cast_tests() {
|
|||
let g_t = ctypes.StructType("g_t", [{ a: ctypes.int32_t }, { b: ctypes.double }]);
|
||||
let a_t = ctypes.ArrayType(g_t, 4);
|
||||
let p_t = ctypes.PointerType(g_t);
|
||||
let f_t = ctypes.FunctionType(ctypes.default_abi, ctypes.void_t);
|
||||
let f_t = ctypes.FunctionType(ctypes.default_abi, ctypes.void_t).ptr;
|
||||
|
||||
let a = a_t();
|
||||
a[0] = { a: 5, b: 7.5 };
|
||||
|
@ -2064,7 +2083,7 @@ function run_function_tests(library)
|
|||
let test_ansi_len = library.declare("test_ansi_len", ctypes.default_abi,
|
||||
ctypes.int32_t, ctypes.char.ptr);
|
||||
let fn_t = ctypes.FunctionType(ctypes.default_abi, ctypes.int32_t,
|
||||
[ ctypes.char.ptr ]);
|
||||
[ ctypes.char.ptr ]).ptr;
|
||||
|
||||
let test_fnptr = library.declare("test_fnptr", ctypes.default_abi, fn_t);
|
||||
|
||||
|
@ -2076,11 +2095,12 @@ function run_function_tests(library)
|
|||
// Test that we can call ptr().
|
||||
do_check_eq(ptr("function pointers rule!"), 23);
|
||||
|
||||
// Test that library.declare() returns data of type FunctionType, and that
|
||||
// Test that library.declare() returns data of type FunctionType.ptr, and that
|
||||
// it is immutable.
|
||||
do_check_true(test_ansi_len.constructor.__proto__ === ctypes.FunctionType.prototype);
|
||||
do_check_true(test_ansi_len.constructor.targetType.__proto__ ===
|
||||
ctypes.FunctionType.prototype);
|
||||
do_check_eq(test_ansi_len.constructor.toSource(),
|
||||
"ctypes.FunctionType(ctypes.default_abi, ctypes.int32_t, [ctypes.char.ptr])");
|
||||
"ctypes.FunctionType(ctypes.default_abi, ctypes.int32_t, [ctypes.char.ptr]).ptr");
|
||||
do_check_throws(function() { test_ansi_len.value = null; }, Error);
|
||||
do_check_eq(ptrValue(test_ansi_len), ptrValue(ptr));
|
||||
|
||||
|
@ -2116,7 +2136,7 @@ function run_single_closure_tests(library, abi, suffix)
|
|||
do_check_eq(closure_fn.call(thisobj, 7), 7 + thisobj.a);
|
||||
|
||||
// Construct a closure, and call it ourselves.
|
||||
let fn_t = ctypes.FunctionType(abi, ctypes.int32_t, [ ctypes.int8_t ]);
|
||||
let fn_t = ctypes.FunctionType(abi, ctypes.int32_t, [ ctypes.int8_t ]).ptr;
|
||||
let closure = fn_t(closure_fn);
|
||||
do_check_eq(closure(-17), -17 + b);
|
||||
|
||||
|
@ -2134,14 +2154,14 @@ function run_single_closure_tests(library, abi, suffix)
|
|||
function run_variadic_tests(library) {
|
||||
let sum_va_type = ctypes.FunctionType(ctypes.default_abi,
|
||||
ctypes.int32_t,
|
||||
[ctypes.uint8_t, "..."]),
|
||||
[ctypes.uint8_t, "..."]).ptr,
|
||||
sum_va = library.declare("test_sum_va_cdecl", ctypes.default_abi, ctypes.int32_t,
|
||||
ctypes.uint8_t, "...");
|
||||
|
||||
do_check_eq(sum_va_type.toSource(),
|
||||
'ctypes.FunctionType(ctypes.default_abi, ctypes.int32_t, [ctypes.uint8_t, "..."])');
|
||||
'ctypes.FunctionType(ctypes.default_abi, ctypes.int32_t, [ctypes.uint8_t, "..."]).ptr');
|
||||
do_check_eq(sum_va.constructor.name, "int32_t(*)(uint8_t, ...)");
|
||||
do_check_true(sum_va.constructor.isVariadic);
|
||||
do_check_true(sum_va.constructor.targetType.isVariadic);
|
||||
|
||||
do_check_eq(sum_va(3,
|
||||
ctypes.int32_t(1),
|
||||
|
@ -2211,9 +2231,9 @@ function run_variadic_tests(library) {
|
|||
do_check_eq(result[2], 16);
|
||||
|
||||
do_check_true(!!(sum_va_type().value = sum_va_type()));
|
||||
let sum_notva_type = ctypes.FunctionType(sum_va_type.abi,
|
||||
sum_va_type.returnType,
|
||||
[ctypes.uint8_t]);
|
||||
let sum_notva_type = ctypes.FunctionType(sum_va_type.targetType.abi,
|
||||
sum_va_type.targetType.returnType,
|
||||
[ctypes.uint8_t]).ptr;
|
||||
do_check_throws(function() {
|
||||
sum_va_type().value = sum_notva_type();
|
||||
}, Error);
|
||||
|
|
Загрузка…
Ссылка в новой задаче