Revise js-facing API for js-ctypes, patch v1. b=513788, r=jorendorff

This commit is contained in:
Dan Witte 2010-03-11 17:17:36 -08:00
parent 80dd558623
commit afa52d32f7
14 changed files with 6427 additions and 992 deletions

4284
js/ctypes/CTypes.cpp Normal file

File diff suppressed because it is too large Load Diff

277
js/ctypes/CTypes.h Normal file
View File

@ -0,0 +1,277 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is js-ctypes.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation <http://www.mozilla.org/>.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dan Witte <dwitte@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef CTYPES_H
#define CTYPES_H
#include "jsapi.h"
#include "nsString.h"
#include "ffi.h"
namespace mozilla {
namespace ctypes {
// for JS error reporting
enum ErrorNum {
#define MSG_DEF(name, number, count, exception, format) \
name = number,
#include "ctypes.msg"
#undef MSG_DEF
CTYPESERR_LIMIT
};
const JSErrorFormatString*
GetErrorMessage(void* userRef, const char* locale, const uintN errorNumber);
bool TypeError(JSContext* cx, const char* expected, jsval actual);
/**
* ABI constants that specify the calling convention to use.
* ctypes.default_abi corresponds to the cdecl convention, and in almost all
* cases is the correct choice. ctypes.stdcall_abi is provided for calling
* functions in the Microsoft Win32 API.
*/
enum ABICode {
ABI_DEFAULT,
ABI_STDCALL,
INVALID_ABI
};
enum TypeCode {
TYPE_void_t,
#define DEFINE_TYPE(name, type, ffiType) TYPE_##name,
#include "typedefs.h"
TYPE_pointer,
TYPE_array,
TYPE_struct
};
ABICode GetABICode(JSContext* cx, JSObject* obj);
struct FieldInfo
{
nsCString mName;
JSObject* mType;
size_t mOffset;
};
bool InitTypeClasses(JSContext* cx, JSObject* parent);
bool ConvertToJS(JSContext* cx, JSObject* typeObj, JSObject* dataObj, void* data, bool wantPrimitive, jsval* result);
bool ImplicitConvert(JSContext* cx, jsval val, JSObject* targetType, void* buffer, bool isArgument, bool* freePointer);
bool ExplicitConvert(JSContext* cx, jsval val, JSObject* targetType, void* buffer);
// Contents of the various slots on each JSClass. The slot indexes are given
// enumerated names for readability.
enum CABISlot {
SLOT_ABICODE = 0, // ABICode of the CABI object
CABI_SLOTS
};
enum CTypeProtoSlot {
SLOT_POINTERPROTO = 0, // ctypes.PointerType.prototype object
SLOT_ARRAYPROTO = 1, // ctypes.ArrayType.prototype object
SLOT_STRUCTPROTO = 2, // ctypes.StructType.prototype object
SLOT_INT64PROTO = 3, // ctypes.Int64.prototype object
SLOT_UINT64PROTO = 4, // ctypes.UInt64.prototype object
CTYPEPROTO_SLOTS
};
enum CTypeSlot {
SLOT_TYPECODE = 0, // TypeCode of the CType object
SLOT_FFITYPE = 1, // ffi_type representing the type
SLOT_ALIGN = 2, // alignment of the data type, in bytes
SLOT_PTR = 3, // cached PointerType object for type.ptr
SLOT_FIELDINFO = 4, // (StructTypes only) FieldInfo array
CTYPE_SLOTS
};
enum CDataSlot {
SLOT_CTYPE = 0, // CType object representing the underlying type
SLOT_REFERENT = 1, // CData object this object refers to, if any
SLOT_DATA = 2, // pointer to a buffer containing the binary data
CDATA_SLOTS
};
enum Int64Slot {
SLOT_INT64 = 0, // pointer to a 64-bit buffer containing the integer
INT64_SLOTS
};
enum Int64FunctionSlot {
SLOT_FN_INT64PROTO = 0 // ctypes.{Int64,UInt64}.prototype object
// JSFunction objects always get exactly two slots.
};
class CType {
public:
static JSObject* Create(JSContext* cx, JSObject* proto, JSString* name, TypeCode type, jsval size, jsval align, ffi_type* ffiType);
static JSObject* DefineBuiltin(JSContext* cx, JSObject* parent, const char* propName, JSObject* proto, const char* name, TypeCode type, jsval size, jsval align, ffi_type* ffiType);
static void Finalize(JSContext* cx, JSObject* obj);
static JSBool ConstructAbstract(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
static JSBool ConstructData(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
static JSBool ConstructBasic(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
static bool IsCType(JSContext* cx, JSObject* obj);
static TypeCode GetTypeCode(JSContext* cx, JSObject* typeObj);
static bool TypesEqual(JSContext* cx, JSObject* t1, JSObject* t2);
static size_t GetSize(JSContext* cx, JSObject* obj);
static bool GetSafeSize(JSContext* cx, JSObject* obj, size_t* result);
static bool IsSizeDefined(JSContext* cx, JSObject* obj);
static size_t GetAlignment(JSContext* cx, JSObject* obj);
static ffi_type* GetFFIType(JSContext* cx, JSObject* obj);
static JSString* GetName(JSContext* cx, JSObject* obj);
static JSObject* GetProtoFromCtor(JSContext* cx, JSObject* obj, CTypeProtoSlot slot);
static JSObject* GetProtoFromType(JSContext* cx, JSObject* obj, CTypeProtoSlot slot);
static JSBool PtrGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp);
static JSBool Array(JSContext* cx, uintN argc, jsval* vp);
static JSBool ToString(JSContext* cx, uintN argc, jsval* vp);
static JSBool ToSource(JSContext* cx, uintN argc, jsval* vp);
};
class PointerType {
public:
static JSBool Create(JSContext* cx, uintN argc, jsval* vp);
static JSObject* CreateInternal(JSContext* cx, JSObject* ctor, JSObject* baseType, JSString* name);
static JSBool ConstructData(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
static JSObject* ConstructInternal(JSContext* cx, JSObject* typeObj, JSObject* parentObj, void* data);
static JSObject* GetBaseType(JSContext* cx, JSObject* obj);
static JSBool ContentsGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp);
static JSBool ContentsSetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp);
};
class ArrayType {
public:
static JSBool Create(JSContext* cx, uintN argc, jsval* vp);
static JSObject* CreateInternal(JSContext* cx, JSObject* baseType, size_t length, bool lengthDefined);
static JSBool ConstructData(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
static JSObject* ConstructInternal(JSContext* cx, JSObject* typeObj, JSObject* parentObj, void* data);
static JSObject* GetBaseType(JSContext* cx, JSObject* obj);
static size_t GetLength(JSContext* cx, JSObject* obj);
static bool GetSafeLength(JSContext* cx, JSObject* obj, size_t* result);
static JSBool Getter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp);
static JSBool Setter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp);
static JSBool AddressOfElement(JSContext* cx, uintN argc, jsval* vp);
};
class StructType {
public:
static JSBool Create(JSContext* cx, uintN argc, jsval* vp);
static JSBool ConstructData(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
static JSObject* ConstructInternal(JSContext* cx, JSObject* typeObj, JSObject* parentObj, void* data);
static nsTArray<FieldInfo>* GetFieldInfo(JSContext* cx, JSObject* obj);
static FieldInfo* LookupField(JSContext* cx, JSObject* obj, jsval idval);
static JSBool FieldGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp);
static JSBool FieldSetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp);
static JSBool AddressOfField(JSContext* cx, uintN argc, jsval* vp);
};
class CData {
public:
static JSObject* Create(JSContext* cx, JSObject* type, JSObject* base, void* data);
static void Finalize(JSContext* cx, JSObject* obj);
static JSObject* GetCType(JSContext* cx, JSObject* dataObj);
static void* GetData(JSContext* cx, JSObject* dataObj);
static bool IsCData(JSContext* cx, JSObject* obj);
static JSBool ValueGetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp);
static JSBool ValueSetter(JSContext* cx, JSObject* obj, jsval idval, jsval* vp);
static JSBool Address(JSContext* cx, uintN argc, jsval* vp);
static JSBool Cast(JSContext* cx, uintN argc, jsval* vp);
static JSBool ReadString(JSContext* cx, uintN argc, jsval* vp);
static JSBool ToSource(JSContext* cx, uintN argc, jsval* vp);
};
class Int64Base {
public:
static JSObject* Construct(JSContext* cx, JSObject* proto, PRUint64 data, bool isUnsigned);
static void Finalize(JSContext* cx, JSObject* obj);
static PRUint64 GetInt(JSContext* cx, JSObject* obj);
static JSBool ToString(JSContext* cx, JSObject* obj, uintN argc, jsval* vp, bool isUnsigned);
static JSBool ToSource(JSContext* cx, JSObject* obj, uintN argc, jsval* vp, bool isUnsigned);
};
class Int64 : public Int64Base {
public:
static JSBool Construct(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
static bool IsInt64(JSContext* cx, JSObject* obj);
static JSBool ToString(JSContext* cx, uintN argc, jsval* vp);
static JSBool ToSource(JSContext* cx, uintN argc, jsval* vp);
// ctypes.Int64 static functions
static JSBool Compare(JSContext* cx, uintN argc, jsval* vp);
static JSBool Lo(JSContext* cx, uintN argc, jsval* vp);
static JSBool Hi(JSContext* cx, uintN argc, jsval* vp);
static JSBool Join(JSContext* cx, uintN argc, jsval* vp);
};
class UInt64 : public Int64Base {
public:
static JSBool Construct(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
static bool IsUInt64(JSContext* cx, JSObject* obj);
static JSBool ToString(JSContext* cx, uintN argc, jsval* vp);
static JSBool ToSource(JSContext* cx, uintN argc, jsval* vp);
// ctypes.UInt64 static functions
static JSBool Compare(JSContext* cx, uintN argc, jsval* vp);
static JSBool Lo(JSContext* cx, uintN argc, jsval* vp);
static JSBool Hi(JSContext* cx, uintN argc, jsval* vp);
static JSBool Join(JSContext* cx, uintN argc, jsval* vp);
};
}
}
#endif

