Anonymous
Легко реализовать интерфейс только idispatch в C ++
Сообщение
Anonymous » 01 июн 2025, 03:26
Я определил следующий интерфейс только idispatch в моем проекте C#: < /p>
Код: Выделить всё
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[Guid("3532C4E8-D320-487C-8BD4-F448B94B9E83")]
public interface ICppRuntimeApi2
{
[DispId(1)]
bool TestCallback(string pasteType);
}
После импорта библиотеки сгенерированных типов в моем проекте C ++ я могу реализовать свой iCppruntimeapi2 свободно, как, например:
Код: Выделить всё
class CppRuntimeApiImpl2 : public MyProject::ICppRuntimeApi2 {
public:
CppRuntimeApiImpl2() : refCount(1) {}
// IUnknown methods
HRESULT __stdcall QueryInterface(REFIID riid, void** ppv) override {
if (riid == IID_IUnknown || riid == IID_IDispatch || riid == __uuidof(MyProject::ICppRuntimeApi2)) {
*ppv = static_cast(this);
}
else {
*ppv = nullptr;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
ULONG __stdcall AddRef() override {
return InterlockedIncrement(&refCount);
}
ULONG __stdcall Release() override {
ULONG count = InterlockedDecrement(&refCount);
if (count == 0) {
delete this;
}
return count;
}
// IDispatch methods
HRESULT __stdcall GetTypeInfoCount(UINT* pctinfo) override {
*pctinfo = 0;
return S_OK;
}
HRESULT __stdcall GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) override {
*ppTInfo = nullptr;
return E_NOTIMPL;
}
HRESULT __stdcall GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId) override {
if (cNames != 1) return DISP_E_UNKNOWNNAME;
if (_wcsicmp(rgszNames[0], L"TestCallback") == 0) {
rgDispId[0] = 1;
return S_OK;
}
return DISP_E_UNKNOWNNAME;
}
HRESULT __stdcall Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr) override {
if (dispIdMember == 1) {
if (pDispParams->cArgs != 1 || pDispParams->rgvarg[0].vt != VT_BSTR) {
return DISP_E_BADPARAMCOUNT;
}
std::wstring pasteType(pDispParams->rgvarg[0].bstrVal, SysStringLen(pDispParams->rgvarg[0].bstrVal));
bool result = TestCallback(pasteType);
if (pVarResult) {
pVarResult->vt = VT_BOOL;
pVarResult->boolVal = result ? VARIANT_TRUE : VARIANT_FALSE;
}
return S_OK;
}
return DISP_E_MEMBERNOTFOUND;
}
// ICppRuntimeApi2 method
bool TestCallback(const std::wstring& pasteType) {
MessageBoxW(nullptr, (L"TestCallback call via COM interop! \nTag: " + pasteType).c_str(), L"TestCallback", MB_OK);
return true;
}
private:
LONG refCount;
};
< /code>
Это решение работает, но, очевидно, это не жизнеспособное решение. Для новых методов потребуется обширные ручные усилия для реализации каждой диспетчерской проверки, проверки типов параметров и вызова фактической логической стороны C ++. Вызов метода testcallback из C#, он, похоже, ничего не называет. Я попытался вызвать посоветные функции, но все еще не работает. способ?
Подробнее здесь:
https://stackoverflow.com/questions/796 ... asily-in-c
1748737566
Anonymous
Я определил следующий интерфейс только idispatch в моем проекте C#: < /p> [code] [ComVisible(true)] [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] [Guid("3532C4E8-D320-487C-8BD4-F448B94B9E83")] public interface ICppRuntimeApi2 { [DispId(1)] bool TestCallback(string pasteType); } [/code] После импорта библиотеки сгенерированных типов в моем проекте C ++ я могу реализовать свой iCppruntimeapi2 свободно, как, например: [code]class CppRuntimeApiImpl2 : public MyProject::ICppRuntimeApi2 { public: CppRuntimeApiImpl2() : refCount(1) {} // IUnknown methods HRESULT __stdcall QueryInterface(REFIID riid, void** ppv) override { if (riid == IID_IUnknown || riid == IID_IDispatch || riid == __uuidof(MyProject::ICppRuntimeApi2)) { *ppv = static_cast(this); } else { *ppv = nullptr; return E_NOINTERFACE; } AddRef(); return S_OK; } ULONG __stdcall AddRef() override { return InterlockedIncrement(&refCount); } ULONG __stdcall Release() override { ULONG count = InterlockedDecrement(&refCount); if (count == 0) { delete this; } return count; } // IDispatch methods HRESULT __stdcall GetTypeInfoCount(UINT* pctinfo) override { *pctinfo = 0; return S_OK; } HRESULT __stdcall GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) override { *ppTInfo = nullptr; return E_NOTIMPL; } HRESULT __stdcall GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId) override { if (cNames != 1) return DISP_E_UNKNOWNNAME; if (_wcsicmp(rgszNames[0], L"TestCallback") == 0) { rgDispId[0] = 1; return S_OK; } return DISP_E_UNKNOWNNAME; } HRESULT __stdcall Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr) override { if (dispIdMember == 1) { if (pDispParams->cArgs != 1 || pDispParams->rgvarg[0].vt != VT_BSTR) { return DISP_E_BADPARAMCOUNT; } std::wstring pasteType(pDispParams->rgvarg[0].bstrVal, SysStringLen(pDispParams->rgvarg[0].bstrVal)); bool result = TestCallback(pasteType); if (pVarResult) { pVarResult->vt = VT_BOOL; pVarResult->boolVal = result ? VARIANT_TRUE : VARIANT_FALSE; } return S_OK; } return DISP_E_MEMBERNOTFOUND; } // ICppRuntimeApi2 method bool TestCallback(const std::wstring& pasteType) { MessageBoxW(nullptr, (L"TestCallback call via COM interop! \nTag: " + pasteType).c_str(), L"TestCallback", MB_OK); return true; } private: LONG refCount; }; < /code> Это решение работает, но, очевидно, это не жизнеспособное решение. Для новых методов потребуется обширные ручные усилия для реализации каждой диспетчерской проверки, проверки типов параметров и вызова фактической логической стороны C ++. Вызов метода testcallback [/code] из C#, он, похоже, ничего не называет. Я попытался вызвать посоветные функции, но все еще не работает. способ? Подробнее здесь: [url]https://stackoverflow.com/questions/79643497/implement-idispatch-only-interface-easily-in-c[/url]