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
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Gwenaël Samain
cython
Commits
8514f0f8
Commit
8514f0f8
authored
Oct 02, 2017
by
Robert Bradshaw
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'late_includes_auto'
parents
1c4f32b9
4592586d
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
113 additions
and
16 deletions
+113
-16
Cython/Compiler/Code.py
Cython/Compiler/Code.py
+1
-0
Cython/Compiler/ModuleNode.py
Cython/Compiler/ModuleNode.py
+18
-5
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+13
-3
Cython/Compiler/Symtab.py
Cython/Compiler/Symtab.py
+19
-8
docs/src/userguide/external_C_code.rst
docs/src/userguide/external_C_code.rst
+7
-0
tests/run/extern_include_order.srctree
tests/run/extern_include_order.srctree
+55
-0
No files found.
Cython/Compiler/Code.py
View file @
8514f0f8
...
...
@@ -985,6 +985,7 @@ class GlobalState(object):
'
global_var
',
'
string_decls
',
'
decls
',
'
late_includes
',
'
all_the_rest
',
'
pystring_table
',
'
cached_builtins
',
...
...
Cython/Compiler/ModuleNode.py
View file @
8514f0f8
...
...
@@ -90,7 +90,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
if
x
not
in
L1
:
L1
.
append
(
x
)
extend_if_not_in
(
self
.
scope
.
include_files
,
scope
.
include_files
)
extend_if_not_in
(
self
.
scope
.
include_files_early
,
scope
.
include_files_early
)
extend_if_not_in
(
self
.
scope
.
include_files_late
,
scope
.
include_files_late
)
extend_if_not_in
(
self
.
scope
.
included_files
,
scope
.
included_files
)
extend_if_not_in
(
self
.
scope
.
python_include_files
,
scope
.
python_include_files
)
...
...
@@ -362,6 +363,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code
.
putln
(
""
)
code
.
putln
(
"/* Implementation of '%s' */"
%
env
.
qualified_name
)
code
=
globalstate
[
'late_includes'
]
code
.
putln
(
"/* Late includes */"
)
self
.
generate_includes
(
env
,
modules
,
code
,
early
=
False
)
code
=
globalstate
[
'all_the_rest'
]
self
.
generate_cached_builtins_decls
(
env
,
code
)
...
...
@@ -653,7 +658,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code
.
putln
(
"#define %s"
%
Naming
.
h_guard_prefix
+
self
.
api_name
(
env
))
code
.
putln
(
"#define %s"
%
Naming
.
api_guard_prefix
+
self
.
api_name
(
env
))
self
.
generate_includes
(
env
,
cimported_modules
,
code
)
code
.
putln
(
"/* Early includes */"
)
self
.
generate_includes
(
env
,
cimported_modules
,
code
,
late
=
False
)
code
.
putln
(
""
)
code
.
putln
(
"#if defined(PYREX_WITHOUT_ASSERTIONS) && !defined(CYTHON_WITHOUT_ASSERTIONS)"
)
code
.
putln
(
"#define CYTHON_WITHOUT_ASSERTIONS"
)
...
...
@@ -727,15 +733,22 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code
.
putln
(
" #define DL_IMPORT(_T) _T"
)
code
.
putln
(
"#endif"
)
def
generate_includes
(
self
,
env
,
cimported_modules
,
code
):
def
generate_includes
(
self
,
env
,
cimported_modules
,
code
,
early
=
True
,
late
=
True
):
includes
=
[]
for
filename
in
env
.
include_files
:
if
early
:
includes
+=
env
.
include_files_early
if
late
:
includes
+=
[
include
for
include
in
env
.
include_files_late
if
include
not
in
env
.
include_files_early
]
for
filename
in
includes
:
byte_decoded_filenname
=
str
(
filename
)
if
byte_decoded_filenname
[
0
]
==
'<'
and
byte_decoded_filenname
[
-
1
]
==
'>'
:
code
.
putln
(
'#include %s'
%
byte_decoded_filenname
)
else
:
code
.
putln
(
'#include "%s"'
%
byte_decoded_filenname
)
if
early
:
code
.
putln_openmp
(
"#include <omp.h>"
)
def
generate_filename_table
(
self
,
code
):
...
...
Cython/Compiler/Nodes.py
View file @
8514f0f8
...
...
@@ -461,17 +461,27 @@ class StatNode(Node):
class
CDefExternNode
(
StatNode
):
# include_file string or None
# body StatNode
# body Stat
List
Node
child_attrs
=
[
"body"
]
def
analyse_declarations
(
self
,
env
):
if
self
.
include_file
:
env
.
add_include_file
(
self
.
include_file
)
old_cinclude_flag
=
env
.
in_cinclude
env
.
in_cinclude
=
1
self
.
body
.
analyse_declarations
(
env
)
env
.
in_cinclude
=
old_cinclude_flag
inc
=
self
.
include_file
if
inc
:
stats
=
self
.
body
.
stats
if
inc
[
0
]
==
'<'
and
inc
[
-
1
]
==
'>'
:
# System include => always early
env
.
add_include_file
(
inc
)
elif
stats
and
all
(
isinstance
(
node
,
CVarDefNode
)
for
node
in
stats
):
# Generate a late include if the body is not empty and
# all statements are variable or function declarations.
env
.
add_include_file
(
inc
,
late
=
True
)
else
:
env
.
add_include_file
(
inc
)
def
analyse_expressions
(
self
,
env
):
return
self
...
...
Cython/Compiler/Symtab.py
View file @
8514f0f8
...
...
@@ -1067,7 +1067,8 @@ class ModuleScope(Scope):
# doc_cname string C name of module doc string
# utility_code_list [UtilityCode] Queuing utility codes for forwarding to Code.py
# python_include_files [string] Standard Python headers to be included
# include_files [string] Other C headers to be included
# include_files_early [string] C headers to be included before Cython decls
# include_files_late [string] C headers to be included after Cython decls
# string_to_entry {string : Entry} Map string const to entry
# identifier_to_entry {string : Entry} Map identifier string const to entry
# context Context
...
...
@@ -1111,7 +1112,8 @@ class ModuleScope(Scope):
self
.
utility_code_list
=
[]
self
.
module_entries
=
{}
self
.
python_include_files
=
[
"Python.h"
]
self
.
include_files
=
[]
self
.
include_files_early
=
[]
self
.
include_files_late
=
[]
self
.
type_names
=
dict
(
outer_scope
.
type_names
)
self
.
pxd_file_loaded
=
0
self
.
cimported_modules
=
[]
...
...
@@ -1247,15 +1249,24 @@ class ModuleScope(Scope):
module
=
module
.
lookup_submodule
(
submodule
)
return
module
def
add_include_file
(
self
,
filename
):
if
filename
not
in
self
.
python_include_files
\
and
filename
not
in
self
.
include_files
:
self
.
include_files
.
append
(
filename
)
def
add_include_file
(
self
,
filename
,
late
=
False
):
if
filename
in
self
.
python_include_files
:
return
# Possibly, the same include appears both as early and as late
# include. We'll deal with this at code generation time.
if
late
:
incs
=
self
.
include_files_late
else
:
incs
=
self
.
include_files_early
if
filename
not
in
incs
:
incs
.
append
(
filename
)
def
add_imported_module
(
self
,
scope
):
if
scope
not
in
self
.
cimported_modules
:
for
filename
in
scope
.
include_files
:
self
.
add_include_file
(
filename
)
for
filename
in
scope
.
include_files_early
:
self
.
add_include_file
(
filename
,
late
=
False
)
for
filename
in
scope
.
include_files_late
:
self
.
add_include_file
(
filename
,
late
=
True
)
self
.
cimported_modules
.
append
(
scope
)
for
m
in
scope
.
cimported_modules
:
self
.
add_imported_module
(
m
)
...
...
docs/src/userguide/external_C_code.rst
View file @
8514f0f8
...
...
@@ -129,6 +129,13 @@ A few more tricks and tips:
cdef extern from *:
...
* If a ``cdef extern from "inc.h"`` block is not empty and contains only
function or variable declarations (and no type declarations of any kind),
Cython will put the ``#include "inc.h"`` statement after all
declarations generated by Cython. This means that the included file
has access to the variables, functions, structures, ... which are
declared by Cython.
Implementing functions in C
---------------------------
...
...
tests/run/extern_include_order.srctree
0 → 100644
View file @
8514f0f8
PYTHON setup.py build_ext --inplace
PYTHON -c "import a"
PYTHON -c "import b"
######## setup.py ########
from Cython.Build import cythonize
from distutils.core import setup
setup(
ext_modules = cythonize("*.pyx"),
)
######## a.pxd ########
cdef extern from "a_early.h":
ctypedef int my_int
cdef extern from "a_late.h":
my_int square_value_plus_one()
cdef my_int my_value "my_value"
cdef my_int square "square"(my_int x)
######## a.pyx ########
my_value = 10
cdef my_int square "square"(my_int x):
return x * x
assert square_value_plus_one() == 101
# Square must be explicitly used for its proto to be generated.
cdef my_int use_square(x):
return square(x)
######## a_early.h ########
typedef int my_int;
######## a_late.h ########
static my_int square_value_plus_one() {
return square(my_value) + 1;
}
######## b.pyx ########
cimport a
# Likewise, a.square must be explicitly used.
assert a.square(a.my_value) + 1 == 101
assert a.square_value_plus_one() == 101
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