View File

@ -50,439 +50,101 @@ namespace ctypes {
** Static helpers ** Static helpers
*******************************************************************************/ *******************************************************************************/
template<class IntegerType>
static IntegerType
Convert(jsdouble d)
{
return IntegerType(d);
}
#ifdef _MSC_VER
// MSVC can't perform double to unsigned __int64 conversion when the
// double is greater than 2^63 - 1. Help it along a little.
template<>
static PRUint64
Convert<PRUint64>(jsdouble d)
{
return d > 0x7fffffffffffffffui64 ?
PRUint64(d - 0x8000000000000000ui64) + 0x8000000000000000ui64 :
PRUint64(d);
}
#endif
template<class IntegerType>
static bool
jsvalToIntStrict(jsval aValue, IntegerType *aResult)
{
if (JSVAL_IS_INT(aValue)) {
jsint i = JSVAL_TO_INT(aValue);
*aResult = IntegerType(i);
// Make sure the integer fits in the alotted precision, and has the right sign.
return jsint(*aResult) == i &&
(i < 0) == (*aResult < 0);
}
if (JSVAL_IS_DOUBLE(aValue)) {
jsdouble d = *JSVAL_TO_DOUBLE(aValue);
*aResult = Convert<IntegerType>(d);
// Don't silently lose bits here -- check that aValue really is an
// integer value, and has the right sign.
return jsdouble(*aResult) == d &&
(d < 0) == (*aResult < 0);
}
if (JSVAL_IS_BOOLEAN(aValue)) {
// Implicitly promote boolean values to 0 or 1, like C.
*aResult = JSVAL_TO_BOOLEAN(aValue);
NS_ASSERTION(*aResult == 0 || *aResult == 1, "invalid boolean");
return true;
}
// Don't silently convert null to an integer. It's probably a mistake.
return false;
}
static bool
jsvalToDoubleStrict(jsval aValue, jsdouble *dp)
{
// Don't silently convert true to 1.0 or false to 0.0, even though C/C++
// does it. It's likely to be a mistake.
if (JSVAL_IS_INT(aValue)) {
*dp = JSVAL_TO_INT(aValue);
return true;
}
if (JSVAL_IS_DOUBLE(aValue)) {
*dp = *JSVAL_TO_DOUBLE(aValue);
return true;
}
return false;
}
JSErrorFormatString ErrorFormatString[CTYPESERR_LIMIT] = {
#define MSG_DEF(name, number, count, exception, format) \
{ format, count, exception } ,
#include "ctypes.msg"
#undef MSG_DEF
};
const JSErrorFormatString*
GetErrorMessage(void* userRef, const char* locale, const uintN errorNumber)
{
if (0 < errorNumber && errorNumber < CTYPESERR_LIMIT)
return &ErrorFormatString[errorNumber];
return NULL;
}
static const char*
ToSource(JSContext* cx, jsval vp)
{
JSString* str = JS_ValueToSource(cx, vp);
if (str)
return JS_GetStringBytes(str);
JS_ClearPendingException(cx);
return "<<error converting value to string>>";
}
static bool
TypeError(JSContext* cx, const char* expected, jsval actual)
{
const char* src = ToSource(cx, actual);
JS_ReportErrorNumber(cx, GetErrorMessage, NULL,
CTYPESMSG_TYPE_ERROR, expected, src);
return false;
}
static bool static bool
GetABI(JSContext* cx, jsval aCallType, ffi_abi& aResult) GetABI(JSContext* cx, jsval aCallType, ffi_abi& aResult)
{ {
ABICode abi = Module::GetABICode(cx, aCallType); if (!JSVAL_IS_OBJECT(aCallType) || JSVAL_IS_NULL(aCallType))
return false;
ABICode abi = GetABICode(cx, JSVAL_TO_OBJECT(aCallType));
// determine the ABI from the subset of those available on the // determine the ABI from the subset of those available on the
// given platform. TYPE_DEFAULT specifies the default // given platform. ABI_DEFAULT specifies the default
// C calling convention (cdecl) on each platform. // C calling convention (cdecl) on each platform.
switch (abi) { switch (abi) {
case ABI_default_abi: case ABI_DEFAULT:
aResult = FFI_DEFAULT_ABI; aResult = FFI_DEFAULT_ABI;
return true; return true;
case ABI_STDCALL:
#if (defined(_WIN32) && !defined(_WIN64)) || defined(_OS2) #if (defined(_WIN32) && !defined(_WIN64)) || defined(_OS2)
case ABI_stdcall_abi:
aResult = FFI_STDCALL; aResult = FFI_STDCALL;
return true; return true;
#endif #endif
default: case INVALID_ABI:
return false; break;
} }
return false;
} }
static bool static bool
PrepareType(JSContext* aContext, jsval aType, Type& aResult) PrepareType(JSContext* aContext, jsval aType, Type& aResult)
{ {
aResult.mType = Module::GetTypeCode(aContext, aType); if (!JSVAL_IS_OBJECT(aType) ||
JSVAL_IS_NULL(aType) ||
switch (aResult.mType) { !CType::IsCType(aContext, JSVAL_TO_OBJECT(aType))) {
case TYPE_void_t: JS_ReportError(aContext, "not a ctypes type");
aResult.mFFIType = ffi_type_void;
break;
case TYPE_int8_t:
aResult.mFFIType = ffi_type_sint8;
break;
case TYPE_int16_t:
aResult.mFFIType = ffi_type_sint16;
break;
case TYPE_int32_t:
aResult.mFFIType = ffi_type_sint32;
break;
case TYPE_int64_t:
aResult.mFFIType = ffi_type_sint64;
break;
case TYPE_bool:
case TYPE_uint8_t:
aResult.mFFIType = ffi_type_uint8;
break;
case TYPE_uint16_t:
aResult.mFFIType = ffi_type_uint16;
break;
case TYPE_uint32_t:
aResult.mFFIType = ffi_type_uint32;
break;
case TYPE_uint64_t:
aResult.mFFIType = ffi_type_uint64;
break;
case TYPE_float:
aResult.mFFIType = ffi_type_float;
break;
case TYPE_double:
aResult.mFFIType = ffi_type_double;
break;
case TYPE_string:
case TYPE_ustring:
aResult.mFFIType = ffi_type_pointer;
break;
default:
JS_ReportError(aContext, "Invalid type specification");
return false; return false;
} }
JSObject* typeObj = JSVAL_TO_OBJECT(aType);
TypeCode typeCode = CType::GetTypeCode(aContext, typeObj);
if (typeCode == TYPE_array) {
// convert array argument types to pointers, just like C.
// ImplicitConvert will do the same, when passing an array as data.
JSObject* baseType = ArrayType::GetBaseType(aContext, typeObj);
typeObj = PointerType::CreateInternal(aContext, NULL, baseType, NULL);
if (!typeObj) {
JS_ReportError(aContext, "couldn't create pointer type from array");
return false;
}
} else if (typeCode == TYPE_void_t) {
// disallow void argument types
JS_ReportError(aContext, "Cannot have void argument type");
return false;
}
// libffi cannot pass types of zero size by value.
JS_ASSERT(CType::GetSize(aContext, typeObj) != 0);
aResult.mType = typeObj;
aResult.mFFIType = *CType::GetFFIType(aContext, typeObj);
return true; return true;
} }
static bool static bool
PrepareValue(JSContext* aContext, const Type& aType, jsval aValue, Value& aResult) PrepareResultType(JSContext* aContext, jsval aType, Type& aResult)
{ {
jsdouble d; if (!JSVAL_IS_OBJECT(aType) ||
JSVAL_IS_NULL(aType) ||
switch (aType.mType) { !CType::IsCType(aContext, JSVAL_TO_OBJECT(aType))) {
case TYPE_bool: JS_ReportError(aContext, "not a ctypes type");
// Do not implicitly lose bits, but allow the values 0, 1, and -0.
// Programs can convert explicitly, if needed, using `Boolean(v)` or `!!v`.
if (!jsvalToIntStrict(aValue, &aResult.mValue.mUint8) ||
aResult.mValue.mUint8 > 1)
return TypeError(aContext, "boolean", aValue);
aResult.mData = &aResult.mValue.mUint8;
break;
case TYPE_int8_t:
// Do not implicitly lose bits.
if (!jsvalToIntStrict(aValue, &aResult.mValue.mInt8))
return TypeError(aContext, "int8", aValue);
aResult.mData = &aResult.mValue.mInt8;
break;
case TYPE_int16_t:
// Do not implicitly lose bits.
if (!jsvalToIntStrict(aValue, &aResult.mValue.mInt16))
return TypeError(aContext, "int16", aValue);
aResult.mData = &aResult.mValue.mInt16;
break;
case TYPE_int32_t:
// Do not implicitly lose bits.
if (!jsvalToIntStrict(aValue, &aResult.mValue.mInt32))
return TypeError(aContext, "int32", aValue);
aResult.mData = &aResult.mValue.mInt32;
break;
case TYPE_int64_t:
// Do not implicitly lose bits.
if (!jsvalToIntStrict(aValue, &aResult.mValue.mInt64))
return TypeError(aContext, "int64", aValue);
aResult.mData = &aResult.mValue.mInt64;
break;
case TYPE_uint8_t:
// Do not implicitly lose bits.
if (!jsvalToIntStrict(aValue, &aResult.mValue.mUint8))
return TypeError(aContext, "uint8", aValue);
aResult.mData = &aResult.mValue.mUint8;
break;
case TYPE_uint16_t:
// Do not implicitly lose bits.
if (!jsvalToIntStrict(aValue, &aResult.mValue.mUint16))
return TypeError(aContext, "uint16", aValue);
aResult.mData = &aResult.mValue.mUint16;
break;
case TYPE_uint32_t:
// Do not implicitly lose bits.
if (!jsvalToIntStrict(aValue, &aResult.mValue.mUint32))
return TypeError(aContext, "uint32", aValue);
aResult.mData = &aResult.mValue.mUint32;
break;
case TYPE_uint64_t:
// Do not implicitly lose bits.
if (!jsvalToIntStrict(aValue, &aResult.mValue.mUint64))
return TypeError(aContext, "uint64", aValue);
aResult.mData = &aResult.mValue.mUint64;
break;
case TYPE_float:
if (!jsvalToDoubleStrict(aValue, &d))
return TypeError(aContext, "float", aValue);
// The following cast silently throws away some bits, but there's
// no good way around it. Sternly requiring that the 64-bit double
// argument be exactly representable as a 32-bit float is
// unrealistic: it would allow 1/2 to pass but not 1/3.
aResult.mValue.mFloat = float(d);
aResult.mData = &aResult.mValue.mFloat;
break;
case TYPE_double:
if (!jsvalToDoubleStrict(aValue, &d))
return TypeError(aContext, "double", aValue);
aResult.mValue.mDouble = d;
aResult.mData = &aResult.mValue.mDouble;
break;
case TYPE_string:
if (JSVAL_IS_NULL(aValue)) {
// Allow passing a null pointer.
aResult.mValue.mPointer = nsnull;
} else if (JSVAL_IS_STRING(aValue)) {
aResult.mValue.mPointer = JS_GetStringBytes(JSVAL_TO_STRING(aValue));
} else {
// Don't implicitly convert to string. Users can implicitly convert
// with `String(x)` or `""+x`.
return TypeError(aContext, "string", aValue);
}
aResult.mData = &aResult.mValue.mPointer;
break;
case TYPE_ustring:
if (JSVAL_IS_NULL(aValue)) {
// Allow passing a null pointer.
aResult.mValue.mPointer = nsnull;
} else if (JSVAL_IS_STRING(aValue)) {
aResult.mValue.mPointer = JS_GetStringChars(JSVAL_TO_STRING(aValue));
} else {
// Don't implicitly convert to string. Users can implicitly convert
// with `String(x)` or `""+x`.
return TypeError(aContext, "ustring", aValue);
}
aResult.mData = &aResult.mValue.mPointer;
break;
default:
NS_NOTREACHED("invalid type");
return false; return false;
} }
return true; JSObject* typeObj = JSVAL_TO_OBJECT(aType);
} TypeCode typeCode = CType::GetTypeCode(aContext, typeObj);
static void // Arrays can never be return types.
PrepareReturnValue(const Type& aType, Value& aResult) if (typeCode == TYPE_array) {
{ JS_ReportError(aContext, "Result type cannot be an array");
switch (aType.mType) {
case TYPE_void_t:
aResult.mData = nsnull;
break;
case TYPE_int8_t:
aResult.mData = &aResult.mValue.mInt8;
break;
case TYPE_int16_t:
aResult.mData = &aResult.mValue.mInt16;
break;
case TYPE_int32_t:
aResult.mData = &aResult.mValue.mInt32;
break;
case TYPE_int64_t:
aResult.mData = &aResult.mValue.mInt64;
break;
case TYPE_bool:
case TYPE_uint8_t:
aResult.mData = &aResult.mValue.mUint8;
break;
case TYPE_uint16_t:
aResult.mData = &aResult.mValue.mUint16;
break;
case TYPE_uint32_t:
aResult.mData = &aResult.mValue.mUint32;
break;
case TYPE_uint64_t:
aResult.mData = &aResult.mValue.mUint64;
break;
case TYPE_float:
aResult.mData = &aResult.mValue.mFloat;
break;
case TYPE_double:
aResult.mData = &aResult.mValue.mDouble;
break;
case TYPE_string:
case TYPE_ustring:
aResult.mData = &aResult.mValue.mPointer;
break;
default:
NS_NOTREACHED("invalid type");
break;
}
}
static bool
ConvertReturnValue(JSContext* aContext,
const Type& aResultType,
const Value& aResultValue,
jsval* aValue)
{
switch (aResultType.mType) {
case TYPE_void_t:
*aValue = JSVAL_VOID;
break;
case TYPE_bool:
*aValue = aResultValue.mValue.mUint8 ? JSVAL_TRUE : JSVAL_FALSE;
break;
case TYPE_int8_t:
*aValue = INT_TO_JSVAL(aResultValue.mValue.mInt8);
break;
case TYPE_int16_t:
*aValue = INT_TO_JSVAL(aResultValue.mValue.mInt16);
break;
case TYPE_int32_t:
if (!JS_NewNumberValue(aContext, jsdouble(aResultValue.mValue.mInt32), aValue))
return false;
break;
case TYPE_int64_t:
// Implicit conversion with loss of bits. :-[
if (!JS_NewNumberValue(aContext, jsdouble(aResultValue.mValue.mInt64), aValue))
return false;
break;
case TYPE_uint8_t:
*aValue = INT_TO_JSVAL(aResultValue.mValue.mUint8);
break;
case TYPE_uint16_t:
*aValue = INT_TO_JSVAL(aResultValue.mValue.mUint16);
break;
case TYPE_uint32_t:
if (!JS_NewNumberValue(aContext, jsdouble(aResultValue.mValue.mUint32), aValue))
return false;
break;
case TYPE_uint64_t:
// Implicit conversion with loss of bits. :-[
if (!JS_NewNumberValue(aContext, jsdouble(aResultValue.mValue.mUint64), aValue))
return false;
break;
case TYPE_float:
if (!JS_NewNumberValue(aContext, jsdouble(aResultValue.mValue.mFloat), aValue))
return false;
break;
case TYPE_double:
if (!JS_NewNumberValue(aContext, jsdouble(aResultValue.mValue.mDouble), aValue))
return false;
break;
case TYPE_string: {
if (!aResultValue.mValue.mPointer) {
// Allow returning a null pointer.
*aValue = JSVAL_NULL;
} else {
JSString *jsstring = JS_NewStringCopyZ(aContext,
reinterpret_cast<const char*>(aResultValue.mValue.mPointer));
if (!jsstring)
return false;
*aValue = STRING_TO_JSVAL(jsstring);
}
break;
}
case TYPE_ustring: {
if (!aResultValue.mValue.mPointer) {
// Allow returning a null pointer.
*aValue = JSVAL_NULL;
} else {
JSString *jsstring = JS_NewUCStringCopyZ(aContext,
reinterpret_cast<const jschar*>(aResultValue.mValue.mPointer));
if (!jsstring)
return false;
*aValue = STRING_TO_JSVAL(jsstring);
}
break;
}
default:
NS_NOTREACHED("invalid type");
return false; return false;
} }
#ifdef _MSC_VER
// Our libffi_msvc fork doesn't support returning structs by value yet.
if (typeCode == TYPE_struct) {
JS_ReportError(aContext,
"Returning structs by value is unsupported on Windows");
return false;
}
#endif
// libffi cannot pass types of zero size by value.
JS_ASSERT(typeCode == TYPE_void_t || CType::GetSize(aContext, typeObj) != 0);
aResult.mType = typeObj;
aResult.mFFIType = *CType::GetFFIType(aContext, typeObj);
return true; return true;
} }
@ -516,7 +178,7 @@ Function::Init(JSContext* aContext,
} }
// prepare the result type // prepare the result type
if (!PrepareType(aContext, aResultType, mResultType)) if (!PrepareResultType(aContext, aResultType, mResultType))
return false; return false;
// prepare the argument types // prepare the argument types
@ -525,12 +187,6 @@ Function::Init(JSContext* aContext,
if (!PrepareType(aContext, aArgTypes[i], *mArgTypes.AppendElement())) if (!PrepareType(aContext, aArgTypes[i], *mArgTypes.AppendElement()))
return false; return false;
// disallow void argument types
if (mArgTypes[i].mType == TYPE_void_t) {
JS_ReportError(aContext, "Cannot have void argument type");
return false;
}
// ffi_prep_cif requires an array of ffi_types; prepare it separately. // ffi_prep_cif requires an array of ffi_types; prepare it separately.
mFFITypes.AppendElement(&mArgTypes[i].mFFIType); mFFITypes.AppendElement(&mArgTypes[i].mFFIType);
} }
@ -561,39 +217,63 @@ Function::Execute(JSContext* cx, PRUint32 argc, jsval* vp)
} }
// prepare the values for each argument // prepare the values for each argument
nsAutoTArray<Value, 16> values; nsAutoTArray<AutoValue, 16> values;
nsAutoTArray<AutoValue, 16> strings;
for (PRUint32 i = 0; i < mArgTypes.Length(); ++i) { for (PRUint32 i = 0; i < mArgTypes.Length(); ++i) {
if (!PrepareValue(cx, mArgTypes[i], JS_ARGV(cx, vp)[i], *values.AppendElement())) AutoValue& value = *values.AppendElement();
jsval arg = JS_ARGV(cx, vp)[i];
bool freePointer = false;
if (!value.SizeToType(cx, mArgTypes[i].mType)) {
JS_ReportAllocationOverflow(cx);
return false; return false;
} }
// create an array of pointers to each value, for passing to ffi_call if (!ImplicitConvert(cx, arg, mArgTypes[i].mType, value.mData, true, &freePointer))
nsAutoTArray<void*, 16> ffiValues; return false;
for (PRUint32 i = 0; i < mArgTypes.Length(); ++i) {
ffiValues.AppendElement(values[i].mData); if (freePointer) {
// ImplicitConvert converted a string for us, which we have to free.
// Keep track of it.
strings.AppendElement()->mData = *static_cast<char**>(value.mData);
}
} }
// initialize a pointer to an appropriate location, for storing the result // initialize a pointer to an appropriate location, for storing the result
Value resultValue; AutoValue resultValue;
PrepareReturnValue(mResultType, resultValue); if (CType::GetTypeCode(cx, mResultType.mType) != TYPE_void_t &&
!resultValue.SizeToType(cx, mResultType.mType)) {
JS_ReportAllocationOverflow(cx);
return false;
}
// suspend the request before we call into the function, since the call // suspend the request before we call into the function, since the call
// may block or otherwise take a long time to return. // may block or otherwise take a long time to return.
jsrefcount rc = JS_SuspendRequest(cx); jsrefcount rc = JS_SuspendRequest(cx);
ffi_call(&mCIF, FFI_FN(mFunc), resultValue.mData, ffiValues.Elements()); ffi_call(&mCIF, FFI_FN(mFunc), resultValue.mData, reinterpret_cast<void**>(values.Elements()));
JS_ResumeRequest(cx, rc); JS_ResumeRequest(cx, rc);
// prepare a JS object from the result // prepare a JS object from the result
jsval rval; jsval rval;
if (!ConvertReturnValue(cx, mResultType, resultValue, &rval)) if (!ConvertToJS(cx, mResultType.mType, NULL, resultValue.mData, false, &rval))
return false; return false;
JS_SET_RVAL(cx, vp, rval); JS_SET_RVAL(cx, vp, rval);
return true; return true;
} }
void
Function::Trace(JSTracer *trc)
{
// Identify the result CType to the tracer.
JS_CALL_TRACER(trc, mResultType.mType, JSTRACE_OBJECT, "CType");
// Identify each argument CType to the tracer.
for (PRUint32 i = 0; i < mArgTypes.Length(); ++i)
JS_CALL_TRACER(trc, mArgTypes[i].mType, JSTRACE_OBJECT, "CType");
}
/******************************************************************************* /*******************************************************************************
** JSObject implementation ** JSObject implementation
*******************************************************************************/ *******************************************************************************/
@ -627,15 +307,16 @@ Function::Create(JSContext* aContext,
JSAutoTempValueRooter fnRoot(aContext, fnObj); JSAutoTempValueRooter fnRoot(aContext, fnObj);
// stash a pointer to self, which Function::Call will need at call time // stash a pointer to self, which Function::Call will need at call time
if (!JS_SetReservedSlot(aContext, fnObj, 0, PRIVATE_TO_JSVAL(self.get()))) if (!JS_SetReservedSlot(aContext, fnObj, SLOT_FUNCTION, PRIVATE_TO_JSVAL(self.get())))
return NULL; return NULL;
// make a strong reference to the library for GC-safety // make a strong reference to the library for GC-safety
if (!JS_SetReservedSlot(aContext, fnObj, 1, OBJECT_TO_JSVAL(aLibrary))) if (!JS_SetReservedSlot(aContext, fnObj, SLOT_LIBRARYOBJ, OBJECT_TO_JSVAL(aLibrary)))
return NULL; return NULL;
// tell the library we exist, so it can delete our Function instance // Tell the library we exist, so it can (a) identify our CTypes to the tracer
// when it comes time to finalize. (JS functions don't have finalizers.) // and (b) delete our Function instance when it comes time to finalize.
// (JS functions don't have finalizers.)
if (!Library::AddFunction(aContext, aLibrary, self)) if (!Library::AddFunction(aContext, aLibrary, self))
return NULL; return NULL;
@ -647,7 +328,7 @@ static Function*
GetFunction(JSContext* cx, JSObject* obj) GetFunction(JSContext* cx, JSObject* obj)
{ {
jsval slot; jsval slot;
JS_GetReservedSlot(cx, obj, 0, &slot); JS_GetReservedSlot(cx, obj, SLOT_FUNCTION, &slot);
return static_cast<Function*>(JSVAL_TO_PRIVATE(slot)); return static_cast<Function*>(JSVAL_TO_PRIVATE(slot));
} }
@ -657,7 +338,7 @@ Function::Call(JSContext* cx, uintN argc, jsval* vp)
JSObject* callee = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)); JSObject* callee = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
jsval slot; jsval slot;
JS_GetReservedSlot(cx, callee, 1, &slot); JS_GetReservedSlot(cx, callee, SLOT_LIBRARYOBJ, &slot);
PRLibrary* library = Library::GetLibrary(cx, JSVAL_TO_OBJECT(slot)); PRLibrary* library = Library::GetLibrary(cx, JSVAL_TO_OBJECT(slot));
if (!library) { if (!library) {

View File

@ -40,48 +40,45 @@
#ifndef FUNCTION_H #ifndef FUNCTION_H
#define FUNCTION_H #define FUNCTION_H
#include "Module.h" #include "CTypes.h"
#include "nsTArray.h" #include "nsTArray.h"
#include "prlink.h" #include "prlink.h"
#include "ffi.h"
namespace mozilla { namespace mozilla {
namespace ctypes { namespace ctypes {
// for JS error reporting enum FunctionSlot
enum ErrorNum { {
#define MSG_DEF(name, number, count, exception, format) \ SLOT_FUNCTION = 0,
name = number, SLOT_LIBRARYOBJ = 1
#include "ctypes.msg" // JSFunction objects always get exactly two slots.
#undef MSG_DEF
CTYPESERR_LIMIT
}; };
const JSErrorFormatString*
GetErrorMessage(void* userRef, const char* locale, const uintN errorNumber);
struct Type struct Type
{ {
ffi_type mFFIType; ffi_type mFFIType;
TypeCode mType; JSObject* mType;
}; };
struct Value struct AutoValue
{ {
AutoValue() : mData(NULL) { }
~AutoValue()
{
delete static_cast<char*>(mData);
}
bool SizeToType(JSContext* cx, JSObject* type)
{
size_t size = CType::GetSize(cx, type);
mData = new char[size];
if (mData)
memset(mData, 0, size);
return mData != NULL;
}
void* mData; void* mData;
union {
PRInt8 mInt8;
PRInt16 mInt16;
PRInt32 mInt32;
PRInt64 mInt64;
PRUint8 mUint8;
PRUint16 mUint16;
PRUint32 mUint32;
PRUint64 mUint64;
float mFloat;
double mDouble;
void* mPointer;
} mValue;
}; };
class Function class Function
@ -90,6 +87,7 @@ public:
Function(); Function();
Function*& Next() { return mNext; } Function*& Next() { return mNext; }
void Trace(JSTracer *trc);
static JSObject* Create(JSContext* aContext, JSObject* aLibrary, PRFuncPtr aFunc, const char* aName, jsval aCallType, jsval aResultType, jsval* aArgTypes, uintN aArgLength); static JSObject* Create(JSContext* aContext, JSObject* aLibrary, PRFuncPtr aFunc, const char* aName, jsval aCallType, jsval aResultType, jsval* aArgTypes, uintN aArgLength);
static JSBool Call(JSContext* cx, uintN argc, jsval* vp); static JSBool Call(JSContext* cx, uintN argc, jsval* vp);

View File

@ -38,6 +38,7 @@
* *
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
#include "jscntxt.h"
#include "Library.h" #include "Library.h"
#include "Function.h" #include "Function.h"
#include "nsServiceManagerUtils.h" #include "nsServiceManagerUtils.h"
@ -55,15 +56,18 @@ namespace ctypes {
static JSClass sLibraryClass = { static JSClass sLibraryClass = {
"Library", "Library",
JSCLASS_HAS_RESERVED_SLOTS(2), JSCLASS_HAS_RESERVED_SLOTS(LIBRARY_SLOTS) | JSCLASS_MARK_IS_TRACE,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub,JS_ResolveStub, JS_ConvertStub, Library::Finalize, JS_EnumerateStub,JS_ResolveStub, JS_ConvertStub, Library::Finalize,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL NULL, NULL, NULL, NULL, NULL, NULL, JS_CLASS_TRACE(Library::Trace), NULL
}; };
#define CTYPESFN_FLAGS \
(JSFUN_FAST_NATIVE | JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT)
static JSFunctionSpec sLibraryFunctions[] = { static JSFunctionSpec sLibraryFunctions[] = {
JS_FN("close", Library::Close, 0, JSFUN_FAST_NATIVE | JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT), JS_FN("close", Library::Close, 0, CTYPESFN_FLAGS),
JS_FN("declare", Library::Declare, 0, JSFUN_FAST_NATIVE | JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT), JS_FN("declare", Library::Declare, 0, CTYPESFN_FLAGS),
JS_FS_END JS_FS_END
}; };
@ -73,13 +77,15 @@ Library::Create(JSContext* cx, jsval aPath)
JSObject* libraryObj = JS_NewObject(cx, &sLibraryClass, NULL, NULL); JSObject* libraryObj = JS_NewObject(cx, &sLibraryClass, NULL, NULL);
if (!libraryObj) if (!libraryObj)
return NULL; return NULL;
JSAutoTempValueRooter root(cx, libraryObj);
// initialize the library // initialize the library
if (!JS_SetReservedSlot(cx, libraryObj, 0, PRIVATE_TO_JSVAL(NULL))) if (!JS_SetReservedSlot(cx, libraryObj, SLOT_LIBRARY, PRIVATE_TO_JSVAL(NULL)))
return NULL; return NULL;
// initialize our Function list to empty // initialize our Function list to empty
if (!JS_SetReservedSlot(cx, libraryObj, 1, PRIVATE_TO_JSVAL(NULL))) if (!JS_SetReservedSlot(cx, libraryObj, SLOT_FUNCTIONLIST,
PRIVATE_TO_JSVAL(NULL)))
return NULL; return NULL;
// attach API functions // attach API functions
@ -92,21 +98,22 @@ Library::Create(JSContext* cx, jsval aPath)
// get the path argument. we accept either an nsILocalFile or a string path. // get the path argument. we accept either an nsILocalFile or a string path.
// determine which we have... // determine which we have...
if (JSVAL_IS_STRING(aPath)) { if (JSVAL_IS_STRING(aPath)) {
const jschar* path = JS_GetStringChars(JSVAL_TO_STRING(aPath)); const PRUnichar* path = reinterpret_cast<const PRUnichar*>(
JS_GetStringCharsZ(cx, JSVAL_TO_STRING(aPath)));
if (!path) if (!path)
return NULL; return NULL;
// We don't use nsILocalFile. // We don't use nsILocalFile, because it doesn't use the system search
// Because this interface doesn't resolve library path to use system search rule. // rules when resolving library path.
PRLibSpec libSpec; PRLibSpec libSpec;
#ifdef XP_WIN #ifdef XP_WIN
// On Windows, converting to native charset may corrupt path string. // On Windows, converting to native charset may corrupt path string.
// So, we have to use Unicode path directly. // So, we have to use Unicode path directly.
libSpec.value.pathname_u = reinterpret_cast<const PRUnichar*>(path); libSpec.value.pathname_u = path;
libSpec.type = PR_LibSpec_PathnameU; libSpec.type = PR_LibSpec_PathnameU;
#else #else
nsCAutoString nativePath; nsCAutoString nativePath;
NS_CopyUnicodeToNative(nsDependentString(reinterpret_cast<const PRUnichar*>(path)), nativePath); NS_CopyUnicodeToNative(nsDependentString(path), nativePath);
libSpec.value.pathname = nativePath.get(); libSpec.value.pathname = nativePath.get();
libSpec.type = PR_LibSpec_Pathname; libSpec.type = PR_LibSpec_Pathname;
#endif #endif
@ -132,7 +139,8 @@ Library::Create(JSContext* cx, jsval aPath)
} }
// stash the library // stash the library
if (!JS_SetReservedSlot(cx, libraryObj, 0, PRIVATE_TO_JSVAL(library))) if (!JS_SetReservedSlot(cx, libraryObj, SLOT_LIBRARY,
PRIVATE_TO_JSVAL(library)))
return NULL; return NULL;
return libraryObj; return libraryObj;
@ -144,7 +152,7 @@ Library::GetLibrary(JSContext* cx, JSObject* obj)
JS_ASSERT(JS_GET_CLASS(cx, obj) == &sLibraryClass); JS_ASSERT(JS_GET_CLASS(cx, obj) == &sLibraryClass);
jsval slot; jsval slot;
JS_GetReservedSlot(cx, obj, 0, &slot); JS_GetReservedSlot(cx, obj, SLOT_LIBRARY, &slot);
return static_cast<PRLibrary*>(JSVAL_TO_PRIVATE(slot)); return static_cast<PRLibrary*>(JSVAL_TO_PRIVATE(slot));
} }
@ -154,7 +162,7 @@ GetFunctionList(JSContext* cx, JSObject* obj)
JS_ASSERT(JS_GET_CLASS(cx, obj) == &sLibraryClass); JS_ASSERT(JS_GET_CLASS(cx, obj) == &sLibraryClass);
jsval slot; jsval slot;
JS_GetReservedSlot(cx, obj, 1, &slot); JS_GetReservedSlot(cx, obj, SLOT_FUNCTIONLIST, &slot);
return static_cast<Function*>(JSVAL_TO_PRIVATE(slot)); return static_cast<Function*>(JSVAL_TO_PRIVATE(slot));
} }
@ -163,7 +171,20 @@ Library::AddFunction(JSContext* cx, JSObject* aLibrary, Function* aFunction)
{ {
// add the new Function instance to the head of the list // add the new Function instance to the head of the list
aFunction->Next() = GetFunctionList(cx, aLibrary); aFunction->Next() = GetFunctionList(cx, aLibrary);
return JS_SetReservedSlot(cx, aLibrary, 1, PRIVATE_TO_JSVAL(aFunction)); return JS_SetReservedSlot(cx, aLibrary, SLOT_FUNCTIONLIST,
PRIVATE_TO_JSVAL(aFunction)) != JS_FALSE;
}
void
Library::Trace(JSTracer *trc, JSObject* obj)
{
// Walk the Function list and for each Function, identify each CType
// associated with it to the tracer.
Function* current = GetFunctionList(trc->context, obj);
while (current) {
current->Trace(trc);
current = current->Next();
}
} }
void void
@ -186,7 +207,7 @@ Library::Finalize(JSContext* cx, JSObject* obj)
JSBool JSBool
Library::Open(JSContext* cx, uintN argc, jsval *vp) Library::Open(JSContext* cx, uintN argc, jsval *vp)
{ {
if (argc != 1) { if (argc != 1 || JSVAL_IS_VOID(JS_ARGV(cx, vp)[0])) {
JS_ReportError(cx, "open requires a single argument"); JS_ReportError(cx, "open requires a single argument");
return JS_FALSE; return JS_FALSE;
} }
@ -217,8 +238,8 @@ Library::Close(JSContext* cx, uintN argc, jsval* vp)
// delete our internal objects // delete our internal objects
Finalize(cx, obj); Finalize(cx, obj);
JS_SetReservedSlot(cx, obj, 0, PRIVATE_TO_JSVAL(NULL)); JS_SetReservedSlot(cx, obj, SLOT_LIBRARY, PRIVATE_TO_JSVAL(NULL));
JS_SetReservedSlot(cx, obj, 1, PRIVATE_TO_JSVAL(NULL)); JS_SetReservedSlot(cx, obj, SLOT_FUNCTIONLIST, PRIVATE_TO_JSVAL(NULL));
JS_SET_RVAL(cx, vp, JSVAL_VOID); JS_SET_RVAL(cx, vp, JSVAL_VOID);
return JS_TRUE; return JS_TRUE;
@ -251,14 +272,15 @@ Library::Declare(JSContext* cx, uintN argc, jsval* vp)
return JS_FALSE; return JS_FALSE;
} }
const char* name = JS_GetStringBytes(JSVAL_TO_STRING(argv[0])); const char* name = JS_GetStringBytesZ(cx, JSVAL_TO_STRING(argv[0]));
PRFuncPtr func = PR_FindFunctionSymbol(library, name); PRFuncPtr func = PR_FindFunctionSymbol(library, name);
if (!func) { if (!func) {
JS_ReportError(cx, "couldn't find function symbol in library"); JS_ReportError(cx, "couldn't find function symbol in library");
return JS_FALSE; return JS_FALSE;
} }
JSObject* fn = Function::Create(cx, obj, func, name, argv[1], argv[2], &argv[3], argc - 3); JSObject* fn = Function::Create(cx, obj, func, name, argv[1], argv[2],
&argv[3], argc - 3);
if (!fn) if (!fn)
return JS_FALSE; return JS_FALSE;

View File

@ -40,19 +40,24 @@
#ifndef LIBRARY_H #ifndef LIBRARY_H
#define LIBRARY_H #define LIBRARY_H
#include "Function.h"
#include "jsapi.h"
struct PRLibrary; struct PRLibrary;
class Function;
namespace mozilla { namespace mozilla {
namespace ctypes { namespace ctypes {
class Function;
enum LibrarySlot {
SLOT_LIBRARY = 0,
SLOT_FUNCTIONLIST = 1,
LIBRARY_SLOTS
};
class Library class Library
{ {
public: public:
static JSObject* Create(JSContext* cx, jsval aPath); static JSObject* Create(JSContext* cx, jsval aPath);
static void Trace(JSTracer *trc, JSObject* obj);
static void Finalize(JSContext* cx, JSObject* obj); static void Finalize(JSContext* cx, JSObject* obj);
static PRLibrary* GetLibrary(JSContext* cx, JSObject* obj); static PRLibrary* GetLibrary(JSContext* cx, JSObject* obj);

View File

@ -62,6 +62,7 @@ IS_COMPONENT = 1
CPPSRCS = \ CPPSRCS = \
Function.cpp \ Function.cpp \
Library.cpp \ Library.cpp \
CTypes.cpp \
Module.cpp \ Module.cpp \
$(NULL) $(NULL)

View File

@ -39,6 +39,7 @@
#include "Module.h" #include "Module.h"
#include "Library.h" #include "Library.h"
#include "CTypes.h"
#include "nsIGenericFactory.h" #include "nsIGenericFactory.h"
#include "nsMemory.h" #include "nsMemory.h"
@ -83,74 +84,15 @@ Module::Call(nsIXPConnectWrappedNative* wrapper,
return NS_OK; return NS_OK;
} }
static JSClass sCABIClass = { #define CTYPESFN_FLAGS \
"CABI", (JSFUN_FAST_NATIVE | JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT)
JSCLASS_HAS_RESERVED_SLOTS(1),
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub,JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};
static JSClass sCTypeClass = {
"CType",
JSCLASS_HAS_RESERVED_SLOTS(1),
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub,JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};
static JSFunctionSpec sModuleFunctions[] = { static JSFunctionSpec sModuleFunctions[] = {
JS_FN("open", Library::Open, 0, JSFUN_FAST_NATIVE | JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT), JS_FN("open", Library::Open, 1, CTYPESFN_FLAGS),
JS_FN("cast", CData::Cast, 2, CTYPESFN_FLAGS),
JS_FS_END JS_FS_END
}; };
ABICode
Module::GetABICode(JSContext* cx, jsval val)
{
// make sure we have an object representing a CABI class,
// and extract the enumerated class type from the reserved slot.
if (!JSVAL_IS_OBJECT(val))
return INVALID_ABI;
JSObject* obj = JSVAL_TO_OBJECT(val);
if (JS_GET_CLASS(cx, obj) != &sCABIClass)
return INVALID_ABI;
jsval result;
JS_GetReservedSlot(cx, obj, 0, &result);
return ABICode(JSVAL_TO_INT(result));
}
TypeCode
Module::GetTypeCode(JSContext* cx, jsval val)
{
// make sure we have an object representing a CType class,
// and extract the enumerated class type from the reserved slot.
if (!JSVAL_IS_OBJECT(val))
return INVALID_TYPE;
JSObject* obj = JSVAL_TO_OBJECT(val);
if (JS_GET_CLASS(cx, obj) != &sCTypeClass)
return INVALID_TYPE;
jsval result;
JS_GetReservedSlot(cx, obj, 0, &result);
return TypeCode(JSVAL_TO_INT(result));
}
static bool
DefineConstant(JSContext* cx, JSObject* parent, JSClass* clasp, const char* name, jsint code)
{
JSObject* obj = JS_DefineObject(cx, parent, name, clasp, NULL,
JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
if (!obj)
return false;
return JS_SetReservedSlot(cx, obj, 0, INT_TO_JSVAL(code));
}
bool bool
Module::Init(JSContext* cx, JSObject* aGlobal) Module::Init(JSContext* cx, JSObject* aGlobal)
{ {
@ -163,22 +105,16 @@ Module::Init(JSContext* cx, JSObject* aGlobal)
NULL, NULL, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT)) NULL, NULL, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT))
return false; return false;
// attach classes representing ABI and type constants if (!InitTypeClasses(cx, ctypes))
#define DEFINE_ABI(name) \
if (!DefineConstant(cx, ctypes, &sCABIClass, #name, ABI_##name)) \
return false; return false;
#define DEFINE_TYPE(name) \
if (!DefineConstant(cx, ctypes, &sCTypeClass, #name, TYPE_##name)) \
return false;
#include "types.h"
#undef DEFINE_ABI
#undef DEFINE_TYPE
// attach API functions // attach API functions
if (!JS_DefineFunctions(cx, ctypes, sModuleFunctions)) if (!JS_DefineFunctions(cx, ctypes, sModuleFunctions))
return false; return false;
return true; // Seal the ctypes object, to prevent modification. (This single object
// instance is shared amongst everyone who imports the ctypes module.)
return JS_SealObject(cx, ctypes, JS_FALSE) != JS_FALSE;
} }
} }

View File

@ -44,27 +44,6 @@
namespace mozilla { namespace mozilla {
namespace ctypes { namespace ctypes {
// Each internal CABI and CType class (representing ABI and type constants,
// respectively) has a unique identifier, stored in a reserved slot on the
// JSObject.
enum ABICode {
#define DEFINE_ABI(name) ABI_##name,
#define DEFINE_TYPE(name)
#include "types.h"
#undef DEFINE_ABI
#undef DEFINE_TYPE
INVALID_ABI
};
enum TypeCode {
#define DEFINE_ABI(name)
#define DEFINE_TYPE(name) TYPE_##name,
#include "types.h"
#undef DEFINE_ABI
#undef DEFINE_TYPE
INVALID_TYPE
};
class Module : public nsIXPCScriptable class Module : public nsIXPCScriptable
{ {
public: public:
@ -76,9 +55,6 @@ public:
// Creates the ctypes object and attaches it to the global object. // Creates the ctypes object and attaches it to the global object.
bool Init(JSContext* aContext, JSObject* aGlobal); bool Init(JSContext* aContext, JSObject* aGlobal);
static ABICode GetABICode(JSContext* cx, jsval val);
static TypeCode GetTypeCode(JSContext* cx, jsval val);
private: private:
~Module(); ~Module();
}; };

View File

@ -44,123 +44,127 @@
#include <math.h> #include <math.h>
void void
test_v() test_void_t_cdecl()
{ {
// do nothing // do nothing
return; return;
} }
PRInt8 #define DEFINE_TYPE(name, type, ffiType) \
test_i8() type \
{ get_##name##_cdecl() \
return 123; { \
return 109.25; \
} \
\
type \
set_##name##_cdecl(type x) \
{ \
return x; \
} \
\
type \
sum_##name##_cdecl(type x, type y) \
{ \
return x + y; \
} \
\
type \
sum_alignb_##name##_cdecl(char a, type x, char b, type y, char c) \
{ \
return x + y; \
} \
\
type \
sum_alignf_##name##_cdecl(float a, type x, float b, type y, float c) \
{ \
return x + y; \
} \
\
type \
sum_many_##name##_cdecl( \
type a, type b, type c, type d, type e, type f, type g, type h, type i, \
type j, type k, type l, type m, type n, type o, type p, type q, type r) \
{ \
return a + b + c + d + e + f + g + h + i + j + k + l + m + n + o + p + q + r;\
} \
\
struct align_##name { \
char x; \
type y; \
}; \
struct nested_##name { \
char a; \
align_##name b; \
char c; \
}; \
\
void \
get_##name##_stats(size_t* align, size_t* size, size_t* nalign, size_t* nsize, \
size_t offsets[]) \
{ \
*align = offsetof(align_##name, y); \
*size = sizeof(align_##name); \
*nalign = offsetof(nested_##name, b); \
*nsize = sizeof(nested_##name); \
offsets[0] = offsetof(align_##name, y); \
offsets[1] = offsetof(nested_##name, b); \
offsets[2] = offsetof(nested_##name, c); \
} }
PRInt8 #include "../typedefs.h"
test_i8_i8(PRInt8 number)
{ #if defined(_WIN32) && !defined(__WIN64)
return number;
#define DEFINE_TYPE(name, type, ffiType) \
type NS_STDCALL \
get_##name##_stdcall() \
{ \
return 109.25; \
} \
\
type NS_STDCALL \
set_##name##_stdcall(type x) \
{ \
return x; \
} \
\
type NS_STDCALL \
sum_##name##_stdcall(type x, type y) \
{ \
return x + y; \
} \
\
type NS_STDCALL \
sum_alignb_##name##_stdcall(char a, type x, char b, type y, char c) \
{ \
return x + y; \
} \
\
type NS_STDCALL \
sum_alignf_##name##_stdcall(float a, type x, float b, type y, float c) \
{ \
return x + y; \
} \
\
type NS_STDCALL \
sum_many_##name##_stdcall( \
type a, type b, type c, type d, type e, type f, type g, type h, type i, \
type j, type k, type l, type m, type n, type o, type p, type q, type r) \
{ \
return a + b + c + d + e + f + g + h + i + j + k + l + m + n + o + p + q + r;\
} }
PRInt8 #include "../typedefs.h"
test_i8_i8_sum(PRInt8 number1, PRInt8 number2)
void NS_STDCALL
test_void_t_stdcall()
{ {
return number1 + number2; // do nothing
return;
} }
PRInt16 #endif /* defined(_WIN32) && !defined(__WIN64) */
test_i16()
{
return 12345;
}
PRInt16
test_i16_i16(PRInt16 number)
{
return number;
}
PRInt16
test_i16_i16_sum(PRInt16 number1, PRInt16 number2)
{
return number1 + number2;
}
PRInt32
test_i32()
{
return 123456789;
}
PRInt32
test_i32_i32(PRInt32 number)
{
return number;
}
PRInt32
test_i32_i32_sum(PRInt32 number1, PRInt32 number2)
{
return number1 + number2;
}
PRInt64
test_i64()
{
#if defined(WIN32) && !defined(__GNUC__)
return 0x28590a1c921de000i64;
#else
return 0x28590a1c921de000LL;
#endif
}
PRInt64
test_i64_i64(PRInt64 number)
{
return number;
}
PRInt64
test_i64_i64_sum(PRInt64 number1, PRInt64 number2)
{
return number1 + number2;
}
float
test_f()
{
return 123456.5f;
}
float
test_f_f(float number)
{
return number;
}
float
test_f_f_sum(float number1, float number2)
{
return (number1 + number2);
}
double
test_d()
{
return 1234567890123456789.5;
}
double
test_d_d(double number)
{
return number;
}
double
test_d_d_sum(double number1, double number2)
{
return (number1 + number2);
}
PRInt32 PRInt32
test_ansi_len(const char* string) test_ansi_len(const char* string)
@ -194,8 +198,33 @@ test_ansi_echo(const char* string)
} }
PRInt32 PRInt32
test_floor(PRInt32 number1, float number2) test_pt_in_rect(RECT rc, POINT pt)
{ {
return PRInt32(floor(float(number1) + number2)); if (pt.x < rc.left || pt.x > rc.right)
return 0;
if (pt.y < rc.bottom || pt.y > rc.top)
return 0;
return 1;
}
void
test_init_pt(POINT* pt, PRInt32 x, PRInt32 y)
{
pt->x = x;
pt->y = y;
}
PRInt32
test_nested_struct(NESTED n)
{
return PRInt32(n.n1 + n.n2 + n.inner.i1 + n.inner.i2 + n.inner.i3 + n.n3 + n.n4);
}
POINT
test_struct_return(RECT r)
{
POINT p;
p.x = r.left; p.y = r.top;
return p;
} }

View File

@ -40,34 +40,56 @@
#include "nscore.h" #include "nscore.h"
#include "prtypes.h" #include "prtypes.h"
#include "jsapi.h"
#define EXPORT_CDECL(type) NS_EXPORT type
#define EXPORT_STDCALL(type) NS_EXPORT type NS_STDCALL
NS_EXTERN_C NS_EXTERN_C
{ {
NS_EXPORT void test_v(); EXPORT_CDECL(void) test_void_t_cdecl();
NS_EXPORT PRInt8 test_i8(); EXPORT_CDECL(void*) get_voidptr_t_cdecl();
NS_EXPORT PRInt8 test_i8_i8(PRInt8); EXPORT_CDECL(void*) set_voidptr_t_cdecl(void*);
NS_EXPORT PRInt8 test_i8_i8_sum(PRInt8, PRInt8);
NS_EXPORT PRInt16 test_i16(); #define DEFINE_TYPE(name, type, ffiType) \
NS_EXPORT PRInt16 test_i16_i16(PRInt16); EXPORT_CDECL(type) get_##name##_cdecl(); \
NS_EXPORT PRInt16 test_i16_i16_sum(PRInt16, PRInt16); EXPORT_CDECL(type) set_##name##_cdecl(type); \
EXPORT_CDECL(type) sum_##name##_cdecl(type, type); \
EXPORT_CDECL(type) sum_alignb_##name##_cdecl(char, type, char, type, char); \
EXPORT_CDECL(type) sum_alignf_##name##_cdecl( \
float, type, float, type, float); \
EXPORT_CDECL(type) sum_many_##name##_cdecl( \
type, type, type, type, type, type, type, type, type, \
type, type, type, type, type, type, type, type, type); \
\
EXPORT_CDECL(void) get_##name##_stats(size_t* align, size_t* size, \
size_t* nalign, size_t* nsize, \
size_t offsets[]);
NS_EXPORT PRInt32 test_i32(); #include "../typedefs.h"
NS_EXPORT PRInt32 test_i32_i32(PRInt32);
NS_EXPORT PRInt32 test_i32_i32_sum(PRInt32, PRInt32);
NS_EXPORT PRInt64 test_i64(); #if defined(_WIN32) && !defined(__WIN64)
NS_EXPORT PRInt64 test_i64_i64(PRInt64); EXPORT_STDCALL(void) test_void_t_stdcall();
NS_EXPORT PRInt64 test_i64_i64_sum(PRInt64, PRInt64);
NS_EXPORT float test_f(); EXPORT_STDCALL(void*) get_voidptr_t_stdcall();
NS_EXPORT float test_f_f(float); EXPORT_STDCALL(void*) set_voidptr_t_stdcall(void*);
NS_EXPORT float test_f_f_sum(float, float);
NS_EXPORT double test_d(); #define DEFINE_TYPE(name, type, ffiType) \
NS_EXPORT double test_d_d(double); EXPORT_STDCALL(type) get_##name##_stdcall(); \
NS_EXPORT double test_d_d_sum(double, double); EXPORT_STDCALL(type) set_##name##_stdcall(type); \
EXPORT_STDCALL(type) sum_##name##_stdcall(type, type); \
EXPORT_STDCALL(type) sum_alignb_##name##_stdcall( \
char, type, char, type, char); \
EXPORT_STDCALL(type) sum_alignf_##name##_stdcall( \
float, type, float, type, float); \
EXPORT_STDCALL(type) sum_many_##name##_stdcall( \
type, type, type, type, type, type, type, type, type, \
type, type, type, type, type, type, type, type, type);
#include "../typedefs.h"
#endif /* defined(_WIN32) && !defined(__WIN64) */
NS_EXPORT PRInt32 test_ansi_len(const char*); NS_EXPORT PRInt32 test_ansi_len(const char*);
NS_EXPORT PRInt32 test_wide_len(const PRUnichar*); NS_EXPORT PRInt32 test_wide_len(const PRUnichar*);
@ -75,6 +97,36 @@ NS_EXTERN_C
NS_EXPORT const PRUnichar* test_wide_ret(); NS_EXPORT const PRUnichar* test_wide_ret();
NS_EXPORT char* test_ansi_echo(const char*); NS_EXPORT char* test_ansi_echo(const char*);
NS_EXPORT PRInt32 test_floor(PRInt32, float); struct POINT {
PRInt32 x;
PRInt32 y;
};
struct RECT {
PRInt32 top;
PRInt32 left;
PRInt32 bottom;
PRInt32 right;
};
struct INNER {
PRUint8 i1;
PRInt64 i2;
PRUint8 i3;
};
struct NESTED {
PRInt32 n1;
PRInt16 n2;
INNER inner;
PRInt64 n3;
PRInt32 n4;
};
NS_EXPORT PRInt32 test_pt_in_rect(RECT, POINT);
NS_EXPORT void test_init_pt(POINT* pt, PRInt32 x, PRInt32 y);
NS_EXPORT PRInt32 test_nested_struct(NESTED);
NS_EXPORT POINT test_struct_return(RECT);
} }

File diff suppressed because it is too large Load Diff

141
js/ctypes/typedefs.h Normal file
View File

@ -0,0 +1,141 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is js-ctypes.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation <http://www.mozilla.org/>.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dan Witte <dwitte@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
// If we're not breaking the types out, combine them together under one
// DEFINE_TYPE macro. Otherwise, turn off whichever ones we're not using.
#if defined(DEFINE_TYPE)
# define DEFINE_CHAR_TYPE(x, y, z) DEFINE_TYPE(x, y, z)
# define DEFINE_BOOL_TYPE(x, y, z) DEFINE_TYPE(x, y, z)
# define DEFINE_INT_TYPE(x, y, z) DEFINE_TYPE(x, y, z)
# define DEFINE_WRAPPED_INT_TYPE(x, y, z) DEFINE_TYPE(x, y, z)
# define DEFINE_FLOAT_TYPE(x, y, z) DEFINE_TYPE(x, y, z)
#else
# ifndef DEFINE_BOOL_TYPE
# define DEFINE_BOOL_TYPE(x, y, z)
# endif
# ifndef DEFINE_CHAR_TYPE
# define DEFINE_CHAR_TYPE(x, y, z)
# endif
# ifndef DEFINE_INT_TYPE
# define DEFINE_INT_TYPE(x, y, z)
# endif
# ifndef DEFINE_WRAPPED_INT_TYPE
# define DEFINE_WRAPPED_INT_TYPE(x, y, z)
# endif
# ifndef DEFINE_FLOAT_TYPE
# define DEFINE_FLOAT_TYPE(x, y, z)
# endif
#endif
// MSVC doesn't have ssize_t. Help it along a little.
#ifndef _MSC_VER
#define CTYPES_SSIZE_T ssize_t
#else
#define CTYPES_SSIZE_T intptr_t
#endif
// Some #defines to make handling of types whose length varies by platform
// easier. These could be implemented as configure tests, but the expressions
// are all statically resolvable so there's no need.
#define CTYPES_FFI_BOOL (sizeof(bool) == 1 ? ffi_type_uint8 : ffi_type_uint32)
#define CTYPES_FFI_LONG (sizeof(long) == 4 ? ffi_type_sint32 : ffi_type_sint64)
#define CTYPES_FFI_ULONG (sizeof(long) == 4 ? ffi_type_uint32 : ffi_type_uint64)
#define CTYPES_FFI_SIZE_T (sizeof(size_t) == 4 ? ffi_type_uint32 : ffi_type_uint64)
#define CTYPES_FFI_SSIZE_T (sizeof(size_t) == 4 ? ffi_type_sint32 : ffi_type_sint64)
#define CTYPES_FFI_INTPTR_T (sizeof(uintptr_t) == 4 ? ffi_type_sint32 : ffi_type_sint64)
#define CTYPES_FFI_UINTPTR_T (sizeof(uintptr_t) == 4 ? ffi_type_uint32 : ffi_type_uint64)
/**
* Builtin types available for arguments and return values, representing
* their C counterparts. Format is:
*
* DEFINE_X_TYPE(typename, ctype, ffitype)
*
* where 'typename' is the name of the type constructor (accessible as
* ctypes.typename), 'ctype' is the corresponding C type declaration (from
* which sizeof(ctype) and templated type conversions will be derived), and
* 'ffitype' is the ffi_type to use. (Special types, such as 'void' and the
* pointer, array, and struct types are handled separately.)
*/
DEFINE_BOOL_TYPE (bool, bool, CTYPES_FFI_BOOL)
DEFINE_INT_TYPE (int8_t, PRInt8, ffi_type_sint8)
DEFINE_INT_TYPE (int16_t, PRInt16, ffi_type_sint16)
DEFINE_INT_TYPE (int32_t, PRInt32, ffi_type_sint32)
DEFINE_INT_TYPE (uint8_t, PRUint8, ffi_type_uint8)
DEFINE_INT_TYPE (uint16_t, PRUint16, ffi_type_uint16)
DEFINE_INT_TYPE (uint32_t, PRUint32, ffi_type_uint32)
DEFINE_INT_TYPE (short, short, ffi_type_sint16)
DEFINE_INT_TYPE (unsigned_short, unsigned short, ffi_type_uint16)
DEFINE_INT_TYPE (int, int, ffi_type_sint32)
DEFINE_INT_TYPE (unsigned_int, unsigned int, ffi_type_uint32)
DEFINE_INT_TYPE (unsigned, unsigned, ffi_type_uint32)
DEFINE_WRAPPED_INT_TYPE(int64_t, PRInt64, ffi_type_sint64)
DEFINE_WRAPPED_INT_TYPE(uint64_t, PRUint64, ffi_type_uint64)
DEFINE_WRAPPED_INT_TYPE(long, long, CTYPES_FFI_LONG)
DEFINE_WRAPPED_INT_TYPE(unsigned_long, unsigned long, CTYPES_FFI_ULONG)
DEFINE_WRAPPED_INT_TYPE(long_long, long long, ffi_type_sint64)
DEFINE_WRAPPED_INT_TYPE(unsigned_long_long, unsigned long long, ffi_type_uint64)
DEFINE_WRAPPED_INT_TYPE(size_t, size_t, CTYPES_FFI_SIZE_T)
DEFINE_WRAPPED_INT_TYPE(ssize_t, CTYPES_SSIZE_T, CTYPES_FFI_SSIZE_T)
DEFINE_WRAPPED_INT_TYPE(intptr_t, intptr_t, CTYPES_FFI_INTPTR_T)
DEFINE_WRAPPED_INT_TYPE(uintptr_t, uintptr_t, CTYPES_FFI_UINTPTR_T)
DEFINE_FLOAT_TYPE (float32_t, float, ffi_type_float)
DEFINE_FLOAT_TYPE (float64_t, double, ffi_type_double)
DEFINE_FLOAT_TYPE (float, float, ffi_type_float)
DEFINE_FLOAT_TYPE (double, double, ffi_type_double)
DEFINE_CHAR_TYPE (char, char, ffi_type_uint8)
DEFINE_CHAR_TYPE (signed_char, signed char, ffi_type_sint8)
DEFINE_CHAR_TYPE (unsigned_char, unsigned char, ffi_type_uint8)
DEFINE_CHAR_TYPE (jschar, jschar, ffi_type_uint16)
#undef CTYPES_SSIZE_T
#undef CTYPES_FFI_BOOL
#undef CTYPES_FFI_LONG
#undef CTYPES_FFI_ULONG
#undef CTYPES_FFI_SIZE_T
#undef CTYPES_FFI_SSIZE_T
#undef CTYPES_FFI_INTPTR_T
#undef CTYPES_FFI_UINTPTR_T
#undef DEFINE_TYPE
#undef DEFINE_CHAR_TYPE
#undef DEFINE_BOOL_TYPE
#undef DEFINE_INT_TYPE
#undef DEFINE_WRAPPED_INT_TYPE
#undef DEFINE_FLOAT_TYPE

View File

@ -1,72 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is js-ctypes.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation <http://www.mozilla.org/>.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dan Witte <dwitte@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/**
* This file defines the constants available on the ctypes.types object (e.g.
* ctypes.types.VOID). They do not have any interesting properties; they simply
* exist as unique identifiers for the type they represent.
*/
/**
* ABI constants that specify the calling convention to use.
* DEFAULT corresponds to the cdecl convention, and in almost all
* cases is the correct choice. STDCALL is provided for calling
* functions in the Microsoft Win32 API.
*/
DEFINE_ABI(default_abi) // corresponds to cdecl
DEFINE_ABI(stdcall_abi) // for calling Win32 API functions
/**
* Types available for arguments and return values, representing
* their C counterparts.
*/
DEFINE_TYPE(void_t) // Only allowed for return types.
DEFINE_TYPE(bool) // _Bool type (assumed 8 bits wide).
DEFINE_TYPE(int8_t) // int8_t (signed char) type.
DEFINE_TYPE(int16_t) // int16_t (short) type.
DEFINE_TYPE(int32_t) // int32_t (int) type.
DEFINE_TYPE(int64_t) // int64_t (long long) type.
DEFINE_TYPE(uint8_t) // uint8_t (unsigned char) type.
DEFINE_TYPE(uint16_t) // uint16_t (unsigned short) type.
DEFINE_TYPE(uint32_t) // uint32_t (unsigned int) type.
DEFINE_TYPE(uint64_t) // uint64_t (unsigned long long) type.
DEFINE_TYPE(float) // float type.
DEFINE_TYPE(double) // double type.
DEFINE_TYPE(string) // C string (char *).
DEFINE_TYPE(ustring) // 16-bit string (char16_t *).