Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/358.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 通过引用将单个整数传递给Cython?_Python_Cython - Fatal编程技术网

Python 通过引用将单个整数传递给Cython?

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

我试图让一个调用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 "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])”。