linux中动态库的制作和调用的3个实验---第2课 python调用动态库

参考

linux中动态库的制作和调用的3个实验---第1课 动态库的制作.csdn

linux中动态库的制作和调用的3个实验---第2课 python调用动态库.csdn

linux中动态库的制作和调用的3个实验---第3课 nodeJs调用动态库.csdn

python 调用动态库很方便,不用安装其他库

pl_hw_test_win32.py

shell 复制代码
# 32位动态库,只能32位python调用
 & "D:\Program Files\JetBrains\CLion 2023.2\bin\lldb\win\x86\bin\python.exe" .\pl_hw_test_win32.py
python 复制代码
import time
from ctypes import *

# -----------------------------------------------------------------------------
# 预加载依赖
# -----------------------------------------------------------------------------
try:
    CDLL(r"D:\Program Files (x86)\dev-cpp\mingw32\bin\libstdc++-6.dll")
    CDLL(r"D:\Program Files (x86)\dev-cpp\mingw32\bin\libwinpthread-1.dll")
    CDLL(r"D:\soft\vcpkg\installed\x86-windows\bin\libcurl.dll")
    CDLL(r"D:\soft\vcpkg\installed\x86-windows\bin\libssl-3.dll")
    print("依赖库预加载成功!")
except Exception as e:
    print("依赖加载失败:", e)
    exit()

# -----------------------------------------------------------------------------
# 加载DLL:MinGW编译dll 使用 CDLL + CFUNCTYPE(重点改动)
# -----------------------------------------------------------------------------
hw = CDLL(r"D:\workspace\gitee\3\ming_pl_hw\cmake-build-debug\bin\libplHwServer.dll")
hw.pl_hw_get_version.restype = c_uint32
print("DLL Version : 0x%06X" % hw.pl_hw_get_version())

# -----------------------------------------------------------------------------
# 常量
# -----------------------------------------------------------------------------
PL_HW_EVENT_NONE = 0
PL_HW_EVENT_IRQ = 1
PL_HW_EVENT_READ_RDY = 2
PL_HW_EVENT_WRITE_DONE = 3
PL_HW_EVENT_ERROR = 4
PL_HW_EVENT_LOG = 5
PL_HW_IOCTL_WRITE_RDY = 1

# -----------------------------------------------------------------------------
# 数据结构
# -----------------------------------------------------------------------------
class PlHwEventData(Structure):
    _fields_ = [
        ("event", c_int),
        ("code", c_int32),
        ("data", c_void_p),
        ("size", c_uint32),
    ]

# MinGW __cdecl 回调:CFUNCTYPE,不再使用WINFUNCTYPE
CALLBACK = CFUNCTYPE(None, POINTER(PlHwEventData), c_void_p)

# -----------------------------------------------------------------------------
# 函数声明
# -----------------------------------------------------------------------------
hw.pl_hw_open.argtypes = [POINTER(c_char_p), POINTER(c_uint32), c_uint32]
hw.pl_hw_open.restype = c_int32

hw.pl_hw_close.argtypes = []
hw.pl_hw_close.restype = None

hw.pl_hw_set_buffer.argtypes = [c_void_p, c_uint32, c_uint32]
hw.pl_hw_set_buffer.restype = c_int32

hw.pl_hw_set_callback.argtypes = [CALLBACK, c_void_p]
hw.pl_hw_set_callback.restype = c_int32

hw.pl_hw_ioctl.argtypes = [c_int, c_void_p]
hw.pl_hw_ioctl.restype = c_int32

