首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何用cppyy从指针中索引类数组

如何用cppyy从指针中索引类数组
EN

Stack Overflow用户
提问于 2020-03-11 16:03:25
回答 1查看 360关注 0票数 1

我在cppyy中见过关于基本类型数组索引的文档。我还没有弄清楚如何索引一个自定义类型数组。

采取:

代码语言:javascript
复制
import cppyy


cppyy.cppdef("""
struct Foo
{
    float var;
}

struct Bar
{
    Foo* foo;    
}
""")

如果Foo对象的数组存储在Bar的实例中,我如何索引该数组以访问Foo元素?

如果我试着:

代码语言:javascript
复制
bar.foo[0]

我得到:

'Foo‘对象不支持索引

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-03-11 17:59:19

编辑2:按照您在下面的注释中的建议,原来的代码现在与cppyyRelease1.6.2一起运行。也就是说,如果Python代理包含指针类型,那么索引就意味着它代表一个数组。

As-is Foo*被视为指向Foo的指针,而不是指向Foo数组的指针。是的,它可以指向数组,但是低级的C++ (C,真的)是模棱两可的,它是指向对象的指针,这是目前为止常见的情况。如果某物是数组,则数组语法可以工作,因为它再次变得明确起来:

代码语言:javascript
复制
import cppyy

cppyy.cppdef("""
struct Foo
{
    float var;
};

struct Bar
{
    Foo foo[1];
};
""")

bar = cppyy.gbl.Bar()
print(len(bar.foo))
print(bar.foo[0])

其中的指纹:

代码语言:javascript
复制
1
<cppyy.gbl.Foo object at 0x7f85ace370f0>

如预期的那样。

如果您不知道数组的长度,那么是否可以选择使用现代的C++结构,比如std::unique_ptr,而不是传统C?它们是完全明确的,因此很容易自动绑定(它们还使内存管理更加容易):

代码语言:javascript
复制
import cppyy

cppyy.cppdef("""
struct Foo
{
    float var;
};

struct Bar
{
    Bar(int num_foo) : foo(std::unique_ptr<Foo[]>{new Foo[num_foo]}) {
       for (int i = 0; i < num_foo; ++i)
           foo[i].var = (float)2.*i;
    }
    std::unique_ptr<Foo[]> foo;
};
""")

num_foo = 4
bar = cppyy.gbl.Bar(num_foo)
for i in range(num_foo):
    print(bar.foo[i].var)

它打印预期的:

代码语言:javascript
复制
0.0
2.0
4.0
6.0

如果您确实处于维护遗留代码这一不值得羡慕的位置,我建议使用C++ (通过JIT )和pythonization (更详细地介绍这里的https://cppyy.readthedocs.io/en/latest/pythonizations.html)来修补一些东西。例如:

代码语言:javascript
复制
import cppyy

cppyy.cppdef("""
struct Foo
{
    float var;
};

struct Bar
{
    Bar() : foo(new Foo{}) { foo[0].var = 42.f; }
    // memory mgmt here ...
    Foo* foo;
};

Foo* Bar_get_foo_indexed(Bar* b, int idx) {
   return &b->foo[idx];
}
""")

# pythonize the getter
class FooGetter(object):
    def __get__(self, obj, kls=None):
        self.obj = obj
        return self
    def __getitem__(self, idx):
        return cppyy.gbl.Bar_get_foo_indexed(self.obj, idx)

cppyy.gbl.Bar.foo = FooGetter()

bar = cppyy.gbl.Bar()
print(bar.foo[0].var)

它打印预期的:

代码语言:javascript
复制
42.0

编辑:基于您的问题的一些更多的想法。首先,C++端的一个强制转换示例:

代码语言:javascript
复制
cppyy.cppdef("""
struct Foo
{
    float var;
};

struct Bar
{
    Bar() : foo(new Foo[2]) { foo[0].var = 42.f; foo[1].var = 13.f; }
    // memory mgmt here ...
    Foo* foo;
};

template<int N>
struct FooArrayWrapper {
    Foo foo[N];
};

template<int N>
FooArrayWrapper<N>* cast_foo_array(Foo*& f) {
    return reinterpret_cast<FooArrayWrapper<N>*>(f);
}

""")

def make_foo_wrapper_init(func):
    def wrapper_init(self, foo_size, *args, **kwargs):
        func(self)
        self.__dict__['foo_array'] = cppyy.gbl.cast_foo_array[foo_size](self.foo).foo
    return wrapper_init

cppyy.gbl.Bar.__init__ = make_foo_wrapper_init(cppyy.gbl.Bar.__init__)

bar = cppyy.gbl.Bar(2)
print(bar.foo_array[0].var)
print(bar.foo_array[1].var)

还有一个在Python端使用指针算法的转换示例:

代码语言:javascript
复制
cppyy.cppdef("""
struct Foo
{
    float var;
};

struct Bar
{
    Bar() : foo(new Foo[2]) { foo[0].var = 42.f; foo[1].var = 13.f; }
    // memory mgmt here ...
    Foo* foo;
};

""")

bar = cppyy.gbl.Bar()
for i in range(2):
    print(cppyy.bind_object(cppyy.addressof(bar.foo)+i*cppyy.sizeof(cppyy.gbl.Foo), cppyy.gbl.Foo).var)

两者都打印预期的:

代码语言:javascript
复制
42.0
13.0
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60640093

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档