1

i am using ctypes to read some data from an external Database.

this data is written in struct. the problem is, that the recieved Data could have different results. for bettern understanding: i have created two structures:

class BEAM(Structure):
    _fields_ = [
        ('NR', c_ulong),
        ("NODE1", c_ulong),
        ("NODE2", c_ulong),
        ("NP", c_ulong),
        ("DL", c_float),
        ("foo", c_ulong),
        ("foobar", c_ulong),
        ("bar", c_ulong),
        ("barfoo", c_ulong)
    ]

class DUMMY(Structure):
    _fields_ = [
        ('ID', c_ulong),
        ("NODE1", c_ulong),
        ("NODE2", c_ulong),
        ("NP", c_ulong),
        ("DL", c_ulong),
        ("foo", c_ulong),
        ("foobar", c_ulong),
        ("bar", c_ulong),
        ("barfoo", c_ulong)
    ]

the difference between this structs is the u_long type in "DL"... in DUMMY it is u_long, in BEAM it's u_float.

after reading the datbase i get into DL = 1056964624 but in float is should be 0.5

my question is how can i cast the DUMMY into BEAM.

i have tried BEAMRecord = cast(Record, POINTER(BEAMRecord)) but there is an error called TypeError: must be a ctypes type

here is my code:

'''
Structure for DataLength
'''
class Len(Structure):
    _fields_ = [
        ('buffer', c_int)
    ]


SLNRecord = element.SLN()
BEAMRecord = element.BEAM()

Record = element.DUMMY()
RecLen = Len()

sofistik = cdll.LoadLibrary("cdb_w30_x64.dll")

py_sof_cdb_init = sofistik.sof_cdb_init
py_sof_cdb_close = sofistik.sof_cdb_close
py_sof_cdb_get = sofistik.sof_cdb_get

py_sof_cdb_get.restype = c_int

Index = py_sof_cdb_init("system.cdb", 99)

pos = c_int(0)

while True:
    RecLen.buffer = sizeof(Record)

    ie = py_sof_cdb_get(Index, 100, 0, byref(Record), byref(RecLen), pos)

    pos.value += 1

    if ie > 1:
        break

    if Record.ID > 0:
        BEAMRecord = cast(Record, POINTER(BEAMRecord))
        print BEAMRecord

py_sof_cdb_close(0)

exit()

thanks for helping


Solution:

by reading this thread i modified @Mr Temp question

i created a BEAMRecordPointer = POINTER(element.BEAM) and BEAMRecord = cast(Record, POINTER(BEAMRecord)) i rewrite to BAR = cast(byref(Record), BEAMRecordPointer).contents so the solution looks like this

if Record.ID > 0:
        BAR = cast(byref(Record), BEAMRecordPointer).contents
        print BAR

I'm doing it wrong?


Update 1

@eryksun has a really good shothand for the cast() function. Thank you.

Community
  • 1
  • 1
JuKe
  • 663
  • 2
  • 7
  • 20
  • I haven't worked with ctypes yet, therefore I'm not sure if I'm talking s**t right now: You're using cast on classes whose elements are ctypes. Are you sure cast is able to do so? Did you try to loop over the elements of the classes and cast the elements instead of the containing class? – Lord_Gestalter Oct 21 '14 at 10:04
  • 1
    While `cast(byref(Record), POINTER(element.BEAM)).contents` will work, in 2.6+ it's simpler to use `element.Beam.from_buffer(Record)`. – Eryk Sun Oct 22 '14 at 06:36

1 Answers1

3

You could just load the structure into a Union, then access it how you need to:

from ctypes import *

class BEAM(Structure):
    _fields_ = [('NR', c_ulong),
                ("NODE1", c_ulong),
                ("NODE2", c_ulong),
                ("NP", c_ulong),
                ("DL", c_float),
                ("foo", c_ulong),
                ("foobar", c_ulong),
                ("bar", c_ulong),
                ("barfoo", c_ulong)]

class DUMMY(Structure):
    _fields_ = [('ID', c_ulong),
                ("NODE1", c_ulong),
                ("NODE2", c_ulong),
                ("NP", c_ulong),
                ("DL", c_ulong),
                ("foo", c_ulong),
                ("foobar", c_ulong),
                ("bar", c_ulong),
                ("barfoo", c_ulong)]

class Both(Union):
    _fields_ = [('Beam',BEAM),('Dummy',DUMMY)]

x = Both()
x.Dummy.DL = 1056964624
print(x.Beam.DL)

Output:

0.5000009536743164

Or more simply:

from ctypes import *

class DL(Union):
    _fields_ = [('DUMMY',c_ulong),('BEAM',c_float)]

class Hybrid(Structure):
    _fields_ = [('NR', c_ulong),
                ("NODE1", c_ulong),
                ("NODE2", c_ulong),
                ("NP", c_ulong),
                ("DL", DL),
                ("foo", c_ulong),
                ("foobar", c_ulong),
                ("bar", c_ulong),
                ("barfoo", c_ulong)]

x = Hybrid()
x.DL.DUMMY = 1056964624
print(x.DL.BEAM)

(same output)

Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251