# -----------------------------------------------------------------------------
# 回调【关键优化:增加try-except捕获异常】
# DLL子线程抛出未捕获Python异常 = 直接栈破坏崩溃
# -----------------------------------------------------------------------------
def on_event(event, user):
    try:
        evt = event.contents
        if evt.event == PL_HW_EVENT_READ_RDY:
            print("[Event] READ_READY")
        elif evt.event == PL_HW_EVENT_WRITE_DONE:
            print("[Event] WRITE_DONE")
        elif evt.event == PL_HW_EVENT_IRQ:
            print("[Event] IRQ")
        elif evt.event == PL_HW_EVENT_ERROR:
            print("[Event] ERROR")
        else:
            print("[Event]", evt.event)
    except Exception as e:
        print(f"Callback inner exception: {e}")

# 全局持久回调对象,防止GC回收
callback = CALLBACK(on_event)

# -----------------------------------------------------------------------------
# Dump工具
# -----------------------------------------------------------------------------
def dump_buffer(title, buf, offset, size):
    print(f"\n{title}")
    line = []
    for i in range(size):
        val = buf[offset + i]
        line.append(f"{val:02X}")
        if (i + 1) % 16 == 0:
            print(" ".join(line))
            line.clear()
    if line:
        print(" ".join(line))

# -----------------------------------------------------------------------------
# Main
# -----------------------------------------------------------------------------
def main():
    print("========== pl_hw win32 test ==========")

    keys = (c_char_p * 1)()
    keys[0] = b"comPort"
    values = (c_uint32 * 1)()
    values[0] = 1

    ret = hw.pl_hw_open(keys, values, 1)
    print("pl_hw_open =", ret)
    if ret != 0:
        print("open failed")
        return

    # 注册回调
    hw.pl_hw_set_callback(callback, None)
    # 共享缓冲区,全局生命周期
    gBuffer = (c_uint8 * 64)()
    hw.pl_hw_set_buffer(gBuffer, 32, 64)
    # 填充发送区
    for i in range(32):
        gBuffer[32 + i] = i
    dump_buffer("Write Buffer:", gBuffer, 32, 32)
    print("\nPL_HW_IOCTL_WRITE_RDY")
    hw.pl_hw_ioctl(PL_HW_IOCTL_WRITE_RDY, None)
    dump_buffer("Read Buffer:", gBuffer, 0, 32)
    time.sleep(1)
    time.sleep(0.2)
    hw.pl_hw_close()
    print("closed")

if __name__ == "__main__":
    main()

zynq_hw_test_py2.py

python 复制代码
# -*- coding: utf-8 -*-
import time
from ctypes import *


hw = CDLL("./libplHwServer_petalinux_release.so")

hw.pl_hw_get_version.restype = c_uint32

print "DLL Version : 0x%06X" % hw.pl_hw_get_version()

# -----------------------------------------------------------------------------
# 常量
# -----------------------------------------------------------------------------

PL_HW_EVENT_NONE = 0
PL_HW_EVENT_IRQ = 1
PL_HW_EVENT_READ_RDY = 2
PL_HW_EVENT_WRITE_DONE = 3
PL_HW_EVENT_ERROR = 4
PL_HW_EVENT_LOG = 5

PL_HW_IOCTL_WRITE_RDY = 1

# -----------------------------------------------------------------------------
# 数据结构
# -----------------------------------------------------------------------------

class PlHwEventData(Structure):
    _fields_ = [
        ("event", c_int),
        ("code", c_int32),
        ("data", c_void_p),
        ("size", c_uint32),
    ]

# Linux 使用 CFUNCTYPE
CALLBACK = CFUNCTYPE(
    None,
    POINTER(PlHwEventData),
    c_void_p
)

# -----------------------------------------------------------------------------
# 函数声明
# -----------------------------------------------------------------------------

hw.pl_hw_open.argtypes = [
    POINTER(c_char_p),
    POINTER(c_uint32),
    c_uint32
]
hw.pl_hw_open.restype = c_int32

hw.pl_hw_close.argtypes = []
hw.pl_hw_close.restype = None

hw.pl_hw_set_buffer.argtypes = [
    c_void_p,
    c_uint32,
    c_uint32
]
hw.pl_hw_set_buffer.restype = c_int32

