参考
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