Hi guys, a C conversion question. The C code:
typedef enum cpSpaceDebugDrawFlags {
CP_SPACE_DEBUG_DRAW_SHAPES = 1<<0,
CP_SPACE_DEBUG_DRAW_CONSTRAINTS = 1<<1,
CP_SPACE_DEBUG_DRAW_COLLISION_POINTS = 1<<2,
} cpSpaceDebugDrawFlags;
typedef struct cpSpaceDebugDrawOptions {
// Attribues ...
cpSpaceDebugDrawFlags flags;
// More attribues ...
} cpSpaceDebugDrawOptions;
// Usage in some function
void someFunc()
{
cpSpaceDebugDrawOptions drawOptions = {
// Field assignments ...
(cpSpaceDebugDrawFlags)(CP_SPACE_DEBUG_DRAW_SHAPES |
CP_SPACE_DEBUG_DRAW_CONSTRAINTS |
CP_SPACE_DEBUG_DRAW_COLLISION_POINTS),
// More field assignments ...
};
// More code
}
Incorrect c2nim conversion:
type
cpSpaceDebugDrawFlags* {.size: sizeof(cint).} = enum
CP_SPACE_DEBUG_DRAW_SHAPES = 1 shl 0,
CP_SPACE_DEBUG_DRAW_CONSTRAINTS = 1 shl 1,
CP_SPACE_DEBUG_DRAW_COLLISION_POINTS = 1 shl 2
cpSpaceDebugDrawOptions* = object
# Attribues ...
flags*: cpSpaceDebugDrawFlags
# More attribues ...
proc someFunc*() =
var drawOptions: cpSpaceDebugDrawOptions(
# Field assignments ...
flags: (cpSpaceDebugDrawFlags)(CP_SPACE_DEBUG_DRAW_SHAPES or
CP_SPACE_DEBUG_DRAW_CONSTRAINTS or
CP_SPACE_DEBUG_DRAW_COLLISION_POINTS) # <- THIS IS WRONG
# More field assignments ...
)
# More code ...
What is the correct way to assign to the 'flags' field in Nim that is the equivalent of the C code?
Or operation is not defined for Nim enums by default. You may try something like
flags = cpSpaceDebugDrawFlags(P_SPACE_DEBUG_DRAW_SHAPES.ord or CP_SPACE_DEBUG_DRAW_CONSTRAINTS.ord)
Or you may define an or operation for your flags. Or maybe use a set of flags. Or, what Araq may recommend, use plain ints as flags instead of enums. Your code may have more syntax errors, maybe it should be "flags =" for assignment.
Thanks for the reply, Stefan.
You were close. This gives an error, because the or-ed together value is 7 and the enum values go only to 4:
flags: cpSpaceDebugDrawFlags(
CP_SPACE_DEBUG_DRAW_SHAPES.ord or
CP_SPACE_DEBUG_DRAW_CONSTRAINTS.ord or
CP_SPACE_DEBUG_DRAW_COLLISION_POINTS.ord
),
but this works:
flags: cast[cpSpaceDebugDrawFlags](
CP_SPACE_DEBUG_DRAW_SHAPES.ord or
CP_SPACE_DEBUG_DRAW_CONSTRAINTS.ord or
CP_SPACE_DEBUG_DRAW_COLLISION_POINTS.ord
),
I guess that's the way it is:
type
cpSpaceDebugDrawFlags = enum
CP_SPACE_DEBUG_DRAW_SHAPES = 1 shl 0,
CP_SPACE_DEBUG_DRAW_CONSTRAINTS = 1 shl 1,
CP_SPACE_DEBUG_DRAW_COLLISION_POINTS = 1 shl 2
cpSpaceDebugDrawOptions = object
flags: set[cpSpaceDebugDrawFlags]
proc someFunc() =
var drawOptions = cpSpaceDebugDrawOptions(flags: {
CP_SPACE_DEBUG_DRAW_SHAPES,
CP_SPACE_DEBUG_DRAW_CONSTRAINTS,
CP_SPACE_DEBUG_DRAW_COLLISION_POINTS
})
@_tulayang no, that's wrong. Try this:
type
cpSpaceDebugDrawFlags = enum
CP_SPACE_DEBUG_DRAW_SHAPES = 0,
CP_SPACE_DEBUG_DRAW_CONSTRAINTS = 1,
CP_SPACE_DEBUG_DRAW_COLLISION_POINTS = 2
cpSpaceDebugDrawOptions = object
flags: set[cpSpaceDebugDrawFlags] # Nim converts the enum value to a bit position via '1 shr x' on its own, because that's how sets actually work
proc someFunc() =
var drawOptions = cpSpaceDebugDrawOptions(flags: {
CP_SPACE_DEBUG_DRAW_SHAPES,
CP_SPACE_DEBUG_DRAW_CONSTRAINTS,
CP_SPACE_DEBUG_DRAW_COLLISION_POINTS
})
Note that Nim uses 1 byte for the set and C a cint so there is still an incompatibility.
That's it Araq! _tulayang's solution compiled but didn't produce the correct result in the application.
I love it when the solutions are more Nimmy ( :) ) and not a straight C translation.