hw.pl_hw_set_callback.argtypes = [
    CALLBACK,
    c_void_p
]
hw.pl_hw_set_callback.restype = c_int32

hw.pl_hw_ioctl.argtypes = [
    c_int,
    c_void_p
]
hw.pl_hw_ioctl.restype = c_int32

# -----------------------------------------------------------------------------
# 回调函数
# -----------------------------------------------------------------------------
def on_event(event, user):
    evt = event.contents

    if evt.event == PL_HW_EVENT_READ_RDY:
        print "[Event] READ_READY"
    elif evt.event == PL_HW_EVENT_WRITE_DONE:
        print "[Event] WRITE_DONE"
    elif evt.event == PL_HW_EVENT_IRQ:
        print "[Event] IRQ"
    elif evt.event == PL_HW_EVENT_ERROR:
        print "[Event] ERROR"
    else:
        print "[Event]", evt.event


callback = CALLBACK(on_event)

# -----------------------------------------------------------------------------
# Dump缓冲区打印
# -----------------------------------------------------------------------------
def dump_buffer(title, buf, offset, size):
    print title
    for i in range(size):
        print "%02X " % buf[offset + i],
        if (i + 1) % 16 == 0:
            print ""
    if size % 16 != 0:
        print ""

# -----------------------------------------------------------------------------
# Main
# -----------------------------------------------------------------------------
print "========== pl_hw test (Linux/Petalinux Python2) =========="

keys = (c_char_p * 1)()
keys[0] = b"comPort"

values = (c_uint32 * 1)()
values[0] = 1

ret = hw.pl_hw_open(keys, values, 1)
print "pl_hw_open =", ret

hw.pl_hw_set_callback(callback, None)

# 64字节缓冲区
gBuffer = (c_uint8 * 64)()

# [0~31] Read Buffer
# [32~63] Write Buffer
hw.pl_hw_set_buffer(gBuffer, 32, 64)

# 填充发送区
for i in range(32):
    gBuffer[32 + i] = i

dump_buffer("Write Buffer:", gBuffer, 32, 32)

print "\nPL_HW_IOCTL_WRITE_RDY"
hw.pl_hw_ioctl(PL_HW_IOCTL_WRITE_RDY, None)

dump_buffer("Read Buffer:", gBuffer, 0, 32)

time.sleep(1)

hw.pl_hw_close()

zynq_hw_test_py3.py

python 复制代码
import time
from ctypes import *

# 加载DLL
# -----------------------------------------------------------------------------
hw = CDLL(r"./libplHwServer_petalinux_release.so")
hw.pl_hw_get_version.restype = c_uint32
print("DLL Version : 0x%06X" % hw.pl_hw_get_version())
# -----------------------------------------------------------------------------
# 常量
# -----------------------------------------------------------------------------
PL_HW_EVENT_NONE = 0
PL_HW_EVENT_IRQ = 1
PL_HW_EVENT_READ_RDY = 2
PL_HW_EVENT_WRITE_DONE = 3
PL_HW_EVENT_ERROR = 4
PL_HW_EVENT_LOG = 5

PL_HW_IOCTL_WRITE_RDY = 1

# -----------------------------------------------------------------------------
# 数据结构
# -----------------------------------------------------------------------------

class PlHwEventData(Structure):
    _fields_ = [
        ("event", c_int),
        ("code", c_int32),
        ("data", c_void_p),
        ("size", c_uint32),
    ]


CALLBACK = CFUNCTYPE(
    None,
    POINTER(PlHwEventData),
    c_void_p
)

# -----------------------------------------------------------------------------
# 函数声明
# -----------------------------------------------------------------------------

hw.pl_hw_open.argtypes = [
    POINTER(c_char_p),
    POINTER(c_uint32),
    c_uint32
]
hw.pl_hw_open.restype = c_int32

hw.pl_hw_close.argtypes = []
hw.pl_hw_close.restype = None

