Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
nexedi
cython
Commits
8d727b67
Commit
8d727b67
authored
Jun 25, 2017
by
scoder
Committed by
GitHub
Jun 25, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into feature/pythran
parents
8705f0fa
4f857124
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
256 additions
and
68 deletions
+256
-68
Cython/Build/Dependencies.py
Cython/Build/Dependencies.py
+40
-9
Cython/Compiler/FusedNode.py
Cython/Compiler/FusedNode.py
+20
-15
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+3
-1
Cython/Compiler/ParseTreeTransforms.py
Cython/Compiler/ParseTreeTransforms.py
+11
-1
Cython/Compiler/PyrexTypes.py
Cython/Compiler/PyrexTypes.py
+14
-7
Cython/Compiler/Symtab.py
Cython/Compiler/Symtab.py
+2
-1
Cython/Shadow.py
Cython/Shadow.py
+1
-1
Cython/Utility/CConvert.pyx
Cython/Utility/CConvert.pyx
+4
-4
Cython/Utility/CppConvert.pyx
Cython/Utility/CppConvert.pyx
+3
-3
Cython/Utility/ImportExport.c
Cython/Utility/ImportExport.c
+38
-0
Cython/Utility/TypeConversion.c
Cython/Utility/TypeConversion.c
+11
-6
docs/src/userguide/external_C_code.rst
docs/src/userguide/external_C_code.rst
+32
-12
tests/errors/cmethbasematch.pxd
tests/errors/cmethbasematch.pxd
+3
-0
tests/errors/cmethbasematch.pyx
tests/errors/cmethbasematch.pyx
+5
-0
tests/run/cimport_from_sys_path.srctree
tests/run/cimport_from_sys_path.srctree
+9
-2
tests/run/cyfunction.pyx
tests/run/cyfunction.pyx
+44
-0
tests/run/fused_cpdef.pyx
tests/run/fused_cpdef.pyx
+6
-0
tests/run/fused_def.pyx
tests/run/fused_def.pyx
+6
-2
tests/run/numpy_test.pyx
tests/run/numpy_test.pyx
+4
-4
No files found.
Cython/Build/Dependencies.py
View file @
8d727b67
...
...
@@ -390,14 +390,30 @@ def normalize_existing(base_path, rel_paths):
@
cached_function
def
normalize_existing0
(
base_dir
,
rel_paths
):
"""
Given some base directory ``base_dir`` and a list of path names
``rel_paths``, normalize each relative path name ``rel`` by
replacing it by ``os.path.join(base, rel)`` if that file exists.
Return a couple ``(normalized, needed_base)`` where ``normalized``
if the list of normalized file names and ``needed_base`` is
``base_dir`` if we actually needed ``base_dir``. If no paths were
changed (for example, if all paths were already absolute), then
``needed_base`` is ``None``.
"""
normalized
=
[]
needed_base
=
None
for
rel
in
rel_paths
:
if
os
.
path
.
isabs
(
rel
):
normalized
.
append
(
rel
)
continue
path
=
join_path
(
base_dir
,
rel
)
if
path_exists
(
path
):
normalized
.
append
(
os
.
path
.
normpath
(
path
))
needed_base
=
base_dir
else
:
normalized
.
append
(
rel
)
return
normalized
return
(
normalized
,
needed_base
)
def
resolve_depends
(
depends
,
include_dirs
):
...
...
@@ -498,20 +514,25 @@ class DependencyTree(object):
return
all
@
cached_method
def
cimports_
and_extern
s
(
self
,
filename
):
def
cimports_
externs_incdir
s
(
self
,
filename
):
# This is really ugly. Nested cimports are resolved with respect to the
# includer, but includes are resolved with respect to the includee.
cimports
,
includes
,
externs
=
self
.
parse_dependencies
(
filename
)[:
3
]
cimports
=
set
(
cimports
)
externs
=
set
(
externs
)
incdirs
=
set
()
for
include
in
self
.
included_files
(
filename
):
included_cimports
,
included_externs
=
self
.
cimports_and_extern
s
(
include
)
included_cimports
,
included_externs
,
included_incdirs
=
self
.
cimports_externs_incdir
s
(
include
)
cimports
.
update
(
included_cimports
)
externs
.
update
(
included_externs
)
return
tuple
(
cimports
),
normalize_existing
(
filename
,
externs
)
incdirs
.
update
(
included_incdirs
)
externs
,
incdir
=
normalize_existing
(
filename
,
externs
)
if
incdir
:
incdirs
.
add
(
incdir
)
return
tuple
(
cimports
),
externs
,
incdirs
def
cimports
(
self
,
filename
):
return
self
.
cimports_
and_extern
s
(
filename
)[
0
]
return
self
.
cimports_
externs_incdir
s
(
filename
)[
0
]
def
package
(
self
,
filename
):
return
package
(
filename
)
...
...
@@ -594,12 +615,22 @@ class DependencyTree(object):
def
distutils_info0
(
self
,
filename
):
info
=
self
.
parse_dependencies
(
filename
)[
3
]
externs
=
self
.
cimports_and_externs
(
filename
)[
1
]
kwds
=
info
.
values
cimports
,
externs
,
incdirs
=
self
.
cimports_externs_incdirs
(
filename
)
# Add dependencies on "cdef extern from ..." files
if
externs
:
if
'depends'
in
info
.
value
s
:
info
.
values
[
'depends'
]
=
list
(
set
(
info
.
value
s
[
'depends'
]).
union
(
externs
))
if
'depends'
in
kwd
s
:
kwds
[
'depends'
]
=
list
(
set
(
kwd
s
[
'depends'
]).
union
(
externs
))
else
:
info
.
values
[
'depends'
]
=
list
(
externs
)
kwds
[
'depends'
]
=
list
(
externs
)
# Add include_dirs to ensure that the C compiler will find the
# "cdef extern from ..." files
if
incdirs
:
include_dirs
=
list
(
kwds
.
get
(
'include_dirs'
,
[]))
for
inc
in
incdirs
:
if
inc
not
in
include_dirs
:
include_dirs
.
append
(
inc
)
kwds
[
'include_dirs'
]
=
include_dirs
return
info
def
distutils_info
(
self
,
filename
,
aliases
=
None
,
base
=
None
):
...
...
Cython/Compiler/FusedNode.py
View file @
8d727b67
...
...
@@ -477,11 +477,7 @@ class FusedCFuncDefNode(StatListNode):
pyx_code
.
imports
.
put_chunk
(
u"""
cdef type ndarray
try:
import numpy
ndarray = numpy.ndarray
except (ImportError, AttributeError, TypeError):
ndarray = None
ndarray = __Pyx_ImportNumPyArrayTypeIfAvailable()
"""
)
seen_int_dtypes
=
set
()
...
...
@@ -540,13 +536,18 @@ class FusedCFuncDefNode(StatListNode):
# PROCESSING ARGUMENT {{arg_tuple_idx}}
if {{arg_tuple_idx}} < len(<tuple>args):
arg = (<tuple>args)[{{arg_tuple_idx}}]
elif '{{arg.name}}' in <dict>kwargs:
elif
kwargs is not None and
'{{arg.name}}' in <dict>kwargs:
arg = (<dict>kwargs)['{{arg.name}}']
else:
{{if arg.default}}
arg = (<tuple>defaults)[{{default_idx}}]
{{else}}
raise TypeError("Expected at least %d arguments" % len(<tuple>args))
{{if arg_tuple_idx < min_positional_args}}
raise TypeError("Expected at least %d argument%s, got %d" % (
{{min_positional_args}}, {{'"s"' if min_positional_args != 1 else '""'}}, len(<tuple>args)))
{{else}}
raise TypeError("Missing keyword-only argument: '%s'" % "{{arg.default}}")
{{endif}}
{{endif}}
"""
)
...
...
@@ -568,6 +569,10 @@ class FusedCFuncDefNode(StatListNode):
'memviewslice_cname'
:
MemoryView
.
memviewslice_cname
,
'func_args'
:
self
.
node
.
args
,
'n_fused'
:
len
(
fused_types
),
'min_positional_args'
:
self
.
node
.
num_required_args
-
self
.
node
.
num_required_kw_args
if
is_def
else
sum
(
1
for
arg
in
self
.
node
.
args
if
arg
.
default
is
None
),
'name'
:
orig_py_func
.
entry
.
name
,
}
...
...
@@ -577,14 +582,11 @@ class FusedCFuncDefNode(StatListNode):
u"""
cdef extern from *:
void __pyx_PyErr_Clear "PyErr_Clear" ()
type __Pyx_ImportNumPyArrayTypeIfAvailable()
int __Pyx_Is_Little_Endian()
"""
)
decl_code
.
indent
()
pyx_code
.
put_chunk
(
u"""
from __future__ import absolute_import # for later numpy import
"""
)
pyx_code
.
put_chunk
(
u"""
def __pyx_fused_cpdef(signatures, args, kwargs, defaults):
...
...
@@ -593,8 +595,8 @@ class FusedCFuncDefNode(StatListNode):
dest_sig = [None] * {{n_fused}}
if kwargs is
None
:
kwargs =
{}
if kwargs is
not None and not kwargs
:
kwargs =
None
cdef Py_ssize_t i
...
...
@@ -655,15 +657,18 @@ class FusedCFuncDefNode(StatListNode):
if
all_buffer_types
:
self
.
_buffer_declarations
(
pyx_code
,
decl_code
,
all_buffer_types
)
env
.
use_utility_code
(
Code
.
UtilityCode
.
load_cached
(
"Import"
,
"ImportExport.c"
))
env
.
use_utility_code
(
Code
.
UtilityCode
.
load_cached
(
"ImportNumPyArray"
,
"ImportExport.c"
))
pyx_code
.
put_chunk
(
u"""
candidates = []
for sig in <dict>signatures:
match_found = False
for src_type, dst_type in zip(sig.strip('()').split('|'), dest_sig):
src_sig = sig.strip('()').split('|')
for i in range(len(dest_sig)):
dst_type = dest_sig[i]
if dst_type is not None:
if src_
type
== dst_type:
if src_
sig[i]
== dst_type:
match_found = True
else:
match_found = False
...
...
Cython/Compiler/Nodes.py
View file @
8d727b67
...
...
@@ -2649,6 +2649,9 @@ class DefNode(FuncDefNode):
child_attrs
=
[
"args"
,
"star_arg"
,
"starstar_arg"
,
"body"
,
"decorators"
,
"return_type_annotation"
]
is_staticmethod
=
False
is_classmethod
=
False
lambda_name
=
None
reqd_kw_flags_cname
=
"0"
is_wrapper
=
0
...
...
@@ -2761,7 +2764,6 @@ class DefNode(FuncDefNode):
return
True
def
analyse_declarations
(
self
,
env
):
self
.
is_classmethod
=
self
.
is_staticmethod
=
False
if
self
.
decorators
:
for
decorator
in
self
.
decorators
:
func
=
decorator
.
decorator
...
...
Cython/Compiler/ParseTreeTransforms.py
View file @
8d727b67
...
...
@@ -1355,8 +1355,18 @@ class DecoratorTransform(ScopeTrackingTransform, SkipDeclarations):
return
self
.
_reject_decorated_property
(
node
,
decorator_node
)
return
self
.
_add_to_property
(
properties
,
node
,
handler_name
,
decorator_node
)
# we clear node.decorators, so we need to set the
# is_staticmethod/is_classmethod attributes now
for
decorator
in
node
.
decorators
:
func
=
decorator
.
decorator
if
func
.
is_name
:
node
.
is_classmethod
|=
func
.
name
==
'classmethod'
node
.
is_staticmethod
|=
func
.
name
==
'staticmethod'
# transform normal decorators
return
self
.
chain_decorators
(
node
,
node
.
decorators
,
node
.
name
)
decs
=
node
.
decorators
node
.
decorators
=
None
return
self
.
chain_decorators
(
node
,
decs
,
node
.
name
)
@
staticmethod
def
_reject_decorated_property
(
node
,
decorator_node
):
...
...
Cython/Compiler/PyrexTypes.py
View file @
8d727b67
...
...
@@ -2208,15 +2208,17 @@ class CPointerBaseType(CType):
if
base_type
.
signed
==
2
:
self
.
to_py_function
=
"__Pyx_PyObject_FromCString"
if
self
.
is_ptr
:
self
.
from_py_function
=
"__Pyx_PyObject_AsSString"
self
.
from_py_function
=
"__Pyx_PyObject_As
%s
SString"
elif
base_type
.
signed
:
self
.
to_py_function
=
"__Pyx_PyObject_FromString"
if
self
.
is_ptr
:
self
.
from_py_function
=
"__Pyx_PyObject_AsString"
self
.
from_py_function
=
"__Pyx_PyObject_As
%s
String"
else
:
self
.
to_py_function
=
"__Pyx_PyObject_FromCString"
if
self
.
is_ptr
:
self
.
from_py_function
=
"__Pyx_PyObject_AsUString"
self
.
from_py_function
=
"__Pyx_PyObject_As%sUString"
if
self
.
is_ptr
:
self
.
from_py_function
%=
''
if
self
.
base_type
.
is_const
else
'Writable'
self
.
exception_value
=
"NULL"
elif
self
.
is_pyunicode_ptr
and
not
base_type
.
is_error
:
self
.
to_py_function
=
"__Pyx_PyUnicode_FromUnicode"
...
...
@@ -2596,7 +2598,7 @@ class CFuncType(CType):
return
self
.
same_c_signature_as_resolved_type
(
other_type
.
resolve
(),
as_cmethod
)
def
same_c_signature_as_resolved_type
(
self
,
other_type
,
as_cmethod
=
0
):
def
same_c_signature_as_resolved_type
(
self
,
other_type
,
as_cmethod
=
0
,
as_pxd_definition
=
0
):
#print "CFuncType.same_c_signature_as_resolved_type:", \
# self, other_type, "as_cmethod =", as_cmethod ###
if
other_type
is
error_type
:
...
...
@@ -2618,8 +2620,13 @@ class CFuncType(CType):
return
0
if
self
.
optional_arg_count
!=
other_type
.
optional_arg_count
:
return
0
if
not
self
.
return_type
.
same_as
(
other_type
.
return_type
):
return
0
if
as_pxd_definition
:
# A narrowing of the return type declared in the pxd is allowed.
if
not
self
.
return_type
.
subtype_of_resolved_type
(
other_type
.
return_type
):
return
0
else
:
if
not
self
.
return_type
.
same_as
(
other_type
.
return_type
):
return
0
if
not
self
.
same_calling_convention_as
(
other_type
):
return
0
if
self
.
exception_check
!=
other_type
.
exception_check
:
...
...
@@ -3238,7 +3245,7 @@ class CStructOrUnionType(CType):
return
False
context
=
dict
(
struct_
name
=
self
.
name
,
struct_
type
=
self
,
var_entries
=
self
.
scope
.
var_entries
,
funcname
=
self
.
from_py_function
,
)
...
...
Cython/Compiler/Symtab.py
View file @
8d727b67
...
...
@@ -2098,7 +2098,8 @@ class CClassScope(ClassScope):
# Fix with_gil vs nogil.
entry
.
type
=
entry
.
type
.
with_with_gil
(
type
.
with_gil
)
elif
type
.
compatible_signature_with
(
entry
.
type
,
as_cmethod
=
1
)
and
type
.
nogil
==
entry
.
type
.
nogil
:
if
self
.
defined
and
not
in_pxd
:
if
(
self
.
defined
and
not
in_pxd
and
not
type
.
same_c_signature_as_resolved_type
(
entry
.
type
,
as_cmethod
=
1
,
as_pxd_definition
=
1
)):
error
(
pos
,
"Compatible but non-identical C method '%s' not redeclared "
"in definition part of extension type '%s'"
%
(
name
,
self
.
class_name
))
...
...
Cython/Shadow.py
View file @
8d727b67
# cython.* namespace for pure mode.
from
__future__
import
absolute_import
__version__
=
"0.2
5.2
"
__version__
=
"0.2
6.alpha0
"
try
:
from
__builtin__
import
basestring
...
...
Cython/Utility/CConvert.pyx
View file @
8d727b67
...
...
@@ -8,8 +8,8 @@ cdef extern from *:
object
PyErr_Format
(
exc
,
const
char
*
format
,
...)
@
cname
(
"{{funcname}}"
)
cdef
{{
struct_
nam
e
}}
{{
funcname
}}(
obj
)
except
*
:
cdef
{{
struct_
nam
e
}}
result
cdef
{{
struct_
typ
e
}}
{{
funcname
}}(
obj
)
except
*
:
cdef
{{
struct_
typ
e
}}
result
if
not
PyMapping_Check
(
obj
):
PyErr_Format
(
TypeError
,
b"Expected %.16s, got %.200s"
,
b"a mapping"
,
Py_TYPE
(
obj
).
tp_name
)
...
...
@@ -33,8 +33,8 @@ cdef extern from *:
object
PyErr_Format
(
exc
,
const
char
*
format
,
...)
@
cname
(
"{{funcname}}"
)
cdef
{{
struct_
nam
e
}}
{{
funcname
}}(
obj
)
except
*
:
cdef
{{
struct_
nam
e
}}
result
cdef
{{
struct_
typ
e
}}
{{
funcname
}}(
obj
)
except
*
:
cdef
{{
struct_
typ
e
}}
result
cdef
Py_ssize_t
length
if
not
PyMapping_Check
(
obj
):
PyErr_Format
(
TypeError
,
b"Expected %.16s, got %.200s"
,
b"a mapping"
,
Py_TYPE
(
obj
).
tp_name
)
...
...
Cython/Utility/CppConvert.pyx
View file @
8d727b67
...
...
@@ -7,12 +7,12 @@ cdef extern from *:
cdef
cppclass
string
"{{type}}"
:
string
()
string
(
char
*
c_str
,
size_t
size
)
cdef
char
*
__Pyx_PyObject_AsStringAndSize
(
object
,
Py_ssize_t
*
)
except
NULL
cdef
c
onst
c
har
*
__Pyx_PyObject_AsStringAndSize
(
object
,
Py_ssize_t
*
)
except
NULL
@
cname
(
"{{cname}}"
)
cdef
string
{{
cname
}}(
object
o
)
except
*
:
cdef
Py_ssize_t
length
cdef
char
*
data
=
__Pyx_PyObject_AsStringAndSize
(
o
,
&
length
)
cdef
c
onst
c
har
*
data
=
__Pyx_PyObject_AsStringAndSize
(
o
,
&
length
)
return
string
(
data
,
length
)
...
...
@@ -27,7 +27,7 @@ cdef extern from *:
{{
for
py_type
in
[
'PyObject'
,
'PyUnicode'
,
'PyStr'
,
'PyBytes'
,
'PyByteArray'
]}}
cdef
extern
from
*
:
cdef
object
__Pyx_
{{
py_type
}}
_FromStringAndSize
(
char
*
,
size_t
)
cdef
object
__Pyx_
{{
py_type
}}
_FromStringAndSize
(
c
onst
c
har
*
,
size_t
)
@
cname
(
"{{cname.replace("
PyObject
", py_type, 1)}}"
)
cdef
inline
object
{{
cname
.
replace
(
"PyObject"
,
py_type
,
1
)}}(
const
string
&
s
):
...
...
Cython/Utility/ImportExport.c
View file @
8d727b67
...
...
@@ -661,3 +661,41 @@ bad:
Py_XDECREF
(
ob
);
return
NULL
;
}
/////////////// ImportNumPyArray.proto ///////////////
static
PyObject
*
__pyx_numpy_ndarray
=
NULL
;
static
PyObject
*
__Pyx_ImportNumPyArrayTypeIfAvailable
(
void
);
/*proto*/
/////////////// ImportNumPyArray.cleanup ///////////////
Py_CLEAR
(
__pyx_numpy_ndarray
);
/////////////// ImportNumPyArray ///////////////
//@requires: ImportExport.c::Import
static
PyObject
*
__Pyx__ImportNumPyArray
(
void
)
{
PyObject
*
numpy_module
,
*
ndarray_object
=
NULL
;
numpy_module
=
__Pyx_Import
(
PYIDENT
(
"numpy"
),
NULL
,
0
);
if
(
likely
(
numpy_module
))
{
ndarray_object
=
PyObject_GetAttrString
(
numpy_module
,
"ndarray"
);
}
if
(
unlikely
(
!
ndarray_object
))
{
// ImportError, AttributeError, ...
PyErr_Clear
();
}
if
(
unlikely
(
!
ndarray_object
||
!
PyObject_TypeCheck
(
ndarray_object
,
&
PyType_Type
)))
{
Py_XDECREF
(
ndarray_object
);
Py_INCREF
(
Py_None
);
ndarray_object
=
Py_None
;
}
return
ndarray_object
;
}
static
CYTHON_INLINE
PyObject
*
__Pyx_ImportNumPyArrayTypeIfAvailable
(
void
)
{
if
(
unlikely
(
!
__pyx_numpy_ndarray
))
{
__pyx_numpy_ndarray
=
__Pyx__ImportNumPyArray
();
}
return
__pyx_numpy_ndarray
;
}
Cython/Utility/TypeConversion.c
View file @
8d727b67
...
...
@@ -37,8 +37,8 @@
#define __Pyx_sst_abs(value) ((value<0) ? -value : value)
#endif
static
CYTHON_INLINE
char
*
__Pyx_PyObject_AsString
(
PyObject
*
);
static
CYTHON_INLINE
char
*
__Pyx_PyObject_AsStringAndSize
(
PyObject
*
,
Py_ssize_t
*
length
);
static
CYTHON_INLINE
c
onst
c
har
*
__Pyx_PyObject_AsString
(
PyObject
*
);
static
CYTHON_INLINE
c
onst
c
har
*
__Pyx_PyObject_AsStringAndSize
(
PyObject
*
,
Py_ssize_t
*
length
);
#define __Pyx_PyByteArray_FromString(s) PyByteArray_FromStringAndSize((const char*)s, strlen((const char*)s))
#define __Pyx_PyByteArray_FromStringAndSize(s, l) PyByteArray_FromStringAndSize((const char*)s, l)
...
...
@@ -54,8 +54,11 @@ static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*);
#define __Pyx_PyStr_FromStringAndSize __Pyx_PyUnicode_FromStringAndSize
#endif
#define __Pyx_PyObject_AsSString(s) ((signed char*) __Pyx_PyObject_AsString(s))
#define __Pyx_PyObject_AsUString(s) ((unsigned char*) __Pyx_PyObject_AsString(s))
#define __Pyx_PyObject_AsWritableString(s) ((char*) __Pyx_PyObject_AsString(s))
#define __Pyx_PyObject_AsWritableSString(s) ((signed char*) __Pyx_PyObject_AsString(s))
#define __Pyx_PyObject_AsWritableUString(s) ((unsigned char*) __Pyx_PyObject_AsString(s))
#define __Pyx_PyObject_AsSString(s) ((const signed char*) __Pyx_PyObject_AsString(s))
#define __Pyx_PyObject_AsUString(s) ((const unsigned char*) __Pyx_PyObject_AsString(s))
#define __Pyx_PyObject_FromCString(s) __Pyx_PyObject_FromString((const char*)s)
#define __Pyx_PyBytes_FromCString(s) __Pyx_PyBytes_FromString((const char*)s)
#define __Pyx_PyByteArray_FromCString(s) __Pyx_PyByteArray_FromString((const char*)s)
...
...
@@ -189,12 +192,14 @@ static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char* c_str) {
return
__Pyx_PyUnicode_FromStringAndSize
(
c_str
,
(
Py_ssize_t
)
strlen
(
c_str
));
}
static
CYTHON_INLINE
char
*
__Pyx_PyObject_AsString
(
PyObject
*
o
)
{
// Py3.7 returns a "const char*" for unicode strings
static
CYTHON_INLINE
const
char
*
__Pyx_PyObject_AsString
(
PyObject
*
o
)
{
Py_ssize_t
ignore
;
return
__Pyx_PyObject_AsStringAndSize
(
o
,
&
ignore
);
}
static
CYTHON_INLINE
char
*
__Pyx_PyObject_AsStringAndSize
(
PyObject
*
o
,
Py_ssize_t
*
length
)
{
// Py3.7 returns a "const char*" for unicode strings
static
CYTHON_INLINE
const
char
*
__Pyx_PyObject_AsStringAndSize
(
PyObject
*
o
,
Py_ssize_t
*
length
)
{
#if CYTHON_COMPILING_IN_CPYTHON && (__PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT)
if
(
#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII
...
...
docs/src/userguide/external_C_code.rst
View file @
8d727b67
...
...
@@ -339,42 +339,57 @@ Public Declarations
---------------------
You can make C types, variables and functions defined in a Cython module
accessible to C code that is linked
with the module, by declaring them with
the public keyword::
accessible to C code that is linked
together with the Cython-generated C file,
by declaring them with
the public keyword::
cdef public struct Bunny: # public type declaration
int vorpalness
cdef public int spam # public variable declaration
cdef public void grail(Bunny *): # public function declaration
print "Ready the holy hand grenade"
cdef public void grail(Bunny *) # public function declaration
If there are any public declarations in a Cython module, a header file called
:file:`modulename.h` file is generated containing equivalent C declarations for
inclusion in other C code.
Users who are embedding Python in C with Cython need to make sure to call Py_Initialize()
and Py_Finalize(). For example, in the following snippet that includes :file:`modulename.h`::
A typical use case for this is building an extension module from multiple
C sources, one of them being Cython generated (i.e. with something like
``Extension("grail", sources=["grail.pyx", "grail_helper.c"])`` in ``setup.py``.
In this case, the file ``grail_helper.c`` just needs to add
``#include "grail.h"`` in order to access the public Cython variables.
A more advanced use case is embedding Python in C using Cython.
In this case, make sure to call Py_Initialize() and Py_Finalize().
For example, in the following snippet that includes :file:`grail.h`:
.. code-block:: c
#include <Python.h>
#include "
modulename
.h"
#include "
grail
.h"
void grail
() {
int main
() {
Py_Initialize();
init
modulename
();
init
grail
();
Bunny b;
grail(b);
Py_Finalize();
}
Any C code wanting to make use of these declarations will need to be linked,
either statically or dynamically, with the extension module
.
This C code can then be built together with the Cython-generated C code
in a single program (or library)
.
If the Cython module resides within a package, then the name of the ``.h``
file consists of the full dotted name of the module, e.g. a module called
:mod:`foo.spam` would have a header file called :file:`foo.spam.h`.
.. NOTE::
On some operating systems like Linux, it is also possible to first
build the Cython extension in the usual way and then link against
the resulting ``.so`` file like a dynamic library.
Beware that this is not portable, so it should be avoided.
.. _api:
C API Declarations
...
...
@@ -418,10 +433,12 @@ made available when you include :file:`modulename_api.h`.::
Vehicle car;
int main(int argc, char *argv[]) {
Py_Initialize();
import_delorean();
car.speed = atoi(argv[1]);
car.power = atof(argv[2]);
activate(&car);
Py_Finalize();
}
.. note::
...
...
@@ -434,7 +451,10 @@ made available when you include :file:`modulename_api.h`.::
Using the :keyword:`api` method does not require the C code using the
declarations to be linked with the extension module in any way, as the Python
import machinery is used to make the connection dynamically. However, only
functions can be accessed this way, not variables.
functions can be accessed this way, not variables. Note also that for the
module import mechanism to be set up correctly, the user must call
Py_Initialize() and Py_Finalize(); if you experience a segmentation fault in
the call to :func:`import_modulename`, it is likely that this wasn't done.
You can use both :keyword:`public` and :keyword:`api` on the same function to
make it available by both methods, e.g.::
...
...
tests/errors/cmethbasematch.pxd
View file @
8d727b67
...
...
@@ -6,3 +6,6 @@ cdef class MissingRedeclaration(Base):
cdef
class
BadRedeclaration
(
Base
):
cdef
f
(
self
)
cdef
class
NarrowerReturn
(
Base
):
pass
tests/errors/cmethbasematch.pyx
View file @
8d727b67
...
...
@@ -28,6 +28,11 @@ cdef class UnneededRedeclaration(Base):
cpdef
f
(
self
):
pass
cdef
class
NarrowerReturn
(
Base
):
# This does not require a new vtable entry.
cdef
Base
f
(
self
):
pass
_ERRORS
=
u"""
8: 9: Signature not compatible with previous declaration
...
...
tests/run/cimport_from_sys_path.srctree
View file @
8d727b67
...
...
@@ -19,8 +19,15 @@ setup(
######## site-packages/b/other.pxd ########
cdef inline foo(int a):
return a**2
cdef extern from "foo.c":
int foo(int)
######## site-packages/b/foo.c ########
static int foo(int a)
{
return a * a;
}
######## a.pyx ########
...
...
tests/run/cyfunction.pyx
View file @
8d727b67
...
...
@@ -304,3 +304,47 @@ def test_annotations(a: "test", b: "other" = 2, c: 123 = 4) -> "ret":
def
inner
(
x
:
"banana"
,
y
:
b
())
->
c
():
return
x
,
y
return
inner
def
add_one
(
func
):
"Decorator to add 1 to the last argument of the function call"
def
inner
(
*
args
):
args
=
args
[:
-
1
]
+
(
args
[
-
1
]
+
1
,)
return
func
(
*
args
)
return
inner
@
add_one
def
test_decorated
(
x
):
"""
>>> test_decorated(0)
1
"""
return
x
@
add_one
@
add_one
def
test_decorated2
(
x
):
"""
>>> test_decorated2(0)
2
"""
return
x
cdef
class
TestDecoratedMethods
:
@
add_one
def
test
(
self
,
x
):
"""
>>> TestDecoratedMethods().test(0)
1
"""
return
x
@
add_one
@
add_one
def
test2
(
self
,
x
):
"""
>>> TestDecoratedMethods().test2(0)
2
"""
return
x
tests/run/fused_cpdef.pyx
View file @
8d727b67
...
...
@@ -94,6 +94,12 @@ def test_multiarg():
x is an int, y is a float: 1 2.0
x is an int, y is a float: 1 2.0
x is a long, y is a double: 4 5.0
>>> multiarg()
Traceback (most recent call last):
TypeError: Expected at least 2 arguments, got 0
>>> multiarg(1, 2.0, 3) # doctest: +ELLIPSIS
Traceback (most recent call last):
TypeError: ...2...arg...3...
"""
multiarg
[
int
,
float
](
1
,
2.0
)
multiarg
[
cy
.
int
,
cy
.
float
](
1
,
2.0
)
...
...
tests/run/fused_def.pyx
View file @
8d727b67
...
...
@@ -105,11 +105,15 @@ def opt_func(fused_t obj, cython.floating myf = 1.2, cython.integral myi = 7):
>>> opt_func(object(), f)
Traceback (most recent call last):
...
TypeError: Function call with ambiguous argument types
>>> opt_func()
Traceback (most recent call last):
TypeError: Expected at least 1 argument, got 0
>>> opt_func("abc", f, i, 5) # doctest: +ELLIPSIS
Traceback (most recent call last):
TypeError: ...at most 3...
>>> opt_func[ExtClassA, cy.float, cy.long](object(), f)
Traceback (most recent call last):
...
TypeError: Argument 'obj' has incorrect type (expected fused_def.ExtClassA, got object)
"""
print
cython
.
typeof
(
obj
),
cython
.
typeof
(
myf
),
cython
.
typeof
(
myi
)
...
...
tests/run/numpy_test.pyx
View file @
8d727b67
...
...
@@ -181,8 +181,8 @@ try:
>>> print(test_nested_dtypes(np.zeros((3,), dtype=np.dtype([
\
('a', np.dtype('i,i')),
\
('b', np.dtype('i,i'))
\
]))))
array([((0, 0), (0, 0)), ((1, 2), (1, 4)), ((1, 2), (1, 4))],
]))))
# doctest: +NORMALIZE_WHITESPACE
array([((0, 0), (0, 0)), ((1, 2), (1, 4)), ((1, 2), (1, 4))],
dtype=[('a', [('f0', '!i4'), ('f1', '!i4')]), ('b', [('f0', '!i4'), ('f1', '!i4')])])
>>> print(test_nested_dtypes(np.zeros((3,), dtype=np.dtype([
\
...
...
@@ -234,8 +234,8 @@ try:
1,1
8,16
>>> test_point_record()
array([(0., 0.), (1., -1.), (2., -2.)],
>>> test_point_record()
# doctest: +NORMALIZE_WHITESPACE
array([(0., 0.), (1., -1.), (2., -2.)],
dtype=[('x', '!f8'), ('y', '!f8')])
"""
...
...
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