Встроить интерпретатор Python в (C ++) приложение на Windows - PullRequest
3 голосов
/ 04 января 2011

Я строю оконное приложение, написанное на C ++.Я хотел бы использовать несколько библиотек Python.

Мне здесь не нужно какое-то необычное взаимодействие с Python.Мой метод такой:

  • Открыть поток для запуска интерпретатора Python.

  • Отправка команд из C ++ в интерпретатор Python.C ++ может потребоваться написать несколько промежуточных файлов для взаимодействия.

Этот метод грязный, но он будет работать для многих сред, подобных интерпретатору, например, gnuplot, lua.

Мой вопрос заключается в том, какие APIтам для меня, чтобы использовать для этой задачи.Может быть, мне нужен Win32 API?

РЕДАКТИРОВАТЬ: Мне не нужен специфический для Python.Я действительно хочу общий метод.Чтобы мое приложение могло также работать с gnuplot и т. Д.

Ответы [ 4 ]

4 голосов
/ 04 января 2011

Если у вас есть исходный дистрибутив Python, вы можете посмотреть в каталоге Demo/embed примеры.Соответствующая документация здесь .

2 голосов
/ 05 февраля 2012

Я собрал консольное приложение IActiveScript C ++ ATL «Hello World», которое:

  • Реализует новый класс с именем CSimpleScriptSite
  • Производные от IActiveScriptSite и IActiveScriptSiteWindow
  • Вызывает CoCreateInstance на Python движке с IActiveSite интерфейсом
  • Выполняет оператор Python print 'Hello World. 5 squared is: ' + str(5 * 5)
  • Не имеет обработки ошибок для плохих Python. Вам следует обратиться к MSDN IActiveScriptError
  • Имеет функции с заглушкой return S_OK; Реализация
  • У меня установлен Python 2.6 , но вы можете использовать любой интерпретатор Python.
  • Я использовал Python для расширений Windows с ProgID Python, который дает интерпретатору Python IActiveScript оболочки
  • Однако вы можете заставить код работать с любым интерпретатором Python, который поддерживает IActiveScript, вам просто нужно обновить ProgID (например, Python.AXScript.2)

Вот пример Python Hello World:

#include <atlbase.h>
#include <activscp.h>

#define CHECKHR(stmt) \
    { \
        HRESULT hr = S_OK; \
        if (FAILED(hr = (stmt))) { return hr; } \
    }

class CSimpleScriptSite :
    public IActiveScriptSite,
    public IActiveScriptSiteWindow
{
public:
    CSimpleScriptSite() : m_cRefCount(1), m_hWnd(NULL) { ZeroMemory(&m_clsidScriptEngine, sizeof(m_clsidScriptEngine)); }

    // IUnknown

    STDMETHOD_(ULONG, AddRef)();
    STDMETHOD_(ULONG, Release)();
    STDMETHOD(QueryInterface)(REFIID riid, void **ppvObject);

    // IActiveScriptSite

    STDMETHOD(GetLCID)(LCID *plcid){ *plcid = 0; return S_OK; }
    STDMETHOD(GetItemInfo)(LPCOLESTR pstrName, DWORD dwReturnMask, IUnknown **ppiunkItem, ITypeInfo **ppti) { return TYPE_E_ELEMENTNOTFOUND; } 
    STDMETHOD(GetDocVersionString)(BSTR *pbstrVersion) { *pbstrVersion = SysAllocString(L"1.0"); return S_OK; }
    STDMETHOD(OnScriptTerminate)(const VARIANT *pvarResult, const EXCEPINFO *pexcepinfo) { return S_OK; }
    STDMETHOD(OnStateChange)(SCRIPTSTATE ssScriptState) { return S_OK; }
    STDMETHOD(OnScriptError)(IActiveScriptError *pIActiveScriptError) { return S_OK; }
    STDMETHOD(OnEnterScript)(void) { return S_OK; }
    STDMETHOD(OnLeaveScript)(void) { return S_OK; }

    // IActiveScriptSiteWindow

    STDMETHOD(GetWindow)(HWND *phWnd) { *phWnd = m_hWnd; return S_OK; }
    STDMETHOD(EnableModeless)(BOOL fEnable) { return S_OK; }

    // Miscellaneous

    HRESULT CloseScriptEngine();
    HRESULT Evaluate(LPCOLESTR szScript, VARIANT *pResult, LPCOLESTR strItemName);
    HRESULT Execute(LPCOLESTR szScript, LPCOLESTR strItemName);
    HRESULT OpenScriptEngine(CLSID &rclsid);
    HRESULT OpenScriptEngine(LPCOLESTR szScriptEngine);
    HRESULT SetWindow(HWND hWnd) { m_hWnd = hWnd; }

private:
    CComPtr<IActiveScript> m_ptrIActiveScript;
    CLSID                  m_clsidScriptEngine;
    ULONG                  m_cRefCount;
    HWND                   m_hWnd;
};

