我能够在我的 MSVS Windows C++ 应用程序中使用嵌入式 Python,并且运行良好。我可以创建 com 对象并像这样使用它们:
import win32com.client as win32
Dialogs = win32.Dispatch('DialogControls.Dialogs')
Dialogs.Message(0, "Hello from C++ object")`
我有许多在 C++ 应用程序中创建的对象,我想在 Python 中访问它们以及它们的事件处理程序。以前我使用 VBScript,并且可以使用 AddObjectEx 做到这一点,但在 Python 中我没有成功。我尝试过类似的方法,但它不起作用。 pComObject 为 NULL。
void PythonEng::PassComObjectToPython(const CString& ObjName, IDispatch* pMyComObject) {
Py_Initialize();
PyObject* pModule = PyImport_ImportModule("win32com.client");
if (pModule) {
PyObject* pDict = PyModule_GetDict(pModule);
PyObject* pDispatch = PyDict_GetItemString(pDict, "Dispatch");
if (pDispatch && PyCallable_Check(pDispatch)) {
PyObject* pArgs = PyTuple_Pack(1, PyLong_FromVoidPtr(pMyComObject));
PyObject* pComObject = PyObject_CallObject(pDispatch, pArgs);
Py_DECREF(pArgs);
if (pComObject) {
PyObject* pGlobals = PyDict_New();
CT2CA pszConvertedAnsiString(ObjName);
std::string strObjName(pszConvertedAnsiString);
PyDict_SetItemString(pGlobals, strObjName.c_str(), pComObject);
Py_DECREF(pComObject);
// Now you can execute Python code that uses my_com_object
PyRun_String("MyGen.Idle(10)", Py_file_input, pGlobals, pGlobals);
Py_DECREF(pGlobals);
}
}
Py_DECREF(pModule);
}
Py_Finalize();
}
我尝试使用上面的代码添加我的 com 对象并从嵌入式 Python 中使用它。
这里有一些想法给你:
#define NOMINMAX
#define WIN32_LEAN_AND_MEAN
#include <cassert>
#include <atlcom.h>
#include <atlbase.h>
#include <Windows.h>
#include <MsXml6.h>
#include <string>
//-----------------------------------------------------------------------------
// ALL your legacy + COM code
class legacy_cpp_com_code
{
public:
legacy_cpp_com_code()
{
// make sure ::CoInitializeEx has been called etc.
auto hr = m_xmlDocument.CoCreateInstance(CLSID_DOMDocument60, nullptr, CLSCTX_INPROC_SERVER);
}
std::wstring GetName()
{
ATL::CComBSTR str;
m_xmlDocument->get_baseName(&str);
return { static_cast<LPWSTR>(str) };
}
void some_method()
{
}
private:
ATL::CComPtr<IXMLDOMDocument> m_xmlDocument;
};
// Or you can use these kind of COM factory methods, to later hide the COM objects in "C" API calls.
ATL::CComPtr<IXMLDOMDocument> GetXmlDocument()
{
// initialization from lamda into a static com pointer (this will be released when the library unloads)
static ATL::CComPtr<IXMLDOMDocument> xmlDocument = []
{
ATL::CComPtr<IXMLDOMDocument> localXmlDocument;
auto hr = localXmlDocument.CoCreateInstance(CLSID_DOMDocument60, nullptr, CLSCTX_INPROC_SERVER);
return localXmlDocument;
}();
return xmlDocument;
}
//-----------------------------------------------------------------------------
// Your "new" scripting API
legacy_cpp_com_code instance;
extern "C"
{
const wchar_t* GetName(void)
{
return instance.GetName().c_str();
// or
// GetXmlDocument().GetName().c_str();
}
void some_method(void)
{
instance.some_method();
}
}