How to declare enum in Cython pxd file for interface with external C library? - enums

I'm trying to use Cython to call external C library from Python. The code looks like this:
header.h
typedef enum {
A = 0,
B = 1,
C = 2,
D = 3
} my_enum_type;
cheader.pxd
cdef extern from "header.h":
ctypedef enum my_enum_type:
A = 1,
B = 2,
C = 3,
D = 4
code.pyx
cimport cheader
cdef cheader.my_enum_type test = A
if test == A:
print("OK")
else:
print("NOK")
With code above I get compiler error: undeclared name not builtin: A
With code bellow there are no compilation errors.
cimport cheader
cdef cheader.my_enum_type test = cheader.my_enum_type.A
if test == cheader.my_enum_type.A:
print("OK")
else:
print("NOK")
If enum is defined in pyx file than code bellow can be used:
ctypedef enum my_enum_type:
A = 1,
B = 2,
C = 3,
D = 4
cdef my_enum_type test = A
if test == A:
print("OK")
else:
print("NOK")
Is it possible to declare enum in pxd file so it's not necessary to reference imported module every time enum has to be used?
What is the proper way to declare enum in pxd file and use it in pyx files?

Related

while deserialising the protobuf as per .proto value is empty string

protobuf:
message test
{
int16 a:1
message testdata{
int16 b:1 `
int16 c:2
repeated testdata test_data=2
}
}
dt=test()
dt.a=11
dt1=d.testdata.add()
dt1.b=2222
dt1.c=3333
send=dt.SerializeToString()
now while deserialising code as below:
t=test()
t.ParseFromString(send)
t1=t.testdata()
print(t1.test_data)----> empty string
print(t1.b)--> value is not printing as expected, its printing object name instead of value.
how to access the nested protobuf elements and any input or suggestions are welcome.
I encourage you to read the documentation.
Your protobuf file is invalid.
A working equivalent of what you've written could be:
example.proto:
syntax = "proto3";
message test {
int32 a=1;
message testdata {
int32 b=1;
int32 c=2;
}
repeated testdata test_data=2;
}
Compiled using:
protoc \
--proto_path=${PWD} \
--python_out=${PWD} \
${PWD}/example.proto
Example Python code (with apologies for my poor variable naming choices):
import example_pb2
from google.protobuf.message import DecodeError
# Create a test message (f)
f = example_pb2.test()
f.a = 1
# Add a repeated property of type testdata
g=f.test_data.add()
g.b=1
g.c=1
# Add a repeated property of type testdata
g=f.test_data.add()
g.b=2
g.c=2
# Add a repeated property of type testdata
g=f.test_data.add()
g.b=3
g.c=3
# Output it
print(f)
# Serialize it and output it
x=f.SerializeToString()
print(x)
# Create a new test message (h) and parse x into it
h=example_pb2.test()
h.ParseFromString(x)
print(h)
# Create incorrectly formatted message (y) as a variant of x
y=b'\x08\x01\x12\x12\x04\x08\x01\x10\x01\x12\x04\x08\x02\x10\x02\x12\x04\x08\x03\x10\x03'
j=example_pb2.test()
try:
j.ParseFromString(y)
print(j)
except DecodeError as e:
print(e)
Yielding:
a: 1
test_data {
b: 1
c: 1
}
test_data {
b: 2
c: 2
}
test_data {
b: 3
c: 3
}
b'\x08\x01\x12\x04\x08\x01\x10\x01\x12\x04\x08\x02\x10\x02\x12\x04\x08\x03\x10\x03'
a: 1
test_data {
b: 1
c: 1
}
test_data {
b: 2
c: 2
}
test_data {
b: 3
c: 3
}
Error parsing message

Can't OR 2 enum values of the same type outside its enum class declaration

I am a newbie to both C++ and game programming. I am dealing with something I don't know how to make it work. I am coding along a game from a book, the authors didn't use enum class for his type but as recommended by most people, I am using enum class to remake it. It produces no error when I OR 2 enum value inside its enum class scope like this:
// This is inside the "Category.h" header file
namespace Category
{
enum class Type
{
None = 0,
SceneAirLayer = 1 << 0,
PlayerAircraft = 1 << 1,
AlliedAircraft = 1 << 2,
EnemyAircraft = 1 << 3,
Pickup = 1 << 4,
AlliedProjectile = 1 << 5,
EnemyProjectile = 1 << 6,
Aircraft = PlayerAircraft | AlliedAircraft | EnemyAircraft,
Projectile = AlliedProjectile | EnemyProjectile
};
}
But when I try to OR them inside a function of another source file, the compiler produces an error,
that is: "no operator "|" matches these operands operand type are Category::Type | Category::Type"
and here is the code inside that function (the game works for the authors version enum without class)
void World::destroyEntitiesOutsideView()
{
// This "command.category" just returns an "unsigned int" value
Command command;
// The error appears here
command.category = static_cast<unsigned int>(Category::Type::Projectile | Category::Type::EnemyAircraft);
// This is I just try to OR them alone but still the same error
Category::Type::Aircraft | Category::Type::AlliedProjectile;
}
Please someone tell me why and how can I fix this error??? Thank you a lot!!!
It is because you are using enum class instead of just enum. "Class enum doesn’t allow implicit conversion to int, and also doesn’t compare enumerators from different enumerations"

Find Possible Numerical Values of Enum Using GDB

With an enum declared and instantiated like this:
enum test_enumeration
{
test1 = 4,
test2 = 10,
test3,
};
test_enumeration test_enum;
I can call
(gdb) ptype test_enum
to get out
type = enum test_enumeration {test1 = 4, test2 = 10, test3}
This gives me the numerical value of test1 and test2 but NOT test3.
If I call
(gdb) print (int)test3
GDB prints out the value 11.
However I want to be able to get something like this:
type = enum test_enumeration {test1 = 4, test2 = 10, test3 = 11}
By printing out the entire type definition using test_enum.
Unfortunately
(gdb) ptype (int)test_enum
returns the the type as int and not the values.
Is there a way to print out the enum constants like this or an option that needs to be set to always display their numerical versions?
GDB V10.1
This will print out all the elements of an enum type. The executable needs to have been compiled with debuginfo.
$ cat print-enum.py
import gdb
class PrintEnumCmd(gdb.Command):
"""print all elements of the given enum type"""
def __init__(self):
super(PrintEnumCmd, self).__init__("print-enum", gdb.COMMAND_DATA, gdb.COMPLETE_EXPRESSION)
def invoke(self, argstr, from_tty):
typename = argstr
if not typename or typename.isspace():
raise gdb.GdbError("Usage: print-enum type")
try:
t = gdb.lookup_type(typename)
except gdb.error:
typename = "enum " + typename
try:
t = gdb.lookup_type(typename)
except gdb.error:
raise gdb.GdbError("type " + typename + " not found")
if t.code != gdb.TYPE_CODE_ENUM:
raise gdb.GdbError("type " + typename + " is not an enum")
for f in t.fields():
print(f.name, "=", f.enumval)
PrintEnumCmd()
$ gdb enu
Reading symbols from enu...done.
(gdb) source print-enum.py
(gdb) print-enum
Usage: print-enum type
(gdb) print-enum test<tab>
test1 test2 test3 test_enumeration
(gdb) print-enum test_enumeration
test1 = 4
test2 = 10
test3 = 11
This is not currently possible in GDB. The code that decides if the = VAL part should be printed is here:
https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=gdb/c-typeprint.c;h=0502d31eff9605e7e2e430c8ad72908792c1b475;hb=HEAD#l1607
The value is only printed if it is not 1 more than the value of the previous enum entry.

Unable to type alias a specialised generic enum

Given the following:
use std::fmt::Debug;
#[derive(Debug)]
enum A<T: Debug> {
X,
Y(T),
}
#[derive(Debug)]
struct B;
type C = A<B>;
// use A<B> as C; // Does not compile
I can use it as:
fn main() {
let val0 = A::X::<B>;
let val1 = A::Y::<B>(B);
println!("{:?}\t{:?}", val0, val1);
}
But then for more than one generic parameter (or if A, B etc were much longer names then to alias it I tried the following but it doesn't compile:
fn main() {
let val0 = C::X;
let val1 = C::Y(B);
println!("{:?}\t{:?}", val0, val1);
}
with errors:
src/main.rs:656:16: 656:20 error: no associated item named `X` found for type `A<B>` in the current scope
src/main.rs:656 let val0 = C::X;
^~~~
src/main.rs:657:16: 657:20 error: no associated item named `Y` found for type `A<B>` in the current scope
src/main.rs:657 let val1 = C::Y(B);
As also noted i am unable to use use to solve the problem. Is there a way around it (because typing the whole thing seems to be cumbersome) ?
rustc --version
rustc 1.9.0 (e4e8b6668 2016-05-18)
Is there a way around it (because typing the whole thing seems to be cumbersome)?
You can specify C as the type of the variable so you can use A::X or A::Y without explicit specifying the type parameter:
let val0: C = A::X;
let val1: C = A::Y(B);

Proper ways to initialize member variables with identical names as the parameters

I got a class that looks like this
class Rational{
public:
Rational(int p = 0, int q = 1) : p(p), q(q){};
private:
int p;
int q;
};
My question is about the initialization syntax where member variables and constructor parameters has identical names.
I now know it is legal to do so, but my question is:
If I want do have "clean", easy to grasp code I wonder if I can do as one normally would do in java:
//Legal Java Code
this.q = q;
this.p = p;
//Is any of these legal C++ code (if so, which one)?
this.q(q);
this.p(p);
//or
this->q(q);
this->p(p);
Even though I haven't tested it, and I can test it, I still want to know the C++ conventions of doing this.
In C++, you have to say:
this -> q = q;
this -> p = p;
or equivalently
(*this).q = q;
(*this).p = p;
But I think the member initializer list syntax
Rational(int p = 0, int q = 1) : p(p), q(q){}
is cleaner (note the lack of a semicolon!) Why don't you like it?

Resources