Commit 3f83a9b3 authored by Stefan Behnel's avatar Stefan Behnel

merge

parents 329fe5e8 287b5d83
......@@ -757,8 +757,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
def generate_cfunction_predeclarations(self, env, code, definition):
for entry in env.cfunc_entries:
if not entry.in_cinclude and (definition
or entry.defined_in_pxd or entry.visibility == 'extern'):
if entry.inline_func_in_pxd or (not entry.in_cinclude and (definition
or entry.defined_in_pxd or entry.visibility == 'extern')):
if entry.visibility in ('public', 'extern'):
dll_linkage = "DL_EXPORT"
else:
......
......@@ -1212,9 +1212,12 @@ class CFuncDefNode(FuncDefNode):
# type CFuncType
# py_func wrapper for calling from Python
# overridable whether or not this is a cpdef function
# inline_in_pxd whether this is an inline function in a pxd file
child_attrs = ["base_type", "declarator", "body", "py_func"]
inline_in_pxd = False
def unqualified_name(self):
return self.entry.name
......@@ -1251,6 +1254,7 @@ class CFuncDefNode(FuncDefNode):
cname = cname, visibility = self.visibility,
defining = self.body is not None,
api = self.api, modifiers = self.modifiers)
self.entry.inline_func_in_pxd = self.inline_in_pxd
self.return_type = type.return_type
if self.overridable:
......
......@@ -212,8 +212,12 @@ class PxdPostParse(CythonTransform):
- "def" functions are let through only if they fill the
getbuffer/releasebuffer slots
- cdef functions are let through only if they are on the
top level and are declared "inline"
"""
ERR_FUNCDEF_NOT_ALLOWED = 'function definition not allowed here'
ERR_INLINE_ONLY = "function definition in pxd file must be declared 'cdef inline'"
ERR_NOGO_WITH_INLINE = "inline function definition in pxd file cannot be '%s'"
def __call__(self, node):
self.scope_type = 'pxd'
......@@ -229,18 +233,26 @@ class PxdPostParse(CythonTransform):
def visit_FuncDefNode(self, node):
# FuncDefNode always come with an implementation (without
# an imp they are CVarDefNodes..)
ok = False
err = self.ERR_INLINE_ONLY
if (isinstance(node, DefNode) and self.scope_type == 'cclass'
and node.name in ('__getbuffer__', '__releasebuffer__')):
ok = True
err = None # allow these slots
if isinstance(node, CFuncDefNode):
ok = True
if u'inline' in node.modifiers and self.scope_type == 'pxd':
node.inline_in_pxd = True
if node.visibility != 'private':
err = self.ERR_NOGO_WITH_INLINE % node.visibility
elif node.api:
err = self.ERR_NOGO_WITH_INLINE % 'api'
else:
err = None # allow inline function
else:
err = None
for stat in node.body.stats:
if not isinstance(stat, CVarDefNode):
self.context.error("C function definition not allowed here")
ok = False
err = self.ERR_INLINE_ONLY
break
node = CVarDefNode(node.pos,
visibility = node.visibility,
......@@ -250,10 +262,8 @@ class PxdPostParse(CythonTransform):
api = node.api,
overridable = node.overridable,
pxd_locals = node.body.stats)
if not ok:
self.context.nonfatal_error(PostParseError(node.pos,
self.ERR_FUNCDEF_NOT_ALLOWED))
if err:
self.context.nonfatal_error(PostParseError(node.pos, err))
return None
else:
return node
......
......@@ -97,7 +97,10 @@ class Entry:
# utility_code string Utility code needed when this entry is used
#
# buffer_aux BufferAux or None Extra information needed for buffer variables
# inline_func_in_pxd boolean Hacky special case for inline function in pxd file.
# Ideally this should not be necesarry.
inline_func_in_pxd = False
borrowed = 0
init = ""
visibility = 'private'
......
......@@ -132,57 +132,8 @@ cdef extern from "numpy/arrayobject.h":
return
else:
info.format = <char*>stdlib.malloc(255) # static size
f = info.format
stack = [iter(descr.fields.iteritems())]
while True:
iterator = stack[-1]
descr = None
while descr is None:
try:
descr = iterator.next()[1][0]
except StopIteration:
stack.pop()
if len(stack) > 0:
f[0] = 125 #"}"
f += 1
iterator = stack[-1]
else:
f[0] = 0 # Terminate string!
return
hasfields = PyDataType_HASFIELDS(descr)
if not hasfields:
t = descr.type_num
if f - info.format > 240: # this should leave room for "T{" and "}" as well
raise RuntimeError("Format string allocated too short.")
# Until ticket #99 is fixed, use integers to avoid warnings
if t == NPY_BYTE: f[0] = 98 #"b"
elif t == NPY_UBYTE: f[0] = 66 #"B"
elif t == NPY_SHORT: f[0] = 104 #"h"
elif t == NPY_USHORT: f[0] = 72 #"H"
elif t == NPY_INT: f[0] = 105 #"i"
elif t == NPY_UINT: f[0] = 73 #"I"
elif t == NPY_LONG: f[0] = 108 #"l"
elif t == NPY_ULONG: f[0] = 76 #"L"
elif t == NPY_LONGLONG: f[0] = 113 #"q"
elif t == NPY_ULONGLONG: f[0] = 81 #"Q"
elif t == NPY_FLOAT: f[0] = 102 #"f"
elif t == NPY_DOUBLE: f[0] = 100 #"d"
elif t == NPY_LONGDOUBLE: f[0] = 103 #"g"
elif t == NPY_CFLOAT: f[0] = 90; f[1] = 102; f += 1
elif t == NPY_CDOUBLE: f[0] = 90; f[1] = 100; f += 1
elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1
elif t == NPY_OBJECT: f[0] = 79 #"O"
else:
raise ValueError("unknown dtype code in numpy.pxd (%d)" % t)
f += 1
else:
f[0] = 84 #"T"
f[1] = 123 #"{"
f += 2
stack.append(iter(descr.fields.iteritems()))
f = _util_dtypestring(descr, info.format, info.format + 255)
f[0] = 0 # Terminate format string
def __releasebuffer__(ndarray self, Py_buffer* info):
if PyArray_HASFIELDS(self):
......@@ -292,3 +243,48 @@ ctypedef npy_longdouble longdouble_t
ctypedef npy_cfloat cfloat_t
ctypedef npy_cdouble cdouble_t
ctypedef npy_clongdouble clongdouble_t
cdef inline char* _util_dtypestring(dtype descr, char* f, char* end) except NULL:
# Recursive utility function used in __getbuffer__ to get format
# string. The new location in the format string is returned.
cdef dtype child
cdef tuple i
for i in descr.fields.itervalues():
child = i[0]
if not PyDataType_HASFIELDS(child):
t = child.type_num
if end - f < 15: # this should leave room for "T{" and "}" as well
raise RuntimeError("Format string allocated too short.")
# Until ticket #99 is fixed, use integers to avoid warnings
if t == NPY_BYTE: f[0] = 98 #"b"
elif t == NPY_UBYTE: f[0] = 66 #"B"
elif t == NPY_SHORT: f[0] = 104 #"h"
elif t == NPY_USHORT: f[0] = 72 #"H"
elif t == NPY_INT: f[0] = 105 #"i"
elif t == NPY_UINT: f[0] = 73 #"I"
elif t == NPY_LONG: f[0] = 108 #"l"
elif t == NPY_ULONG: f[0] = 76 #"L"
elif t == NPY_LONGLONG: f[0] = 113 #"q"
elif t == NPY_ULONGLONG: f[0] = 81 #"Q"
elif t == NPY_FLOAT: f[0] = 102 #"f"
elif t == NPY_DOUBLE: f[0] = 100 #"d"
elif t == NPY_LONGDOUBLE: f[0] = 103 #"g"
elif t == NPY_CFLOAT: f[0] = 90; f[1] = 102; f += 1
elif t == NPY_CDOUBLE: f[0] = 90; f[1] = 100; f += 1
elif t == NPY_CLONGDOUBLE: f[0] = 90; f[1] = 103; f += 1
elif t == NPY_OBJECT: f[0] = 79 #"O"
else:
raise ValueError("unknown dtype code in numpy.pxd (%d)" % t)
f += 1
else:
f[0] = 84 #"T"
f[1] = 123 #"{"
f += 2
f = _util_dtypestring(child, f, end)
f[0] = 125 #"}"
f += 1
return f
cimport e_func_in_pxd_support
_ERRORS = u"""
1:5: function definition in pxd file must be declared 'cdef inline'
4:5: inline function definition in pxd file cannot be 'public'
7:5: inline function definition in pxd file cannot be 'api'
"""
cdef foo():
return 1
cdef public inline foo2():
return 1
cdef api inline foo3():
return 1
cdef inline int my_add(int a, int b):
return a + b
"""
>>> f()
3
>>> g()
6
>>> h()
6
"""
cimport inlinepxd_support
from inlinepxd_support cimport my_add as my_add3
def f():
return my_add(1, 2)
def g():
return inlinepxd_support.my_add(1, 2, 3)
def h():
return my_add3(1, 2, 3)
cdef inline int my_add(int a, int b, int c):
return a + b + c
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment