Cython:如何使用 C++-类 的用户自定义转换?
Cython: How user-defined conversion of C++-classes can be used?
Cython 的 documentation seems to be silent about how user-defined conversion 可以被包装。
例如,当以下 c++ 代码打印 1
(即 true
、here live)时:
#include <iostream>
struct X{
operator bool() const{ return true;}
};
int main() {
X x;
std::cout << x << "\n";
}
其在 Cython 中的 "equivalent":
%%cython -+
cdef extern from *:
"""
struct X {
//implicit conversion
operator bool() const { return true; }
};
"""
cdef cppclass X:
operator bool() # ERROR HERE
def testit():
cdef X x;
print(x) # implicit cast, "should" print True
没有被 cythonized 并出现以下错误消息(在标有 ERROR HERE
的行中):
'operator' is not a type identifier
如何从 Cython 使用用户定义的转换,如果不能,有什么解决方法?
仅查看 bool
案例:
我不相信 print(x)
应该将它转换为布尔值。 print(x)
查找到 Python 对象的转换(好吧,bool
可以转换为 Python 对象,但有点间接)。 Python 本身仅在相当有限的情况下使用 __bool__
(__nonzero__
in Python 2),例如在 if
语句中,而 Cython 通常遵循 Python 作为规则的行为。因此我将测试代码更改为
def testit():
cdef X x
if x:
print("is True")
else:
print("if False")
operator bool()
给出错误
'operator' is not a type identifier
我假设它需要像所有其他 C++ 函数一样以 return 类型开始(即 operator
没有特殊情况)。这有效(有点......见下一点......):
bool operator bool()
这个语法就是 tested for in Cython's testsuite.
但是,您确实需要在文件顶部执行 from libcpp cimport bool
以获得 C++ bool
类型。
如果您查看 if x:
的转换源,它最终会变成
__pyx_t_1 = __pyx_v_x.operator bool();
if (__pyx_t_1) {
operator bool
被显式调用(这对于 Cython 来说很常见),但在正确的位置使用,因此 Cython 清楚地理解它的用途。同样,如果你在没有定义运算符的情况下执行 if x:
,你会得到错误
Object of type 'X' has no attribute 'operator bool'
再次表明这是 Cython 的一个特性。
这里显然有一点文档错误,如果将来语法更改为更接近 C++,我不会 100% 感到惊讶。
对于更一般的情况:it looks like bool
is the only type-conversion operator supported 目前,您无法定义其他运算符。
这只是对 的一些补充。
如前所述,Cython 仅支持 operator bool
- 其他用户定义的转换,例如:
cdef cppclass X:
int operator int()
将导致类似
的错误消息
Overloading operator 'int' not yet supported.
一种可能的解决方法是不包装用户定义的转换,而是在需要时使用显式转换。例如:
%%cython -+ -a
cdef extern from *:
"""
struct X {
//implicit conversion
operator int() const { return 42; }
};
"""
cdef cppclass X:
pass # leave operator int() out
def testit():
cdef X x;
print(<int>x)
一旦调用 testit
就会编译并打印 42
。 Cython 不干预此处的显式转换。
具有讽刺意味的是,上述解决方法不适用于 operator bool()
:
%%cython -+ -a
cdef extern from *:
"""
struct X {
//implicit conversion
operator bool() const { return true; }
};
"""
cdef cppclass X:
pass # leave operator bool() out
def testit():
cdef X x;
if <bint>x:
print(True)
else:
print(False)
导致错误信息:
Object of type 'X' has no attribute 'operator bool'
显然,此检查是 operator bool()
-支持包的一部分..
然而,可以使用转换为 int
而不是转换为 bool/bint
来实现目标:
...
if <int>x:
...
但是,应该首选 operator bool()
包装。
简而言之:
- 使用
bint operator bool()
包装 C++ 的 operator bool()
- 不要为其他运算符包装和使用显式转换。
Cython 的 documentation seems to be silent about how user-defined conversion 可以被包装。
例如,当以下 c++ 代码打印 1
(即 true
、here live)时:
#include <iostream>
struct X{
operator bool() const{ return true;}
};
int main() {
X x;
std::cout << x << "\n";
}
其在 Cython 中的 "equivalent":
%%cython -+
cdef extern from *:
"""
struct X {
//implicit conversion
operator bool() const { return true; }
};
"""
cdef cppclass X:
operator bool() # ERROR HERE
def testit():
cdef X x;
print(x) # implicit cast, "should" print True
没有被 cythonized 并出现以下错误消息(在标有 ERROR HERE
的行中):
'operator' is not a type identifier
如何从 Cython 使用用户定义的转换,如果不能,有什么解决方法?
仅查看 bool
案例:
我不相信
print(x)
应该将它转换为布尔值。print(x)
查找到 Python 对象的转换(好吧,bool
可以转换为 Python 对象,但有点间接)。 Python 本身仅在相当有限的情况下使用__bool__
(__nonzero__
in Python 2),例如在if
语句中,而 Cython 通常遵循 Python 作为规则的行为。因此我将测试代码更改为def testit(): cdef X x if x: print("is True") else: print("if False")
operator bool()
给出错误'operator' is not a type identifier
我假设它需要像所有其他 C++ 函数一样以 return 类型开始(即
operator
没有特殊情况)。这有效(有点......见下一点......):bool operator bool()
这个语法就是 tested for in Cython's testsuite.
但是,您确实需要在文件顶部执行
from libcpp cimport bool
以获得 C++bool
类型。
如果您查看 if x:
的转换源,它最终会变成
__pyx_t_1 = __pyx_v_x.operator bool();
if (__pyx_t_1) {
operator bool
被显式调用(这对于 Cython 来说很常见),但在正确的位置使用,因此 Cython 清楚地理解它的用途。同样,如果你在没有定义运算符的情况下执行 if x:
,你会得到错误
Object of type 'X' has no attribute 'operator bool'
再次表明这是 Cython 的一个特性。
这里显然有一点文档错误,如果将来语法更改为更接近 C++,我不会 100% 感到惊讶。
对于更一般的情况:it looks like bool
is the only type-conversion operator supported 目前,您无法定义其他运算符。
这只是对
如前所述,Cython 仅支持 operator bool
- 其他用户定义的转换,例如:
cdef cppclass X:
int operator int()
将导致类似
的错误消息Overloading operator 'int' not yet supported.
一种可能的解决方法是不包装用户定义的转换,而是在需要时使用显式转换。例如:
%%cython -+ -a
cdef extern from *:
"""
struct X {
//implicit conversion
operator int() const { return 42; }
};
"""
cdef cppclass X:
pass # leave operator int() out
def testit():
cdef X x;
print(<int>x)
一旦调用 testit
就会编译并打印 42
。 Cython 不干预此处的显式转换。
具有讽刺意味的是,上述解决方法不适用于 operator bool()
:
%%cython -+ -a
cdef extern from *:
"""
struct X {
//implicit conversion
operator bool() const { return true; }
};
"""
cdef cppclass X:
pass # leave operator bool() out
def testit():
cdef X x;
if <bint>x:
print(True)
else:
print(False)
导致错误信息:
Object of type 'X' has no attribute 'operator bool'
显然,此检查是 operator bool()
-支持包的一部分..
然而,可以使用转换为 int
而不是转换为 bool/bint
来实现目标:
...
if <int>x:
...
但是,应该首选 operator bool()
包装。
简而言之:
- 使用
bint operator bool()
包装 C++ 的operator bool()
- 不要为其他运算符包装和使用显式转换。