Windows11/64下如何让Python调用PortMidi C库?
Windows11 x64下Python对接PortMidi的问题解决指南
系统库路径配置
- 将编译好的
portmidi.dll放到以下任意位置:- Python安装目录下的
DLLs文件夹 - 系统
C:\Windows\System32文件夹 - 或把dll所在目录添加到系统环境变量
PATH,添加后重启终端/IDE生效
- Python安装目录下的
- 对于
portmidi.lib,可将其放入VS默认库目录(如C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\[版本号]\lib\x64,路径根据你的VS版本调整),或在后续调用时手动指定lib路径。
ctypes方案:Pm_Write访问冲突排查
PortMidi的Pm_Write函数原型为:
PmError Pm_Write(PmStream *stream, const PmEvent *buffer, int32_t length);
按以下步骤排查问题:
确认
PmEvent结构体定义正确
x64下必须匹配PortMidi的类型定义,ctypes中应写为:class PmEvent(ctypes.Structure): _fields_ = [("message", ctypes.c_uint32), ("timestamp", ctypes.c_uint32)]注意使用
c_uint32,避免因类型大小不匹配导致指针越界。检查调用参数的合法性
- 确保
stream是Pm_OpenOutput返回的有效指针,调用Pm_OpenOutput后需检查返回值是否为0(成功) - 传递事件数组时,直接传入数组对象即可,无需手动用
byref或pointer转换:# 创建2个事件的数组 events = (PmEvent * 2)() events[0].message = 0x904040 # 示例NoteOn消息 events[0].timestamp = 0 # 直接传数组,ctypes自动转为指针 pm.Pm_Write(stream, events, 2)
- 确保
指定正确的调用约定
PortMidi默认使用cdecl调用约定,加载dll时需明确指定:pm = ctypes.CDLL("portmidi.dll", ctypes.CDECL)不要用
ctypes.windll(默认stdcall),避免调用栈异常。验证初始化流程
确保Pm_Initialize()返回0(初始化成功),设备枚举、打开输出流的每一步都检查返回值,排除前置操作导致的非法指针。
Cython方案:编译错误修复
基于过时的pyportmidi修改,按以下步骤调整:
修正setup.py配置
明确指定头文件、库文件路径,匹配x64编译选项:from setuptools import setup, Extension from Cython.Build import cythonize ext_modules = [ Extension( "pyportmidi", sources=["pyportmidi.pyx"], include_dirs=["你的PortMidi头文件目录"], libraries=["portmidi"], library_dirs=["你的PortMidi库文件目录"], extra_compile_args=["/MD"], # 与PortMidi编译时的多线程DLL选项一致 ) ] setup( name="pyportmidi", ext_modules=cythonize(ext_modules) )修复pyx文件的类型与语法
- 在pyx文件开头添加标准类型定义,适配x64:
cdef extern from "<stdint.h>": ctypedef int int32_t ctypedef unsigned int uint32_t - 正确定义
PmEvent结构体:cdef struct PmEvent: uint32_t message uint32_t timestamp - 确保函数声明与PortMidi原型完全一致,比如
Pm_Write:cdef extern from "portmidi.h": int Pm_Write(void *stream, const PmEvent *buffer, int32_t length)
- 在pyx文件开头添加标准类型定义,适配x64:
使用正确的编译环境
打开VS的x64 Developer Command Prompt,执行编译命令:python setup.py build_ext --inplace必须用x64编译环境,确保与Python、PortMidi的位数一致,避免链接错误。
内容的提问来源于stack exchange,提问作者user1441998
相关产品推荐
相关产品推荐

