如何在Nim语言的Chipmunk7绑定中正确调用eachShape迭代器
问题描述
我正在使用Nim语言的chipmunk7库绑定,尝试调用迭代器eachShape。绑定的相关代码如下:
SpaceShapeIteratorFunc* = proc (shape: Shape; data: pointer) {.cdecl.} ## Space/body iterator callback function type. [..] proc eachShape*(space: Space; `func`: SpaceShapeIteratorFunc; data: pointer) {.cdecl, importc: "cpSpaceEachShape".} ## Call `func` for each shape in the space.
我写了如下调用代码:
import std/math import chipmunk7 import playdate/api var gravity = v(0, 100) var timeStep = 1.0/50.0 var time = 0.0 var space = newSpace() space.gravity = gravity [..] proc drawChipmunkHello*() = # iterate over all shapes in the space for shape in eachShape(space): if shape.shapeType == ShapeType.circle: let circle = shape as CircleShape drawCircle(circle.body.position, circle.radius, circle.body.angle, kColorBlack) elif shape.shapeType == ShapeType.segment: let segment = shape as SegmentShape drawSegment(segment, kColorBlack) elif shape.shapeType == ShapeType.poly: let poly = shape as PolyShape for i in 0 ..< poly.count: let a = poly.getVert(i) let b = poly.getVert((i + 1) % poly.count) playdate.graphics.drawLine(a.x.toInt, a.y.toInt, b.x.toInt, b.y.toInt, 1, kColorBlack);
编译时报错:
hello.nim(63, 25) Error: type mismatch: got <Space> but expected one of: proc eachShape(space: Space; func: SpaceShapeIteratorFunc; data: pointer) first type mismatch at position: 2 missing parameter: func 1 other mismatching symbols have been suppressed; compile with --showAllMismatches:on to see them
第63行是drawChipmunkHello()里的第一行迭代代码。参考过C语言的迭代器调用示例,想请教该迭代器的正确调用语法是什么?
解决方法
当前绑定的eachShape是C风格的回调式接口,并非Nim原生的迭代器,所以不能直接用for...in语法遍历。你可以按照以下两种方式调用:
方式1:直接使用回调函数
定义一个符合SpaceShapeIteratorFunc类型的回调proc,把绘制逻辑放在里面,然后传给eachShape:
proc drawShapeCallback(shape: Shape; data: pointer) {.cdecl.} = case shape.shapeType of ShapeType.circle: let circle = shape as CircleShape drawCircle(circle.body.position, circle.radius, circle.body.angle, kColorBlack) of ShapeType.segment: let segment = shape as SegmentShape drawSegment(segment, kColorBlack) of ShapeType.poly: let poly = shape as PolyShape for i in 0 ..< poly.count: let a = poly.getVert(i) let b = poly.getVert((i + 1) % poly.count) playdate.graphics.drawLine(a.x.toInt, a.y.toInt, b.x.toInt, b.y.toInt, 1, kColorBlack) proc drawChipmunkHello*() = # 调用eachShape,传入回调函数,data参数不需要的话传nil eachShape(space, drawShapeCallback, nil)
方式2:封装成Nim迭代器(推荐)
如果想使用for...in的语法,可以自己封装一个Nim迭代器,把回调逻辑包装起来:
iterator eachShape*(space: Space): Shape = var currentShape: Shape proc captureShape(shape: Shape; data: pointer) {.cdecl.} = currentShape = shape yield currentShape eachShape(space, captureShape, nil) # 现在就可以用你原本的for循环写法了 proc drawChipmunkHello*() = for shape in eachShape(space): case shape.shapeType of ShapeType.circle: let circle = shape as CircleShape drawCircle(circle.body.position, circle.radius, circle.body.angle, kColorBlack) of ShapeType.segment: let segment = shape as SegmentShape drawSegment(segment, kColorBlack) of ShapeType.poly: let poly = shape as PolyShape for i in 0 ..< poly.count: let a = poly.getVert(i) let b = poly.getVert((i + 1) % poly.count) playdate.graphics.drawLine(a.x.toInt, a.y.toInt, b.x.toInt, b.y.toInt, 1, kColorBlack)
封装迭代器时,yield会在回调被调用时触发,从而实现逐个返回Shape对象的效果,完全适配你原本的遍历逻辑。
内容的提问来源于stack exchange,提问作者Nino van Hooff
相关产品推荐
相关产品推荐

