Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
C
cpython
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
cpython
Commits
a06a1a88
Kaydet (Commit)
a06a1a88
authored
Şub 13, 2008
tarafından
Thomas Heller
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Add pickle support to ctypes types.
üst
91a1dec4
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
177 additions
and
1 deletion
+177
-1
ctypes.rst
Doc/library/ctypes.rst
+5
-0
test_pickling.py
Lib/ctypes/test/test_pickling.py
+78
-0
NEWS
Misc/NEWS
+3
-0
_ctypes.c
Modules/_ctypes/_ctypes.c
+63
-1
callproc.c
Modules/_ctypes/callproc.c
+23
-0
ctypes.h
Modules/_ctypes/ctypes.h
+3
-0
stgdict.c
Modules/_ctypes/stgdict.c
+2
-0
No files found.
Doc/library/ctypes.rst
Dosyayı görüntüle @
a06a1a88
...
@@ -2011,6 +2011,11 @@ Fundamental data types
...
@@ -2011,6 +2011,11 @@ Fundamental data types
ctypes data types. ``_SimpleCData`` is a subclass of ``_CData``, so it inherits
ctypes data types. ``_SimpleCData`` is a subclass of ``_CData``, so it inherits
their methods and attributes.
their methods and attributes.
.. versionchanged:: 2.6
ctypes data types that are not and do not contain pointers can
now be pickled.
Instances have a single attribute:
Instances have a single attribute:
...
...
Lib/ctypes/test/test_pickling.py
0 → 100644
Dosyayı görüntüle @
a06a1a88
import
unittest
import
pickle
from
ctypes
import
*
import
_ctypes_test
dll
=
CDLL
(
_ctypes_test
.
__file__
)
class
X
(
Structure
):
_fields_
=
[(
"a"
,
c_int
),
(
"b"
,
c_double
)]
init_called
=
0
def
__init__
(
self
,
*
args
,
**
kw
):
X
.
init_called
+=
1
self
.
x
=
42
class
Y
(
X
):
_fields_
=
[(
"str"
,
c_char_p
)]
class
PickleTest
(
unittest
.
TestCase
):
def
dumps
(
self
,
item
):
return
pickle
.
dumps
(
item
)
def
loads
(
self
,
item
):
return
pickle
.
loads
(
item
)
def
test_simple
(
self
):
for
src
in
[
c_int
(
42
),
c_double
(
3.14
),
]:
dst
=
self
.
loads
(
self
.
dumps
(
src
))
self
.
failUnlessEqual
(
src
.
__dict__
,
dst
.
__dict__
)
self
.
failUnlessEqual
(
buffer
(
src
),
buffer
(
dst
))
def
test_struct
(
self
):
X
.
init_called
=
0
x
=
X
()
x
.
a
=
42
self
.
failUnlessEqual
(
X
.
init_called
,
1
)
y
=
self
.
loads
(
self
.
dumps
(
x
))
# loads must NOT call __init__
self
.
failUnlessEqual
(
X
.
init_called
,
1
)
# ctypes instances are identical when the instance __dict__
# and the memory buffer are identical
self
.
failUnlessEqual
(
y
.
__dict__
,
x
.
__dict__
)
self
.
failUnlessEqual
(
buffer
(
y
),
buffer
(
x
))
def
test_unpickable
(
self
):
# ctypes objects that are pointers or contain pointers are
# unpickable.
self
.
assertRaises
(
ValueError
,
lambda
:
self
.
dumps
(
Y
()))
prototype
=
CFUNCTYPE
(
c_int
)
for
item
in
[
c_char_p
(),
c_wchar_p
(),
c_void_p
(),
pointer
(
c_int
(
42
)),
dll
.
_testfunc_p_p
,
prototype
(
lambda
:
42
),
]:
self
.
assertRaises
(
ValueError
,
lambda
:
self
.
dumps
(
item
))
class
PickleTest_1
(
PickleTest
):
def
dumps
(
self
,
item
):
return
pickle
.
dumps
(
item
,
1
)
class
PickleTest_2
(
PickleTest
):
def
dumps
(
self
,
item
):
return
pickle
.
dumps
(
item
,
2
)
if
__name__
==
"__main__"
:
unittest
.
main
()
Misc/NEWS
Dosyayı görüntüle @
a06a1a88
...
@@ -400,6 +400,9 @@ Core and builtins
...
@@ -400,6 +400,9 @@ Core and builtins
Library
Library
-------
-------
- ctypes instances that are not or do not contain pointers can now be
pickled.
- Patch #1966: Break infinite loop in httplib when the servers
- Patch #1966: Break infinite loop in httplib when the servers
implements the chunked encoding incorrectly.
implements the chunked encoding incorrectly.
...
...
Modules/_ctypes/_ctypes.c
Dosyayı görüntüle @
a06a1a88
...
@@ -128,6 +128,9 @@ bytes(cdata)
...
@@ -128,6 +128,9 @@ bytes(cdata)
PyObject
*
PyExc_ArgError
;
PyObject
*
PyExc_ArgError
;
static
PyTypeObject
Simple_Type
;
static
PyTypeObject
Simple_Type
;
/* a callable object used for unpickling */
static
PyObject
*
_unpickle
;
char
*
conversion_mode_encoding
=
NULL
;
char
*
conversion_mode_encoding
=
NULL
;
char
*
conversion_mode_errors
=
NULL
;
char
*
conversion_mode_errors
=
NULL
;
...
@@ -718,6 +721,7 @@ PointerType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
...
@@ -718,6 +721,7 @@ PointerType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
stgdict
->
length
=
1
;
stgdict
->
length
=
1
;
stgdict
->
ffi_type_pointer
=
ffi_type_pointer
;
stgdict
->
ffi_type_pointer
=
ffi_type_pointer
;
stgdict
->
paramfunc
=
PointerType_paramfunc
;
stgdict
->
paramfunc
=
PointerType_paramfunc
;
stgdict
->
flags
|=
TYPEFLAG_ISPOINTER
;
proto
=
PyDict_GetItemString
(
typedict
,
"_type_"
);
/* Borrowed ref */
proto
=
PyDict_GetItemString
(
typedict
,
"_type_"
);
/* Borrowed ref */
if
(
proto
&&
-
1
==
PointerType_SetProto
(
stgdict
,
proto
))
{
if
(
proto
&&
-
1
==
PointerType_SetProto
(
stgdict
,
proto
))
{
...
@@ -1139,6 +1143,9 @@ ArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
...
@@ -1139,6 +1143,9 @@ ArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
itemalign
=
itemdict
->
align
;
itemalign
=
itemdict
->
align
;
if
(
itemdict
->
flags
&
(
TYPEFLAG_ISPOINTER
|
TYPEFLAG_HASPOINTER
))
stgdict
->
flags
|=
TYPEFLAG_HASPOINTER
;
stgdict
->
size
=
itemsize
*
length
;
stgdict
->
size
=
itemsize
*
length
;
stgdict
->
align
=
itemalign
;
stgdict
->
align
=
itemalign
;
stgdict
->
length
=
length
;
stgdict
->
length
=
length
;
...
@@ -1684,12 +1691,21 @@ SimpleType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
...
@@ -1684,12 +1691,21 @@ SimpleType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
switch
(
PyString_AS_STRING
(
proto
)[
0
])
{
switch
(
PyString_AS_STRING
(
proto
)[
0
])
{
case
'z'
:
/* c_char_p */
case
'z'
:
/* c_char_p */
ml
=
&
c_char_p_method
;
ml
=
&
c_char_p_method
;
stgdict
->
flags
|=
TYPEFLAG_ISPOINTER
;
break
;
break
;
case
'Z'
:
/* c_wchar_p */
case
'Z'
:
/* c_wchar_p */
ml
=
&
c_wchar_p_method
;
ml
=
&
c_wchar_p_method
;
stgdict
->
flags
|=
TYPEFLAG_ISPOINTER
;
break
;
break
;
case
'P'
:
/* c_void_p */
case
'P'
:
/* c_void_p */
ml
=
&
c_void_p_method
;
ml
=
&
c_void_p_method
;
stgdict
->
flags
|=
TYPEFLAG_ISPOINTER
;
break
;
case
'u'
:
case
'X'
:
case
'O'
:
ml
=
NULL
;
stgdict
->
flags
|=
TYPEFLAG_ISPOINTER
;
break
;
break
;
default:
default:
ml
=
NULL
;
ml
=
NULL
;
...
@@ -1926,7 +1942,7 @@ make_funcptrtype_dict(StgDictObject *stgdict)
...
@@ -1926,7 +1942,7 @@ make_funcptrtype_dict(StgDictObject *stgdict)
"class must define _flags_ which must be an integer"
);
"class must define _flags_ which must be an integer"
);
return
-
1
;
return
-
1
;
}
}
stgdict
->
flags
=
PyInt_AS_LONG
(
ob
);
stgdict
->
flags
=
PyInt_AS_LONG
(
ob
)
|
TYPEFLAG_ISPOINTER
;
/* _argtypes_ is optional... */
/* _argtypes_ is optional... */
ob
=
PyDict_GetItemString
((
PyObject
*
)
stgdict
,
"_argtypes_"
);
ob
=
PyDict_GetItemString
((
PyObject
*
)
stgdict
,
"_argtypes_"
);
...
@@ -2001,6 +2017,7 @@ CFuncPtrType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
...
@@ -2001,6 +2017,7 @@ CFuncPtrType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return
NULL
;
return
NULL
;
stgdict
->
paramfunc
=
CFuncPtrType_paramfunc
;
stgdict
->
paramfunc
=
CFuncPtrType_paramfunc
;
stgdict
->
flags
|=
TYPEFLAG_ISPOINTER
;
/* create the new instance (which is a class,
/* create the new instance (which is a class,
since we are a metatype!) */
since we are a metatype!) */
...
@@ -2255,6 +2272,45 @@ CData_nohash(PyObject *self)
...
@@ -2255,6 +2272,45 @@ CData_nohash(PyObject *self)
return
-
1
;
return
-
1
;
}
}
static
PyObject
*
CData_reduce
(
PyObject
*
_self
,
PyObject
*
args
)
{
CDataObject
*
self
=
(
CDataObject
*
)
_self
;
if
(
PyObject_stgdict
(
_self
)
->
flags
&
(
TYPEFLAG_ISPOINTER
|
TYPEFLAG_HASPOINTER
))
{
PyErr_SetString
(
PyExc_ValueError
,
"ctypes objects containing pointers cannot be pickled"
);
return
NULL
;
}
return
Py_BuildValue
(
"O(O(NN))"
,
_unpickle
,
Py_TYPE
(
_self
),
PyObject_GetAttrString
(
_self
,
"__dict__"
),
PyString_FromStringAndSize
(
self
->
b_ptr
,
self
->
b_size
));
}
static
PyObject
*
CData_setstate
(
PyObject
*
_self
,
PyObject
*
args
)
{
void
*
data
;
int
len
;
int
res
;
PyObject
*
dict
,
*
mydict
;
CDataObject
*
self
=
(
CDataObject
*
)
_self
;
if
(
!
PyArg_ParseTuple
(
args
,
"Os#"
,
&
dict
,
&
data
,
&
len
))
return
NULL
;
if
(
len
>
self
->
b_size
)
len
=
self
->
b_size
;
memmove
(
self
->
b_ptr
,
data
,
len
);
mydict
=
PyObject_GetAttrString
(
_self
,
"__dict__"
);
res
=
PyDict_Update
(
mydict
,
dict
);
Py_DECREF
(
mydict
);
if
(
res
==
-
1
)
return
NULL
;
Py_INCREF
(
Py_None
);
return
Py_None
;
}
/*
/*
* default __ctypes_from_outparam__ method returns self.
* default __ctypes_from_outparam__ method returns self.
*/
*/
...
@@ -2267,6 +2323,8 @@ CData_from_outparam(PyObject *self, PyObject *args)
...
@@ -2267,6 +2323,8 @@ CData_from_outparam(PyObject *self, PyObject *args)
static
PyMethodDef
CData_methods
[]
=
{
static
PyMethodDef
CData_methods
[]
=
{
{
"__ctypes_from_outparam__"
,
CData_from_outparam
,
METH_NOARGS
,
},
{
"__ctypes_from_outparam__"
,
CData_from_outparam
,
METH_NOARGS
,
},
{
"__reduce__"
,
CData_reduce
,
METH_NOARGS
,
},
{
"__setstate__"
,
CData_setstate
,
METH_VARARGS
,
},
{
NULL
,
NULL
},
{
NULL
,
NULL
},
};
};
...
@@ -5107,6 +5165,10 @@ init_ctypes(void)
...
@@ -5107,6 +5165,10 @@ init_ctypes(void)
if
(
!
m
)
if
(
!
m
)
return
;
return
;
_unpickle
=
PyObject_GetAttrString
(
m
,
"_unpickle"
);
if
(
_unpickle
==
NULL
)
return
;
if
(
PyType_Ready
(
&
PyCArg_Type
)
<
0
)
if
(
PyType_Ready
(
&
PyCArg_Type
)
<
0
)
return
;
return
;
...
...
Modules/_ctypes/callproc.c
Dosyayı görüntüle @
a06a1a88
...
@@ -1578,7 +1578,30 @@ resize(PyObject *self, PyObject *args)
...
@@ -1578,7 +1578,30 @@ resize(PyObject *self, PyObject *args)
return
Py_None
;
return
Py_None
;
}
}
static
PyObject
*
unpickle
(
PyObject
*
self
,
PyObject
*
args
)
{
PyObject
*
typ
;
PyObject
*
state
;
PyObject
*
result
;
PyObject
*
tmp
;
if
(
!
PyArg_ParseTuple
(
args
,
"OO"
,
&
typ
,
&
state
))
return
NULL
;
result
=
PyObject_CallMethod
(
typ
,
"__new__"
,
"O"
,
typ
);
if
(
result
==
NULL
)
return
NULL
;
tmp
=
PyObject_CallMethod
(
result
,
"__setstate__"
,
"O"
,
state
);
if
(
tmp
==
NULL
)
{
Py_DECREF
(
result
);
return
NULL
;
}
Py_DECREF
(
tmp
);
return
result
;
}
PyMethodDef
module_methods
[]
=
{
PyMethodDef
module_methods
[]
=
{
{
"_unpickle"
,
unpickle
,
METH_VARARGS
},
{
"resize"
,
resize
,
METH_VARARGS
,
"Resize the memory buffer of a ctypes instance"
},
{
"resize"
,
resize
,
METH_VARARGS
,
"Resize the memory buffer of a ctypes instance"
},
#ifdef CTYPES_UNICODE
#ifdef CTYPES_UNICODE
{
"set_conversion_mode"
,
set_conversion_mode
,
METH_VARARGS
,
set_conversion_mode_doc
},
{
"set_conversion_mode"
,
set_conversion_mode
,
METH_VARARGS
,
set_conversion_mode_doc
},
...
...
Modules/_ctypes/ctypes.h
Dosyayı görüntüle @
a06a1a88
...
@@ -286,6 +286,9 @@ PyObject *_CallProc(PPROC pProc,
...
@@ -286,6 +286,9 @@ PyObject *_CallProc(PPROC pProc,
#define FUNCFLAG_HRESULT 0x2
#define FUNCFLAG_HRESULT 0x2
#define FUNCFLAG_PYTHONAPI 0x4
#define FUNCFLAG_PYTHONAPI 0x4
#define TYPEFLAG_ISPOINTER 0x100
#define TYPEFLAG_HASPOINTER 0x200
#define DICTFLAG_FINAL 0x1000
#define DICTFLAG_FINAL 0x1000
struct
tagPyCArgObject
{
struct
tagPyCArgObject
{
...
...
Modules/_ctypes/stgdict.c
Dosyayı görüntüle @
a06a1a88
...
@@ -414,6 +414,8 @@ StructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct)
...
@@ -414,6 +414,8 @@ StructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct)
return
-
1
;
return
-
1
;
}
}
stgdict
->
ffi_type_pointer
.
elements
[
ffi_ofs
+
i
]
=
&
dict
->
ffi_type_pointer
;
stgdict
->
ffi_type_pointer
.
elements
[
ffi_ofs
+
i
]
=
&
dict
->
ffi_type_pointer
;
if
(
dict
->
flags
&
(
TYPEFLAG_ISPOINTER
|
TYPEFLAG_HASPOINTER
))
stgdict
->
flags
|=
TYPEFLAG_HASPOINTER
;
dict
->
flags
|=
DICTFLAG_FINAL
;
/* mark field type final */
dict
->
flags
|=
DICTFLAG_FINAL
;
/* mark field type final */
if
(
PyTuple_Size
(
pair
)
==
3
)
{
/* bits specified */
if
(
PyTuple_Size
(
pair
)
==
3
)
{
/* bits specified */
switch
(
dict
->
ffi_type_pointer
.
type
)
{
switch
(
dict
->
ffi_type_pointer
.
type
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment