Reading double c structures of Dll with Ctypes in Python

Question:

I’v done researched a lot about this problem.. But there’s no where and I couldn’t find it. I’m trying to call double c structure by calling c dll.

My question is, did i right way to declare “Class Structure” in python? I couldn’t think that i’m right on my way. Because even though the Functions that I want to call from dll, It didn’t come output anything.

[Visual C++/C]

I did try to C Syntax code,

typedef sturct {
    int nBoardNum;
    struct{
        char  pBoardName[16];
        int   nBoardID;
    }BOARDINDEX[8];
}AAPBOARDINFO, *PAAPBOARDINFO;

HANDLE AcapOpen(char* cpBoardName, int nBoardNo, int nCh)

[Python]

I changed Python Syntax like this.

import ctypes as c

class BOARDINDEX(c.Structure):
    _field_ = [("nBoardName", c.c_char_p * 16),("nBoardID", c.c_int)]

class AAPBOARDINFO(c.Structure):
    _field_ = [("nBoardNum", c.c_int), ("BOARDINDEX", BOARDINDEX * 8)]

AapLib2 = c.WinDLL("AapLib2.dll")

BoardName = ["ABC","FWD","HGW"]
BoardNo = 0
ch = 1

output = Open(BoardName, BoardNo, ch)

def Open(BoardName, BoardNo, ch)

    func = AapLib2.AcapOpen
    func.argtypes = [c.POINTER(BOARDINDEX),c.c_int, c.c_int]
    func.restype = c.c_int

    ref = BOARDINDEX()

    res = func(c.byref(ref.nBoardName),BoardNo, ch)
    return res

Nothing outcomes when call Open() function…

please consider my request and any answer would be great…

Asked By: whatagreatdeal

||

Answers:

Everything you need to know, can be found in the [Python.Docs]: ctypes – A foreign function library for Python.

There are a couple of problems with the code:

  1. Structure members are specified in the _fields_ (not _field_) attribute

  2. char pBoardName[16] maps to ctypes.c_char * 16 (not c_char_p)

  3. HANDLE should be mapped to wintypes.HANDLE

  4. Function prototype differs between C and Python

  5. Using globals like AapLib2 is best to be be avoided, but I left them unchanged as they are outside the question scope

#1. and #3. will generate Undefined Behavior! Check [SO]: C function called from Python via ctypes returns incorrect value (@CristiFati’s answer) for more details.

Here’s a modified version of your code. Needless to say that I didn’t actually test it, as I don’t have the .dll:

#!/usr/bin/env python

import ctypes as cts
import sys
from ctypes import wintypes as wts


class BOARDINDEX(cts.Structure):
    _fields_ = [
        ("nBoardName", cts.c_char * 16),
        ("nBoardID", cts.c_int),
    ]


class AAPBOARDINFO(cts.Structure):
    _fields_ = [
        ("nBoardNum", cts.c_int),
        ("BOARDINDEX", BOARDINDEX * 8),
    ]


def open_board(board_name, board_no, ch):
    AcapOpen = aaplib2.AcapOpen
    AcapOpen.argtypes = (cts.c_char_p, cts.c_int, cts.c_int)
    AcapOpen.restype = wts.HANDLE
    ref = BOARDINDEX(board_name, board_no)  # Probably this line should be replaced by the 3 (commented) ones below (AcapGetBoardInfo prototype would have to be specified as well)
    #abi = AAPBOARDINFO()
    #AcapGetBoardInfo(cts.byref(abi))
    #ref = abi.BOARDINDEX[0]
    res = AcapOpen(ref.nBoardName, ref.nBoardID, ch)
    return res


def main(*argv):
    board_names = (
        "ABC",
        "FWD",
        "HGW",
    )
    board_no = 0
    ch = 1
    aaplib2 = cts.WinDLL("AapLib2.dll")
    output = open_board(board_names[0], board_no, ch)
    print(output)


if __name__ == "__main__":
    print("Python {:s} {:03d}bit on {:s}n".format(" ".join(elem.strip() for elem in sys.version.split("n")),
                                                   64 if sys.maxsize > 0x100000000 else 32, sys.platform))
    rc = main(*sys.argv[1:])
    print("nDone.n")
    sys.exit(rc)

Let me know how this works out.

Answered By: CristiFati
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.