Python 通过引用将单个整数传递给Cython?
我试图让一个调用C函数的测试项目正常工作,其中有一个整数参数需要通过引用从Python传递: 测试.cpp:Python 通过引用将单个整数传递给Cython?,python,cython,Python,Cython,我试图让一个调用C函数的测试项目正常工作,其中有一个整数参数需要通过引用从Python传递: 测试.cpp: #include <iostream> using namespace std; void testFn(int &val); void testFn(int &val) { cout << "val: " << val << endl; val = -1; } cdef extern from "t
#include <iostream>
using namespace std;
void testFn(int &val);
void testFn(int &val)
{
cout << "val: " << val << endl;
val = -1;
}
cdef extern from "test.cpp":
void testFn(int &val)
def myTest(int[:] val):
testFn(&val[0])
def main():
val = [0];
myTest(val)
print(val)
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
sourcefiles = ['caller.pyx']
ext_modules = [Extension("caller", sourcefiles)]
setup(
name = 'test app',
cmdclass = {'build_ext': build_ext},
ext_modules = ext_modules
)
setup.caller.py:
#include <iostream>
using namespace std;
void testFn(int &val);
void testFn(int &val)
{
cout << "val: " << val << endl;
val = -1;
}
cdef extern from "test.cpp":
void testFn(int &val)
def myTest(int[:] val):
testFn(&val[0])
def main():
val = [0];
myTest(val)
print(val)
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
sourcefiles = ['caller.pyx']
ext_modules = [Extension("caller", sourcefiles)]
setup(
name = 'test app',
cmdclass = {'build_ext': build_ext},
ext_modules = ext_modules
)
但当我尝试构建项目时,我得到了一个错误:
$ python setup.caller.py build_ext --inplace
Compiling caller.pyx because it changed.
[1/1] Cythonizing caller.pyx
Error compiling Cython file:
------------------------------------------------------------
...
def myTest(int[:] val):
testFn(&val[0])
^
------------------------------------------------------------
caller.pyx:11:20: Cannot assign type 'int *' to 'int'
我知道在Python中传递整数参数是不起作用的,因为这样的参数是不可变的。正如错误所说:您传递的是一个指针,它期望的是纯类型(C++的行为实际上不像指针,它们不能被取消引用等等)。我认为以下措施应该有效:
def myTest(int[:] val):
testFn(val[0])
您的main
函数也会出现问题,因为列表不是缓冲区类型(因此不能与memoryview一起使用)。通过将其转换为numpy数组或Python数组来修复此问题
def main():
val = np.array([0],dtype=np.int) # or array.array
myTest(val)
print(val)
&int
(用于testFn
)和int*
(您的&val[0]
)不完全相同,这解释了编译器错误
即使可以就地更改python整数,也不应该这样做。一种可能的解决方案是将python整数传递给包装函数,并将包装函数的结果作为新的python整数返回:
def myTest(int val):
testFn(val)
return val
在幕后,cython将python integer转换为c风格的整数,并在调用myTest
后将其转换为(新的)python整数。但是,val
是一个独立(局部)变量,不是对原始python整数的引用,因此通过更改它,我们不会更改原始python整数:
>>> a=6
>>> b=myTest(a)
val: 6
>>> a,b
(6,-1)
我认为这是行不通的——Python整数应该是不可变的(因此,如果它真的起作用,它可能会破坏Python,因为它将小整数视为单例)。但我目前无法测试它(或我自己的答案…),所以我可能会wrong@DavidW我想我还不够清楚,我的解决方案没有尝试在适当的位置更改python整数,而是返回一个新的整数-更改单例整数没有危险。这个解决方案没有提供OP想要的功能,但是将python整数放入
array.array
,以便能够使用缓冲协议并将其替换到位,这对我来说听起来不太有吸引力。谢谢你的回答。我使用了“导入数组…val=array.array('I',[0])”。