hw.pl_hw_set_buffer.argtypes = [
    c_void_p,
    c_uint32,
    c_uint32
]
hw.pl_hw_set_buffer.restype = c_int32

hw.pl_hw_set_callback.argtypes = [
    CALLBACK,
    c_void_p
]
hw.pl_hw_set_callback.restype = c_int32

hw.pl_hw_ioctl.argtypes = [
    c_int,
    c_void_p
]
hw.pl_hw_ioctl.restype = c_int32

# -----------------------------------------------------------------------------
# 回调
# -----------------------------------------------------------------------------

def on_event(event, user):
    evt = event.contents

    if evt.event == PL_HW_EVENT_READ_RDY:
        print("[Event] READ_READY")

    elif evt.event == PL_HW_EVENT_WRITE_DONE:
        print("[Event] WRITE_DONE")

    elif evt.event == PL_HW_EVENT_IRQ:
        print("[Event] IRQ")

    elif evt.event == PL_HW_EVENT_ERROR:
        print("[Event] ERROR")

    else:
        print("[Event]", evt.event)


callback = CALLBACK(on_event)

# -----------------------------------------------------------------------------
# Dump
# -----------------------------------------------------------------------------

def dump_buffer(title, buf, offset, size):
    print(title)

    for i in range(size):
        print("%02X " % buf[offset + i], end="")
        if (i + 1) % 16 == 0:
            print()

    if size % 16 != 0:
        print()

# -----------------------------------------------------------------------------
# Main
# -----------------------------------------------------------------------------

print("========== pl_hw mock ==========")

keys = (c_char_p * 1)()
keys[0] = b"comPort"

values = (c_uint32 * 1)()
values[0] = 1

ret = hw.pl_hw_open(keys, values, 1)
print("pl_hw_open =", ret)

hw.pl_hw_set_callback(callback, None)

# 64字节缓冲区
gBuffer = (c_uint8 * 64)()

# [0~31] Read Buffer
# [32~63] Write Buffer
hw.pl_hw_set_buffer(gBuffer, 32, 64)

# 填充发送区
for i in range(32):
    gBuffer[32 + i] = i

dump_buffer("Write Buffer:", gBuffer, 32, 32)

print("\nPL_HW_IOCTL_WRITE_RDY")

hw.pl_hw_ioctl(PL_HW_IOCTL_WRITE_RDY, None)

dump_buffer("Read Buffer:", gBuffer, 0, 32)

time.sleep(1)

hw.pl_hw_close()

测试

bash 复制代码
root@ant:~# python3  zynq_hw_test_py3.py
DLL Version : 0x010100
========== pl_hw mock ==========
pl_hw_open = 0
Write Buffer:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F

PL_HW_IOCTL_WRITE_RDY
[Event] WRITE_DONE
Read Buffer:
01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10
11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20
相关推荐
味悲17 小时前
Linux 环境下 DNS 服务器搭建
linux·运维·服务器
dok1218 小时前
Johannes 《Linux内核模块与设备驱动开发:编写Linux驱动程序》 (7)open,release (8) write read
linux
皮卡狮18 小时前
进程间通信:认识匿名管道和进程池实现
linux
feasibility.18 小时前
wsl安装Ubuntu方法(含网络不稳定处理)
linux·运维·windows·ubuntu
‎ദ്ദിᵔ.˛.ᵔ₎19 小时前
linux进程
linux
湿滑路面19 小时前
硅基聊天室——如何用supervisor优雅的管理服务进程
linux·前端·python
我命由我1234520 小时前
Windows 操作系统 - 符号链接
linux·运维·windows·系统架构·操作系统·运维开发·系统
kdxiaojie20 小时前
Linux 驱动研究 —— V4L2 (15)
linux·运维·笔记·学习
happyh h h h p p p p1 天前
LVS 项目完整知识点总结
linux·服务器·数据库