gpt4 book ai didi

python - 痛饮/ python : object does not support indexing

转载 作者:太空狗 更新时间:2023-10-29 21:33:31 26 4
gpt4 key购买 nike

给定这组文件:

foo.h:

#pragma once

#include <stdio.h>

template <class T0> class Foo {
public:
T0 m[3];

Foo(const T0 &a, const T0 &b, const T0 &c) {
m[0] = a;
m[1] = b;
m[2] = c;
}
void info() { printf("%d %d %d\n", m[0], m[1], m[2]); }
// T0 &operator[](int id) { return ((T0 *)m)[id]; }
};

foo.cpp:

#include "foo.h"

foo.i(尝试 1):

%module foo

%{
#include "foo.h"
%}

%include "foo.h"

%template(intFoo) Foo<int>;

%extend Foo{
T0& __getitem__(int id) { return ((T0 *)m)[id]; }
}

设置.py:

import os
import sys
from setuptools import setup, Extension

foo_module = Extension('_foo',
sources=[
'foo.i',
'foo.cpp'
],
swig_opts=['-c++', '-py3', '-builtin'],
include_dirs=['.']
)

setup(name='foo',
version='0.1',
platforms=['Windows', 'Linux'],
ext_modules=[foo_module],
py_modules=["foo"],
)

测试.py:

from foo import intFoo

a = intFoo(10,20,30)
print(dir(a))
a.info()
print(a[2])

我构建了正在运行的扩展:

python setup.py build_ext --force -i

但是当我尝试运行 test.py 时,我会得到:

TypeError: 'foo.intFoo' object does not support indexing

foo.i 中的语句extend 是在任何其他 SO 相关线程上建议的答案,这意味着我在这里使用不正确。谁能解释一下如何解决这个问题,以便在我运行 test.py 时能够成功使用 [] 运算符?

另一种尝试:

  • 尝试 2:

    %module foo

    %{
    #include "foo.h"
    %}

    %include "foo.h"

    %template(intFoo) Foo<int>;

    %extend intFoo{
    T0& __getitem__(int id) { return ((T0 *)m)[id]; }
    }

    抛出此错误TypeError: 'foo.intFoo' object does not support indexing

  • 尝试 3

    %module foo

    %{
    #include "foo.h"
    %}

    %include "foo.h"

    %extend Foo{
    T0& __getitem__(int id) { return ((T0 *)m)[id]; }
    }

    %template(intFoo) Foo<int>;

    抛出此错误 foo_wrap.cpp(3808): error C2065: 'm': undeclared identifier

最佳答案

(在整个示例中,我使用的是您的第一个版本的 foo.i)

首先,您需要在 %template 指令之前指定 %extend 才能生效。

一旦我们解决了这个问题,我们现在就会从您的 %extend 代码中得到一个编译器错误:

foo_wrap.cpp: In function 'int& Foo_Sl_int_Sg____getitem__(Foo<int>*, int)':
foo_wrap.cpp:3705:85: error: 'm' was not declared in this scope

发生这种情况是因为您使用 %extend 添加的方法并不是您要将它们添加到的类的真正成员。要在此上下文中访问 m,我们需要使用 $self->m 来引用它。 SWIG 将 replace $self为我们提供适当的变量。 (值得快速浏览一下生成的代码以了解其工作原理)

调试类型映射或扩展时的一个有用提示是在 SWIG 生成的输出中搜索您编写的代码 - 如果它不存在,则它没有按照您的想法应用。

因此,一旦我们修复了关于 m 未被声明的错误,我们就会遇到另一个问题,因为您已经使用 -builtin 进行了编译:

In [1]: import foo

In [2]: f=foo.intFoo(1,2,3)

In [3]: f[0]
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-3-e71eec16918d> in <module>()
----> 1 f[0]

TypeError: 'intFoo' object does not support indexing

In [4]: f.__getitem__(0)
Out[4]: <Swig Object of type 'int *' at 0xa8807d40>

即使您已经添加了 __getitem__,使用 f[n] 的索引仍然不起作用。发生这种情况是因为 Python 中的纯 C-API 类运算符重载的工作方式不同。您已经成功添加了一个 __getitem__ 方法,但是 Python 正在寻找 builtin type's slots (特别是 mp_subscript)执行操作的方法。所以我们也需要解决这个问题。完成后一个工作的 foo.i 看起来像:

%module foo

%{
#include "foo.h"
%}

%feature("python:slot", "mp_subscript", functype="binaryfunc") Foo::__getitem__;

%include "foo.h"

%extend Foo{
T0& __getitem__(int id) { return ((T0 *)$self->m)[id]; }
}

%template(intFoo) Foo<int>;

所以现在我们可以做你想做的事了:

In [1]: import foo

In [2]: f=foo.intFoo(1,2,3)

In [3]: f[0]
Out[3]: <Swig Object of type 'int *' at 0xb4024100>

(您实际上不必再调用它 __getitem__,因为该函数已在插槽中注册,应该可以调用 operator[]例如根本没有 %extend)

最后,您可能希望将返回类型更改为 const T0&,或者编写一个 Python 类型来代理对象以更好地进行非 const int 引用。

关于python - 痛饮/ python : object does not support indexing,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44308849/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com