Re: [Cython] operator() bug in cython
On Fri Feb 13 2015 at 11:07:39 PM Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
Ulrich Dobramysl wrote:
Thanks! I haven't figured out how to call heap allocated objects, as the code --- cdef OperatorTest *t = new OperatorTest() t() --- is not translatable by Cython.
Have you tried:
t[0]()
?
Thanks, I didn't think about the t[0] trick!
I haven't been following the development of Cython's internals, so I may be speaking naively here, but it looks wrong to me that the cname of that entry should be 'operator()' rather than the c-level name of the variable that the NameNode refers to.
The cname of the entry is correct IMO, because it cannot have any knowledge about the cname of the object it is being called as later. The logic dealing with the special case of an operator() member function of a c++ class in SimpleCallNode.analyse_c_function_call() needs to be changed slightly to not treat operator() as an overloaded entry. Rather, the function type of the SimpleCallNode needs to be set to the type of the looked-up operator() entry. Then, at the code generation stage, the correct cname of the SimpleCallNode entry is used and not the entry of operator(). With the patch below my test case compiles and runs without problems: ---- diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index f99ec6e..88522c9 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -4569,11 +4569,13 @@ class SimpleCallNode(CallNode): args = self.args if func_type.is_cpp_class: - overloaded_entry = self.function.type.scope.lookup("operator()") - if overloaded_entry is None: + call_operator = self.function.type.scope.lookup("operator()") + if call_operator is None: self.type = PyrexTypes.error_type self.result_code = "<error>" return + self.function.type = call_operator.type + overloaded_entry = None elif hasattr(self.function, 'entry'): overloaded_entry = self.function.entry elif (isinstance(self.function, IndexNode) and @@ -4603,7 +4605,7 @@ class SimpleCallNode(CallNode): else: entry = None func_type = self.function_type() - if not func_type.is_cfunction: + if not (func_type.is_cfunction or func_type.is_cpp_class): error(self.pos, "Calling non-function type '%s'" % func_type) self.type = PyrexTypes.error_type self.result_code = "<error>" ---- What do you think? I don't know a lot about cython's internals, so there might be use cases which break this code. Ulrich
On Tue, Feb 17, 2015 at 2:51 AM Ulrich Dobramysl <uli-do@gmx.at> wrote:
On Fri Feb 13 2015 at 11:07:39 PM Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
Ulrich Dobramysl wrote:
Thanks! I haven't figured out how to call heap allocated objects, as the code --- cdef OperatorTest *t = new OperatorTest() t() --- is not translatable by Cython.
Have you tried:
t[0]()
?
Thanks, I didn't think about the t[0] trick!
I haven't been following the development of Cython's internals, so I may be speaking naively here, but it looks wrong to me that the cname of that entry should be 'operator()' rather than the c-level name of the variable that the NameNode refers to.
The cname of the entry is correct IMO, because it cannot have any knowledge about the cname of the object it is being called as later. The logic dealing with the special case of an operator() member function of a c++ class in SimpleCallNode.analyse_c_function_call() needs to be changed slightly to not treat operator() as an overloaded entry. Rather, the function type of the SimpleCallNode needs to be set to the type of the looked-up operator() entry. Then, at the code generation stage, the correct cname of the SimpleCallNode entry is used and not the entry of operator(). With the patch below my test case compiles and runs without problems: ---- diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index f99ec6e..88522c9 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -4569,11 +4569,13 @@ class SimpleCallNode(CallNode): args = self.args
if func_type.is_cpp_class: - overloaded_entry = self.function.type.scope.lookup("operator()") - if overloaded_entry is None: + call_operator = self.function.type.scope.lookup("operator()") + if call_operator is None: self.type = PyrexTypes.error_type self.result_code = "<error>" return + self.function.type = call_operator.type + overloaded_entry = None elif hasattr(self.function, 'entry'): overloaded_entry = self.function.entry elif (isinstance(self.function, IndexNode) and @@ -4603,7 +4605,7 @@ class SimpleCallNode(CallNode): else: entry = None func_type = self.function_type() - if not func_type.is_cfunction: + if not (func_type.is_cfunction or func_type.is_cpp_class): error(self.pos, "Calling non-function type '%s'" % func_type) self.type = PyrexTypes.error_type self.result_code = "<error>" ---- What do you think? I don't know a lot about cython's internals, so there might be use cases which break this code.
Ulrich
_______________________________________________ cython-devel mailing list cython-devel@python.org https://mail.python.org/mailman/listinfo/cython-devel
What is the status on this? The most recent patch appears to work if the first two changed lines are ignored. If it would help move this along, I can open a PR with the modified patch and a commit that still attributes the patch to the original author. Thanks! -Ian Henriksen
On Mon, Jun 22, 2015 at 3:13 PM Ian Henriksen < insertinterestingnamehere@gmail.com> wrote:
On Tue, Feb 17, 2015 at 2:51 AM Ulrich Dobramysl <uli-do@gmx.at> wrote:
On Fri Feb 13 2015 at 11:07:39 PM Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
Ulrich Dobramysl wrote:
Thanks! I haven't figured out how to call heap allocated objects, as the code --- cdef OperatorTest *t = new OperatorTest() t() --- is not translatable by Cython.
Have you tried:
t[0]()
?
Thanks, I didn't think about the t[0] trick!
I haven't been following the development of Cython's internals, so I may be speaking naively here, but it looks wrong to me that the cname of that entry should be 'operator()' rather than the c-level name of the variable that the NameNode refers to.
The cname of the entry is correct IMO, because it cannot have any knowledge about the cname of the object it is being called as later. The logic dealing with the special case of an operator() member function of a c++ class in SimpleCallNode.analyse_c_function_call() needs to be changed slightly to not treat operator() as an overloaded entry. Rather, the function type of the SimpleCallNode needs to be set to the type of the looked-up operator() entry. Then, at the code generation stage, the correct cname of the SimpleCallNode entry is used and not the entry of operator(). With the patch below my test case compiles and runs without problems: ---- diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index f99ec6e..88522c9 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -4569,11 +4569,13 @@ class SimpleCallNode(CallNode): args = self.args
if func_type.is_cpp_class: - overloaded_entry = self.function.type.scope.lookup("operator()") - if overloaded_entry is None: + call_operator = self.function.type.scope.lookup("operator()") + if call_operator is None: self.type = PyrexTypes.error_type self.result_code = "<error>" return + self.function.type = call_operator.type + overloaded_entry = None elif hasattr(self.function, 'entry'): overloaded_entry = self.function.entry elif (isinstance(self.function, IndexNode) and @@ -4603,7 +4605,7 @@ class SimpleCallNode(CallNode): else: entry = None func_type = self.function_type() - if not func_type.is_cfunction: + if not (func_type.is_cfunction or func_type.is_cpp_class): error(self.pos, "Calling non-function type '%s'" % func_type) self.type = PyrexTypes.error_type self.result_code = "<error>" ---- What do you think? I don't know a lot about cython's internals, so there might be use cases which break this code.
Ulrich
_______________________________________________ cython-devel mailing list cython-devel@python.org https://mail.python.org/mailman/listinfo/cython-devel
What is the status on this? The most recent patch appears to work if the first two changed lines are ignored. If it would help move this along, I can open a PR with the modified patch and a commit that still attributes the patch to the original author. Thanks! -Ian Henriksen
Alright, I've put up a pull request at https://github.com/cython/cython/pull/400. I hope this makes things a bit easier. -Ian Henriksen
participants (2)
-
Ian Henriksen -
Ulrich Dobramysl