chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1 @@
|
||||
*.cpp
|
||||
@@ -0,0 +1,169 @@
|
||||
from ..base import DGLError
|
||||
from libcpp.vector cimport vector
|
||||
from libcpp cimport bool
|
||||
from cpython.version cimport PY_MAJOR_VERSION
|
||||
from cpython cimport pycapsule
|
||||
from libc.stdint cimport int32_t, int64_t, uint64_t, uint8_t, uint16_t
|
||||
import ctypes
|
||||
|
||||
cdef enum DGLObjectTypeCode:
|
||||
kObjectInt = 0
|
||||
kObjectUInt = 1
|
||||
kObjectFloat = 2
|
||||
kHandle = 3
|
||||
kNull = 4
|
||||
kDGLDataType = 5
|
||||
kDGLContext = 6
|
||||
kArrayHandle = 7
|
||||
kObjectHandle = 8
|
||||
kModuleHandle = 9
|
||||
kFuncHandle = 10
|
||||
kStr = 11
|
||||
kBytes = 12
|
||||
kNDArrayContainer = 13
|
||||
kExtBegin = 15
|
||||
|
||||
cdef extern from "dgl/runtime/c_runtime_api.h":
|
||||
ctypedef struct DGLDataType:
|
||||
uint8_t code
|
||||
uint8_t bits
|
||||
uint16_t lanes
|
||||
|
||||
ctypedef struct DGLContext:
|
||||
int32_t device_type
|
||||
int32_t device_id
|
||||
|
||||
ctypedef struct DGLArray:
|
||||
void* data
|
||||
DGLContext ctx
|
||||
int32_t ndim
|
||||
DGLDataType dtype
|
||||
int64_t* shape
|
||||
int64_t* strides
|
||||
uint64_t byte_offset
|
||||
|
||||
ctypedef struct DLManagedTensor:
|
||||
DGLArray dl_tensor
|
||||
void* manager_ctx
|
||||
void (*deleter)(DLManagedTensor* self)
|
||||
|
||||
ctypedef struct DGLValue:
|
||||
int64_t v_int64
|
||||
double v_float64
|
||||
void* v_handle
|
||||
const char* v_str
|
||||
DGLDataType v_type
|
||||
DGLContext v_ctx
|
||||
|
||||
ctypedef int64_t dgl_index_t
|
||||
ctypedef DGLArray* DGLArrayHandle
|
||||
ctypedef void* DGLStreamHandle
|
||||
ctypedef void* DGLRetValueHandle
|
||||
ctypedef void* DGLFunctionHandle
|
||||
ctypedef void* ObjectHandle
|
||||
|
||||
ctypedef int (*DGLPackedCFunc)(
|
||||
DGLValue* args,
|
||||
int* type_codes,
|
||||
int num_args,
|
||||
DGLRetValueHandle ret,
|
||||
void* resource_handle)
|
||||
|
||||
ctypedef void (*DGLPackedCFuncFinalizer)(void* resource_handle)
|
||||
|
||||
cdef extern from "dgl/runtime/c_runtime_api.h":
|
||||
void DGLAPISetLastError(const char* msg)
|
||||
const char *DGLGetLastError()
|
||||
int DGLFuncCall(DGLFunctionHandle func,
|
||||
DGLValue* arg_values,
|
||||
int* type_codes,
|
||||
int num_args,
|
||||
DGLValue* ret_val,
|
||||
int* ret_type_code) nogil
|
||||
int DGLFuncFree(DGLFunctionHandle func)
|
||||
int DGLCFuncSetReturn(DGLRetValueHandle ret,
|
||||
DGLValue* value,
|
||||
int* type_code,
|
||||
int num_ret)
|
||||
int DGLFuncCreateFromCFunc(DGLPackedCFunc func,
|
||||
void* resource_handle,
|
||||
DGLPackedCFuncFinalizer fin,
|
||||
DGLFunctionHandle *out)
|
||||
int DGLCbArgToReturn(DGLValue* value, int code)
|
||||
int DGLArrayAlloc(dgl_index_t* shape,
|
||||
dgl_index_t ndim,
|
||||
DGLDataType dtype,
|
||||
DGLContext ctx,
|
||||
DGLArrayHandle* out)
|
||||
int DGLArrayAllocSharedMem(const char *mem_name,
|
||||
const dgl_index_t *shape,
|
||||
int ndim,
|
||||
int dtype_code,
|
||||
int dtype_bits,
|
||||
int dtype_lanes,
|
||||
bool is_create,
|
||||
DGLArrayHandle* out)
|
||||
int DGLArrayFree(DGLArrayHandle handle)
|
||||
int DGLArrayCopyFromTo(DGLArrayHandle src,
|
||||
DGLArrayHandle to)
|
||||
|
||||
cdef extern from "dgl/runtime/c_object_api.h":
|
||||
int DGLObjectFree(ObjectHandle handle)
|
||||
int DGLObjectTypeKey2Index(const char* type_key,
|
||||
int* out_index)
|
||||
int DGLObjectGetTypeIndex(ObjectHandle handle,
|
||||
int* out_index)
|
||||
int DGLObjectGetAttr(ObjectHandle handle,
|
||||
const char* key,
|
||||
DGLValue* out_value,
|
||||
int* out_type_code,
|
||||
int* out_success)
|
||||
|
||||
cdef extern from "dgl/runtime/dlpack_convert.h":
|
||||
int DGLArrayFromDLPack(DLManagedTensor* arr_from,
|
||||
DGLArrayHandle* out)
|
||||
int DGLArrayToDLPack(DGLArrayHandle arr_from,
|
||||
DLManagedTensor** out,
|
||||
int alignment)
|
||||
void DGLDLManagedTensorCallDeleter(DLManagedTensor* dltensor)
|
||||
|
||||
cdef inline py_str(const char* x):
|
||||
if PY_MAJOR_VERSION < 3:
|
||||
return x
|
||||
else:
|
||||
return x.decode("utf-8")
|
||||
|
||||
|
||||
cdef inline c_str(pystr):
|
||||
"""Create ctypes char * from a python string
|
||||
Parameters
|
||||
----------
|
||||
string : string type
|
||||
python string
|
||||
|
||||
Returns
|
||||
-------
|
||||
str : c_char_p
|
||||
A char pointer that can be passed to C API
|
||||
"""
|
||||
return pystr.encode("utf-8")
|
||||
|
||||
|
||||
cdef inline CALL(int ret):
|
||||
if ret != 0:
|
||||
raise DGLError(py_str(DGLGetLastError()))
|
||||
|
||||
|
||||
cdef inline object ctypes_handle(void* chandle):
|
||||
"""Cast C handle to ctypes handle."""
|
||||
return ctypes.cast(<unsigned long long>chandle, ctypes.c_void_p)
|
||||
|
||||
|
||||
cdef inline void* c_handle(object handle):
|
||||
"""Cast C types handle to c handle."""
|
||||
cdef unsigned long long v_ptr
|
||||
if handle.value is None:
|
||||
return NULL
|
||||
else:
|
||||
v_ptr = handle.value
|
||||
return <void*>(v_ptr)
|
||||
@@ -0,0 +1,4 @@
|
||||
include "./base.pxi"
|
||||
include "./object.pxi"
|
||||
include "./function.pxi"
|
||||
include "./ndarray.pxi"
|
||||
@@ -0,0 +1,308 @@
|
||||
import ctypes
|
||||
import traceback
|
||||
from cpython cimport Py_INCREF, Py_DECREF
|
||||
from numbers import Number, Integral
|
||||
from ..base import string_types
|
||||
from ..object_generic import convert_to_object, ObjectGeneric
|
||||
from ..runtime_ctypes import DGLDataType as CTypesDGLDataType, \
|
||||
DGLContext as CTypesDGLContext, \
|
||||
DGLByteArray
|
||||
|
||||
|
||||
cdef void dgl_callback_finalize(void* fhandle):
|
||||
local_pyfunc = <object>(fhandle)
|
||||
Py_DECREF(local_pyfunc)
|
||||
|
||||
cdef int dgl_callback(DGLValue* args,
|
||||
int* type_codes,
|
||||
int num_args,
|
||||
DGLRetValueHandle ret,
|
||||
void* fhandle) with gil:
|
||||
cdef list pyargs
|
||||
cdef DGLValue value
|
||||
cdef int tcode
|
||||
local_pyfunc = <object>(fhandle)
|
||||
pyargs = []
|
||||
for i in range(num_args):
|
||||
value = args[i]
|
||||
tcode = type_codes[i]
|
||||
if (tcode == kObjectHandle or
|
||||
tcode == kFuncHandle or
|
||||
tcode == kModuleHandle or
|
||||
tcode > kExtBegin):
|
||||
CALL(DGLCbArgToReturn(&value, tcode))
|
||||
|
||||
if tcode != kArrayHandle:
|
||||
pyargs.append(make_ret(value, tcode))
|
||||
else:
|
||||
pyargs.append(c_make_array(value.v_handle, True))
|
||||
try:
|
||||
rv = local_pyfunc(*pyargs)
|
||||
except Exception:
|
||||
msg = traceback.format_exc()
|
||||
DGLAPISetLastError(c_str(msg))
|
||||
return -1
|
||||
if rv is not None:
|
||||
if isinstance(rv, tuple):
|
||||
raise ValueError("PackedFunction can only support one return value")
|
||||
temp_args = []
|
||||
make_arg(rv, &value, &tcode, temp_args)
|
||||
CALL(DGLCFuncSetReturn(ret, &value, &tcode, 1))
|
||||
return 0
|
||||
|
||||
|
||||
def convert_to_dgl_func(object pyfunc):
|
||||
"""Convert a python function to DGL function
|
||||
|
||||
Parameters
|
||||
----------
|
||||
pyfunc : python function
|
||||
The python function to be converted.
|
||||
|
||||
Returns
|
||||
-------
|
||||
dglfunc: dgl.Function
|
||||
The converted dgl function.
|
||||
"""
|
||||
cdef DGLFunctionHandle chandle
|
||||
Py_INCREF(pyfunc)
|
||||
CALL(DGLFuncCreateFromCFunc(dgl_callback,
|
||||
<void*>(pyfunc),
|
||||
dgl_callback_finalize,
|
||||
&chandle))
|
||||
ret = _CLASS_FUNCTION(None, False)
|
||||
(<FunctionBase>ret).chandle = chandle
|
||||
return ret
|
||||
|
||||
|
||||
cdef inline int make_arg(object arg,
|
||||
DGLValue* value,
|
||||
int* tcode,
|
||||
list temp_args) except -1:
|
||||
"""Pack arguments into c args dgl call accept"""
|
||||
cdef unsigned long long ptr
|
||||
if isinstance(arg, ObjectBase):
|
||||
value[0].v_handle = (<ObjectBase>arg).chandle
|
||||
tcode[0] = kObjectHandle
|
||||
elif isinstance(arg, NDArrayBase):
|
||||
value[0].v_handle = (<NDArrayBase>arg).chandle
|
||||
tcode[0] = (kNDArrayContainer if
|
||||
not (<NDArrayBase>arg).c_is_view else kArrayHandle)
|
||||
elif isinstance(arg, _DGL_COMPATS):
|
||||
ptr = arg._dgl_handle
|
||||
value[0].v_handle = (<void*>ptr)
|
||||
tcode[0] = arg.__class__._dgl_tcode
|
||||
elif isinstance(arg, (int, long)):
|
||||
value[0].v_int64 = arg
|
||||
tcode[0] = kObjectInt
|
||||
elif isinstance(arg, float):
|
||||
value[0].v_float64 = arg
|
||||
tcode[0] = kObjectFloat
|
||||
elif isinstance(arg, str):
|
||||
tstr = c_str(arg)
|
||||
value[0].v_str = tstr
|
||||
tcode[0] = kStr
|
||||
temp_args.append(tstr)
|
||||
elif arg is None:
|
||||
value[0].v_handle = NULL
|
||||
tcode[0] = kNull
|
||||
elif isinstance(arg, Number):
|
||||
value[0].v_float64 = arg
|
||||
tcode[0] = kObjectFloat
|
||||
elif isinstance(arg, CTypesDGLDataType):
|
||||
tstr = c_str(str(arg))
|
||||
value[0].v_str = tstr
|
||||
tcode[0] = kStr
|
||||
temp_args.append(tstr)
|
||||
elif isinstance(arg, CTypesDGLContext):
|
||||
value[0].v_ctx = (<DGLContext*>(
|
||||
<unsigned long long>ctypes.addressof(arg)))[0]
|
||||
tcode[0] = kDGLContext
|
||||
elif isinstance(arg, bytearray):
|
||||
arr = DGLByteArray()
|
||||
arr.data = ctypes.cast(
|
||||
(ctypes.c_byte * len(arg)).from_buffer(arg),
|
||||
ctypes.POINTER(ctypes.c_byte))
|
||||
arr.size = len(arg)
|
||||
value[0].v_handle = <void*>(
|
||||
<unsigned long long>ctypes.addressof(arr))
|
||||
tcode[0] = kBytes
|
||||
temp_args.append(arr)
|
||||
elif isinstance(arg, string_types):
|
||||
tstr = c_str(arg)
|
||||
value[0].v_str = tstr
|
||||
tcode[0] = kStr
|
||||
temp_args.append(tstr)
|
||||
elif isinstance(arg, (list, tuple, dict, ObjectGeneric)):
|
||||
arg = convert_to_object(arg)
|
||||
value[0].v_handle = (<ObjectBase>arg).chandle
|
||||
tcode[0] = kObjectHandle
|
||||
temp_args.append(arg)
|
||||
#elif isinstance(arg, _CLASS_MODULE):
|
||||
# value[0].v_handle = c_handle(arg.handle)
|
||||
# tcode[0] = kModuleHandle
|
||||
elif isinstance(arg, FunctionBase):
|
||||
value[0].v_handle = (<FunctionBase>arg).chandle
|
||||
tcode[0] = kFuncHandle
|
||||
elif isinstance(arg, ctypes.c_void_p):
|
||||
value[0].v_handle = c_handle(arg)
|
||||
tcode[0] = kHandle
|
||||
elif callable(arg):
|
||||
arg = convert_to_dgl_func(arg)
|
||||
value[0].v_handle = (<FunctionBase>arg).chandle
|
||||
tcode[0] = kFuncHandle
|
||||
temp_args.append(arg)
|
||||
else:
|
||||
raise TypeError("Don't know how to handle type %s" % type(arg))
|
||||
return 0
|
||||
|
||||
cdef inline bytearray make_ret_bytes(void* chandle):
|
||||
handle = ctypes_handle(chandle)
|
||||
arr = ctypes.cast(handle, ctypes.POINTER(DGLByteArray))[0]
|
||||
size = arr.size
|
||||
res = bytearray(size)
|
||||
rptr = (ctypes.c_byte * size).from_buffer(res)
|
||||
if not ctypes.memmove(rptr, arr.data, size):
|
||||
raise RuntimeError('memmove failed')
|
||||
return res
|
||||
|
||||
cdef inline object make_ret(DGLValue value, int tcode):
|
||||
"""convert result to return value."""
|
||||
if tcode == kObjectHandle:
|
||||
return make_ret_object(value.v_handle)
|
||||
elif tcode == kNull:
|
||||
return None
|
||||
elif tcode == kObjectInt:
|
||||
return value.v_int64
|
||||
elif tcode == kObjectFloat:
|
||||
return value.v_float64
|
||||
elif tcode == kNDArrayContainer:
|
||||
return c_make_array(value.v_handle, False)
|
||||
elif tcode == kStr:
|
||||
return py_str(value.v_str)
|
||||
elif tcode == kBytes:
|
||||
return make_ret_bytes(value.v_handle)
|
||||
elif tcode == kHandle:
|
||||
return ctypes_handle(value.v_handle)
|
||||
elif tcode == kDGLContext:
|
||||
return CTypesDGLContext(value.v_ctx.device_type, value.v_ctx.device_id)
|
||||
# (minjie): class module are not used in DGL.
|
||||
#elif tcode == kModuleHandle:
|
||||
# return _CLASS_MODULE(ctypes_handle(value.v_handle))
|
||||
elif tcode == kFuncHandle:
|
||||
fobj = _CLASS_FUNCTION(None, False)
|
||||
(<FunctionBase>fobj).chandle = value.v_handle
|
||||
return fobj
|
||||
elif tcode in _DGL_EXT_RET:
|
||||
return _DGL_EXT_RET[tcode](ctypes_handle(value.v_handle))
|
||||
|
||||
raise ValueError("Unhandled type code %d" % tcode)
|
||||
|
||||
|
||||
cdef inline int FuncCall3(void* chandle,
|
||||
tuple args,
|
||||
int nargs,
|
||||
DGLValue* ret_val,
|
||||
int* ret_tcode) except -1:
|
||||
cdef DGLValue[3] values
|
||||
cdef int[3] tcodes
|
||||
nargs = len(args)
|
||||
temp_args = []
|
||||
for i in range(nargs):
|
||||
make_arg(args[i], &values[i], &tcodes[i], temp_args)
|
||||
with nogil:
|
||||
ret = DGLFuncCall(chandle, &values[0], &tcodes[0],
|
||||
nargs, ret_val, ret_tcode)
|
||||
if ret != 0:
|
||||
raise DGLError(py_str(DGLGetLastError()))
|
||||
return 0
|
||||
|
||||
cdef inline int FuncCall(void* chandle,
|
||||
tuple args,
|
||||
DGLValue* ret_val,
|
||||
int* ret_tcode) except -1:
|
||||
cdef int nargs
|
||||
nargs = len(args)
|
||||
if nargs <= 3:
|
||||
FuncCall3(chandle, args, nargs, ret_val, ret_tcode)
|
||||
return 0
|
||||
|
||||
cdef vector[DGLValue] values
|
||||
cdef vector[int] tcodes
|
||||
values.resize(max(nargs, 1))
|
||||
tcodes.resize(max(nargs, 1))
|
||||
temp_args = []
|
||||
for i in range(nargs):
|
||||
make_arg(args[i], &values[i], &tcodes[i], temp_args)
|
||||
with nogil:
|
||||
ret = DGLFuncCall(chandle, &values[0], &tcodes[0],
|
||||
nargs, ret_val, ret_tcode)
|
||||
if ret != 0:
|
||||
raise DGLError(py_str(DGLGetLastError()))
|
||||
return 0
|
||||
|
||||
|
||||
cdef inline int ConstructorCall(void* constructor_handle,
|
||||
int type_code,
|
||||
tuple args,
|
||||
void** handle) except -1:
|
||||
"""Call contructor of a handle function"""
|
||||
cdef DGLValue ret_val
|
||||
cdef int ret_tcode
|
||||
FuncCall(constructor_handle, args, &ret_val, &ret_tcode)
|
||||
assert ret_tcode == type_code
|
||||
handle[0] = ret_val.v_handle
|
||||
return 0
|
||||
|
||||
|
||||
cdef class FunctionBase:
|
||||
cdef DGLFunctionHandle chandle
|
||||
cdef int is_global
|
||||
|
||||
cdef inline _set_handle(self, handle):
|
||||
if handle is None:
|
||||
self.chandle = NULL
|
||||
else:
|
||||
self.chandle = c_handle(handle)
|
||||
|
||||
property is_global:
|
||||
def __get__(self):
|
||||
return self.c_is_global != 0
|
||||
|
||||
def __set__(self, value):
|
||||
self.c_is_global = value
|
||||
|
||||
property handle:
|
||||
def __get__(self):
|
||||
if self.chandle == NULL:
|
||||
return None
|
||||
else:
|
||||
return ctypes.cast(<unsigned long long>self.chandle, ctypes.c_void_p)
|
||||
def __set__(self, value):
|
||||
self._set_handle(value)
|
||||
|
||||
def __init__(self, handle, is_global):
|
||||
self._set_handle(handle)
|
||||
self.c_is_global = is_global
|
||||
|
||||
def __dealloc__(self):
|
||||
if self.is_global == 0:
|
||||
CALL(DGLFuncFree(self.chandle))
|
||||
|
||||
def __call__(self, *args):
|
||||
cdef DGLValue ret_val
|
||||
cdef int ret_tcode
|
||||
FuncCall(self.chandle, args, &ret_val, &ret_tcode)
|
||||
return make_ret(ret_val, ret_tcode)
|
||||
|
||||
_CLASS_FUNCTION = None
|
||||
_CLASS_MODULE = None
|
||||
|
||||
def _set_class_module(module_class):
|
||||
"""Initialize the module."""
|
||||
global _CLASS_MODULE
|
||||
_CLASS_MODULE = module_class
|
||||
|
||||
def _set_class_function(func_class):
|
||||
global _CLASS_FUNCTION
|
||||
_CLASS_FUNCTION = func_class
|
||||
@@ -0,0 +1,110 @@
|
||||
from ..runtime_ctypes import DGLArrayHandle as PyDGLArrayHandle
|
||||
from cpython cimport PyCapsule_Destructor
|
||||
|
||||
cdef const char* _c_str_dltensor = "dltensor"
|
||||
cdef const char* _c_str_used_dltensor = "used_dltensor"
|
||||
|
||||
|
||||
cdef _c_dlpack_deleter(object pycaps):
|
||||
cdef DLManagedTensor* dltensor
|
||||
if pycapsule.PyCapsule_IsValid(pycaps, _c_str_dltensor):
|
||||
dltensor = <DLManagedTensor*>pycapsule.PyCapsule_GetPointer(pycaps, _c_str_dltensor)
|
||||
DGLDLManagedTensorCallDeleter(dltensor)
|
||||
|
||||
|
||||
def _from_dlpack(object dltensor):
|
||||
cdef DLManagedTensor* ptr
|
||||
cdef DGLArrayHandle chandle
|
||||
if pycapsule.PyCapsule_IsValid(dltensor, _c_str_dltensor):
|
||||
ptr = <DLManagedTensor*>pycapsule.PyCapsule_GetPointer(dltensor, _c_str_dltensor)
|
||||
CALL(DGLArrayFromDLPack(ptr, &chandle))
|
||||
# set name and destructor to be empty
|
||||
pycapsule.PyCapsule_SetDestructor(dltensor, NULL)
|
||||
pycapsule.PyCapsule_SetName(dltensor, _c_str_used_dltensor)
|
||||
return c_make_array(chandle, 0)
|
||||
raise ValueError("Expect a dltensor field, pycapsule.PyCapsule can only be consumed once")
|
||||
|
||||
|
||||
cdef class NDArrayBase:
|
||||
cdef DGLArray* chandle
|
||||
cdef int c_is_view
|
||||
|
||||
cdef inline _set_handle(self, handle):
|
||||
cdef unsigned long long ptr
|
||||
if handle is None:
|
||||
self.chandle = NULL
|
||||
else:
|
||||
ptr = ctypes.cast(handle, ctypes.c_void_p).value
|
||||
self.chandle = <DGLArray*>(ptr)
|
||||
|
||||
property _dgl_handle:
|
||||
def __get__(self):
|
||||
return <unsigned long long>self.chandle
|
||||
|
||||
property handle:
|
||||
def __get__(self):
|
||||
if self.chandle == NULL:
|
||||
return None
|
||||
else:
|
||||
return ctypes.cast(
|
||||
<unsigned long long>self.chandle, PyDGLArrayHandle)
|
||||
|
||||
def __set__(self, value):
|
||||
self._set_handle(value)
|
||||
|
||||
def __init__(self, handle, is_view):
|
||||
self._set_handle(handle)
|
||||
self.c_is_view = is_view
|
||||
|
||||
def __dealloc__(self):
|
||||
if self.c_is_view == 0:
|
||||
CALL(DGLArrayFree(self.chandle))
|
||||
|
||||
def to_dlpack(self, alignment=0):
|
||||
"""Produce an array from a DLPack Tensor without copying memory
|
||||
|
||||
Args
|
||||
-------
|
||||
alignment: int, default to be 0
|
||||
Indicates the alignment requirement when converting to dlpack. Will copy to a
|
||||
new tensor if the alignment requirement is not satisfied.
|
||||
0 means no alignment requirement.
|
||||
|
||||
Returns
|
||||
-------
|
||||
dlpack : DLPack tensor view of the array data
|
||||
"""
|
||||
cdef DLManagedTensor* dltensor
|
||||
if self.c_is_view != 0:
|
||||
raise ValueError("to_dlpack do not work with memory views")
|
||||
CALL(DGLArrayToDLPack(self.chandle, &dltensor, alignment))
|
||||
return pycapsule.PyCapsule_New(dltensor, _c_str_dltensor, <PyCapsule_Destructor>_c_dlpack_deleter)
|
||||
|
||||
|
||||
cdef c_make_array(void* chandle, is_view):
|
||||
ret = _CLASS_NDARRAY(None, is_view)
|
||||
(<NDArrayBase>ret).chandle = <DGLArray*>chandle
|
||||
return ret
|
||||
|
||||
|
||||
cdef _DGL_COMPATS = ()
|
||||
|
||||
cdef _DGL_EXT_RET = {}
|
||||
|
||||
def _reg_extension(cls, fcreate):
|
||||
global _DGL_COMPATS
|
||||
_DGL_COMPATS += (cls,)
|
||||
if fcreate:
|
||||
_DGL_EXT_RET[cls._dgl_tcode] = fcreate
|
||||
|
||||
|
||||
def _make_array(handle, is_view):
|
||||
cdef unsigned long long ptr
|
||||
ptr = ctypes.cast(handle, ctypes.c_void_p).value
|
||||
return c_make_array(<void*>ptr, is_view)
|
||||
|
||||
cdef object _CLASS_NDARRAY = None
|
||||
|
||||
def _set_class_ndarray(cls):
|
||||
global _CLASS_NDARRAY
|
||||
_CLASS_NDARRAY = cls
|
||||
@@ -0,0 +1,91 @@
|
||||
from ... import _api_internal
|
||||
from ..base import string_types
|
||||
from ..object_generic import _set_class_object_base
|
||||
|
||||
"""Maps object type to its constructor"""
|
||||
OBJECT_TYPE = []
|
||||
|
||||
def _register_object(int index, object cls):
|
||||
"""register object class"""
|
||||
while len(OBJECT_TYPE) <= index:
|
||||
OBJECT_TYPE.append(None)
|
||||
OBJECT_TYPE[index] = cls
|
||||
|
||||
|
||||
cdef inline object make_ret_object(void* chandle):
|
||||
global OBJECT_TYPE
|
||||
cdef int tindex
|
||||
cdef list object_type
|
||||
cdef object cls
|
||||
object_type = OBJECT_TYPE
|
||||
CALL(DGLObjectGetTypeIndex(chandle, &tindex))
|
||||
if tindex < len(object_type):
|
||||
cls = object_type[tindex]
|
||||
if cls is not None:
|
||||
obj = cls.__new__(cls)
|
||||
else:
|
||||
obj = ObjectBase.__new__(ObjectBase)
|
||||
else:
|
||||
obj = ObjectBase.__new__(ObjectBase)
|
||||
(<ObjectBase>obj).chandle = chandle
|
||||
return obj
|
||||
|
||||
|
||||
cdef class ObjectBase:
|
||||
cdef void* chandle
|
||||
|
||||
cdef _set_handle(self, handle):
|
||||
cdef unsigned long long ptr
|
||||
if handle is None:
|
||||
self.chandle = NULL
|
||||
else:
|
||||
ptr = handle.value
|
||||
self.chandle = <void*>(ptr)
|
||||
|
||||
property handle:
|
||||
def __get__(self):
|
||||
if self.chandle == NULL:
|
||||
return None
|
||||
else:
|
||||
return ctypes_handle(self.chandle)
|
||||
|
||||
def __set__(self, value):
|
||||
self._set_handle(value)
|
||||
|
||||
def __dealloc__(self):
|
||||
CALL(DGLObjectFree(self.chandle))
|
||||
|
||||
def __getattr__(self, name):
|
||||
cdef DGLValue ret_val
|
||||
cdef int ret_type_code, ret_succ
|
||||
CALL(DGLObjectGetAttr(self.chandle, c_str(name),
|
||||
&ret_val, &ret_type_code, &ret_succ))
|
||||
if ret_succ == 0:
|
||||
raise AttributeError(
|
||||
"'%s' object has no attribute '%s'" % (type(self), name))
|
||||
return make_ret(ret_val, ret_type_code)
|
||||
|
||||
def __init_handle_by_constructor__(self, fconstructor, *args):
|
||||
"""Initialize the handle by calling constructor function.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
fconstructor : Function
|
||||
Constructor function.
|
||||
|
||||
args: list of objects
|
||||
The arguments to the constructor
|
||||
|
||||
Note
|
||||
----
|
||||
We have a special calling convention to call constructor functions.
|
||||
So the return handle is directly set into the Object object
|
||||
instead of creating a new Object.
|
||||
"""
|
||||
cdef void* chandle
|
||||
ConstructorCall(
|
||||
(<FunctionBase>fconstructor).chandle,
|
||||
kObjectHandle, args, &chandle)
|
||||
self.chandle = chandle
|
||||
|
||||
_set_class_object_base(ObjectBase)
|
||||
Reference in New Issue
Block a user