You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C++嵌入的Python环境中传入本地创建的IDispatch COM对象并实现访问与事件处理

如何在C++嵌入的Python环境中传入本地创建的IDispatch COM对象并实现访问与事件处理

嗨,我来帮你搞定这个在C嵌入Python里传本地COM对象的问题!你之前用Dispatch的思路不对,因为win32com.client.Dispatch是用来从ProgID新建COM对象的,不是用来包装你已经在C里创建好的IDispatch指针的。下面给你一步步讲怎么改:

核心思路

咱们得把C++里的IDispatch对象直接包装成Python能识别的win32com对象,然后把它注入到Python的全局命名空间里,这样Python脚本就能直接用它,还能绑定事件处理器。

具体代码修改

首先,你得调整你的PassComObjectToPython函数,别再去调用Dispatch了,改用pythoncom提供的函数把IDispatch转换成Python对象,再放到Python的全局环境里。代码大概是这样:

#include <python.h>
#include <pythoncom.h> // 必须包含这个头文件,编译时要链接pythoncom.lib和pywintypes.lib

void PythonEng::PassComObjectToPython(const CString& ObjName, IDispatch* pMyComObject) {
    // 划重点:Py_Initialize和PyCOM_Initialize只需要初始化一次,别每次传对象都调用!
    static bool isPythonInitialized = false;
    if (!isPythonInitialized) {
        Py_Initialize();
        PyCOM_Initialize(); // 初始化pythoncom环境,win32com全靠它
        isPythonInitialized = true;
    }

    // 把C++的IDispatch对象转换成Python可识别的对象
    PyObject *pPyObj = PyCom_PyObjectFromIUnknown(
        (IUnknown*)pMyComObject, 
        IID_IDispatch, 
        TRUE // 让Python自动管理这个COM对象的引用计数
    );

    if (pPyObj) {
        // 把这个Python对象注入到__main__模块的全局命名空间
        PyObject *pMainModule = PyImport_AddModule("__main__");
        if (pMainModule) {
            PyObject *pMainDict = PyModule_GetDict(pMainModule);
            // 用你指定的ObjName作为全局变量名,把对象放进去
            PyDict_SetItemString(pMainDict, ObjName.GetString(), pPyObj);
        }
        Py_DECREF(pPyObj); // 释放引用,避免内存泄漏
    }
}

怎么在Python里使用这个对象

现在你在Python脚本里就可以直接用这个对象了!比如你传的ObjName是"Dialogs",那Python里直接写:

# 不用再Dispatch了,直接用全局的Dialogs对象
Dialogs.Message(0, "Hello from C++ passed object!")

事件处理的实现

如果要处理这个COM对象的事件,用win32com.client的WithEvents就行,举个例子:

import win32com.client

# 定义你的事件处理器类,方法名要和COM对象的事件名对应
class DialogEventHandler:
    def OnMessageClicked(self, returnCode):
        # 这里写你处理事件的逻辑
        print(f"用户点击了消息框,返回码:{returnCode}")

# 把事件处理器绑定到我们从C++传过来的COM对象上
handler = DialogEventHandler()
win32com.client.WithEvents(Dialogs, handler)

一些必须注意的细节

  • 一定要链接pythoncom.lib和pywintypes.lib,不然编译会报错,这两个库在你的Python安装目录的libs文件夹里
  • 绝对不要多次调用Py_Initialize和PyCOM_Initialize,初始化一次就够了,重复初始化会导致各种奇怪的问题
  • 要确保你的C++ COM对象pMyComObject的生命周期足够长,直到Python脚本完全不再使用它,不然会出现访问非法内存的崩溃问题
  • 记得正确管理Python对象的引用计数,比如用Py_DECREF释放不再需要的对象,不然会有内存泄漏的风险

备注:内容来源于stack exchange,提问作者Emil Dimitrov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 12:09:33