STDMETHODIMP_(ULONG) CSimpleScriptSite::AddRef()
{
    return InterlockedIncrement(&m_cRefCount);
}

STDMETHODIMP_(ULONG) CSimpleScriptSite::Release()
{
    if (!InterlockedDecrement(&m_cRefCount))
    {
        delete this;
        return 0;
    }
    return m_cRefCount;
}

STDMETHODIMP CSimpleScriptSite::QueryInterface(REFIID riid, void **ppvObject)
{
    if (riid == IID_IUnknown || riid == IID_IActiveScriptSiteWindow)
    {
        *ppvObject = (IActiveScriptSiteWindow *) this;
        AddRef();
        return NOERROR;
    }
    if (riid == IID_IActiveScriptSite)
    {
        *ppvObject = (IActiveScriptSite *) this;
        AddRef();
        return NOERROR;
    }
    return E_NOINTERFACE;
}

HRESULT CSimpleScriptSite::OpenScriptEngine(CLSID &rclsid)
{
    m_ptrIActiveScript = NULL;
    CHECKHR(CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, IID_IActiveScript, (void **) &m_ptrIActiveScript));
    CHECKHR(m_ptrIActiveScript->SetScriptSite(this));
    CComPtr<IActiveScriptParse> ptrIActiveScriptParse;
    CHECKHR(m_ptrIActiveScript->QueryInterface(IID_IActiveScriptParse, (void **) &ptrIActiveScriptParse));
    CHECKHR(ptrIActiveScriptParse->InitNew());
    m_clsidScriptEngine = rclsid;
    return S_OK;
}

HRESULT CSimpleScriptSite::OpenScriptEngine(LPCOLESTR szScriptEngine)
{
    CLSID clsid;
    CHECKHR(CLSIDFromProgID(szScriptEngine, &clsid));
    return OpenScriptEngine(clsid);
}

HRESULT CSimpleScriptSite::CloseScriptEngine()
{
    if (!m_ptrIActiveScript) { return S_OK; }
    CHECKHR(m_ptrIActiveScript->SetScriptState(SCRIPTSTATE_CLOSED));
    m_ptrIActiveScript = NULL;
    return S_OK;
}

HRESULT CSimpleScriptSite::Evaluate(LPCOLESTR szScript, VARIANT *pResult, LPCOLESTR strItemName)
{
    if (!m_ptrIActiveScript) { return E_POINTER; }
    if (!pResult) { return E_INVALIDARG; }
    EXCEPINFO ei = {0};
    CComPtr<IActiveScriptParse> ptrIActiveScriptParse;
    CHECKHR(m_ptrIActiveScript->QueryInterface(IID_IActiveScriptParse, (void **) &ptrIActiveScriptParse));
    CHECKHR(ptrIActiveScriptParse->ParseScriptText(szScript, strItemName, NULL, NULL, 0, 0, SCRIPTTEXT_ISEXPRESSION, pResult, &ei));
    return m_ptrIActiveScript->SetScriptState(SCRIPTSTATE_CONNECTED);
}

HRESULT CSimpleScriptSite::Execute(LPCOLESTR szScript, LPCOLESTR strItemName)
{
    if (!m_ptrIActiveScript) { return E_POINTER; }
    EXCEPINFO ei = {0};
    CComPtr<IActiveScriptParse> ptrIActiveScriptParse;
    CHECKHR(m_ptrIActiveScript->QueryInterface(IID_IActiveScriptParse, (void **) &ptrIActiveScriptParse));
    CHECKHR(ptrIActiveScriptParse->ParseScriptText(szScript, strItemName, NULL, NULL, 0, 0, 0L, NULL, &ei));
    return m_ptrIActiveScript->SetScriptState(SCRIPTSTATE_CONNECTED);
}

int _tmain(int argc, _TCHAR* argv[])
{
    HRESULT hr = S_OK;
    hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
    CSimpleScriptSite *pScriptSite = new CSimpleScriptSite();
    hr = pScriptSite->OpenScriptEngine(OLESTR("Python"));
    hr = pScriptSite->Execute(OLESTR("print 'Hello World. 5 squared is: ' + str(5 * 5)"), NULL);
    hr = pScriptSite->CloseScriptEngine();
    hr = pScriptSite->Release();
    ::CoUninitialize();
    return 0;
}
2 голосов
/ 04 января 2011

ActivePython (http://www.activestate.com/activepython/downloads) устанавливается как движок ActiveScript. ProgID - это Python.AXScript.2. Поэтому его можно использовать с COM через стандартный интерфейс IActiveScript Windows.

Распределение - это другое дело. Либо вы требуете от клиентов, или вы можете попытаться извлечь сочные кусочки из пакета ActiveState, или, возможно, есть официальный способ сделать автоматическую установку ...

0 голосов
/ 04 января 2011

Вы также можете использовать буст Python: http://www.boost.org/doc/libs/1_45_0/libs/python/doc/index.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...