# Virtual Method Implementation Guide ## Overview The Zoom SDK requires implementing ALL pure virtual methods from interface classes, even platform-specific ones. Missing even a single method results in abstract class errors at compile time. This guide shows how to find required methods and implement them correctly. --- ## Critical Rules 1. **Implement ALL pure virtual methods** - No exceptions 2. **Include WIN32-conditional methods** - They're required even though they're in `#if defined(WIN32)` blocks 3. **SDK version matters** - Different versions have different required methods 4. **Use exact signatures** - Parameter names can differ, but types and order must match exactly --- ## How to Find Required Methods ### Method 1: Grep the SDK Headers ```bash # Find all pure virtual methods (ending with = 0) grep "= 0" SDK/x64/h/*.h # Find methods in specific interface grep "= 0" SDK/x64/h/auth_service_interface.h grep "= 0" SDK/x64/h/meeting_service_interface.h ``` ### Method 2: Read Compiler Errors When you forget to implement a method, the compiler tells you: ``` error C2259: 'AuthServiceEventListener': cannot instantiate abstract class note: see declaration of 'AuthServiceEventListener' note: due to following members: 'void IAuthServiceEvent::onNotificationServiceStatus(SDKNotificationServiceStatus,SDKNotificationServiceError)': is abstract at auth_service_interface.h(256) ``` This tells you: - **Method name**: `onNotificationServiceStatus` - **Parameters**: `SDKNotificationServiceStatus status, SDKNotificationServiceError error` - **Location**: Line 256 in `auth_service_interface.h` ### Method 3: Read the Header Files Manually Open the interface header and look for methods marked with `= 0`: ```cpp class IAuthServiceEvent { public: virtual ~IAuthServiceEvent() {} virtual void onAuthenticationReturn(AuthResult ret) = 0; // <-- REQUIRED (= 0) virtual void onLogout() = 0; // <-- REQUIRED (= 0) }; ``` --- ## Complete Method Lists ### IAuthServiceEvent (6 methods required) **File**: `SDK/x64/h/auth_service_interface.h` (lines 217-258) ```cpp class AuthServiceEventListener : public IAuthServiceEvent { public: // Method 1: Authentication result (JWT token validation) void onAuthenticationReturn(AuthResult ret) override; // Method 2: Login result with fail reason (for user login, not JWT) void onLoginReturnWithReason(LOGINSTATUS ret, IAccountInfo* pAccountInfo, LoginFailReason reason) override; // Method 3: Logout notification void onLogout() override; // Method 4: Zoom identity expired (need to regenerate token) void onZoomIdentityExpired() override; // Method 5: Zoom auth identity expiring soon (10 minutes warning) void onZoomAuthIdentityExpired() override; // Method 6: WIN32 ONLY - Notification service status #if defined(WIN32) void onNotificationServiceStatus(SDKNotificationServiceStatus status, SDKNotificationServiceError error) override; #endif }; ``` **Important notes**: - Methods 1-5 are cross-platform - Method 6 is Windows-only but **MUST** be implemented on Windows - For JWT auth, only `onAuthenticationReturn` fires; others are for user login --- ### IMeetingServiceEvent (9 methods required) **File**: `SDK/x64/h/meeting_service_interface.h` (lines 830-897) ```cpp class MeetingServiceEventListener : public IMeetingServiceEvent { public: // Method 1: Meeting status changed (joined, ended, failed, etc.) void onMeetingStatusChanged(MeetingStatus status, int iResult) override; // Method 2: Meeting statistics warning (network issues, etc.) void onMeetingStatisticsWarningNotification(StatisticsWarningType type) override; // Method 3: Meeting parameters (right before meeting starts) void onMeetingParameterNotification(const MeetingParameter* meeting_param) override; // Method 4: Participants activities suspended void onSuspendParticipantsActivities() override; // Method 5: AI Companion status changed void onAICompanionActiveChangeNotice(bool bActive) override; // Method 6: Meeting topic changed void onMeetingTopicChanged(const zchar_t* sTopic) override; // Method 7: Meeting at capacity, provides livestream URL void onMeetingFullToWatchLiveStream(const zchar_t* sLiveStreamUrl) override; // Method 8: User network quality changed void onUserNetworkStatusChanged(MeetingComponentType type, ConnectionQuality level, unsigned int userId, bool uplink) override; // Method 9: WIN32 ONLY - App signal panel updated #if defined(WIN32) void onAppSignalPanelUpdated(IMeetingAppSignalHandler* pHandler) override; #endif }; ``` **Important notes**: - Methods 1-8 are cross-platform - Method 9 is Windows-only but **MUST** be implemented on Windows - Most apps only care about method 1 (`onMeetingStatusChanged`) --- ## Implementation Patterns ### Minimal Implementation (Empty Stubs) If you don't need a method's functionality, implement it as an empty stub: ```cpp void AuthServiceEventListener::onLogout() { // We're not using user login, so this never fires // Empty implementation is fine } void MeetingServiceEventListener::onAICompanionActiveChangeNotice(bool bActive) { // We don't care about AI Companion status // Empty implementation is fine } ``` ### Logging Implementation (Recommended for Debugging) Add basic logging to see when callbacks fire: ```cpp void AuthServiceEventListener::onZoomIdentityExpired() { std::cout << "[AUTH] Zoom identity expired! Need to regenerate JWT token." << std::endl; } void MeetingServiceEventListener::onMeetingStatisticsWarningNotification(StatisticsWarningType type) { std::cout << "[MEETING] Statistics warning: " << static_cast(type) << std::endl; } ``` ### Full Implementation (For Important Callbacks) ```cpp void MeetingServiceEventListener::onMeetingStatusChanged(MeetingStatus status, int iResult) { switch (status) { case MEETING_STATUS_IDLE: std::cout << "[MEETING] Status: IDLE" << std::endl; break; case MEETING_STATUS_CONNECTING: std::cout << "[MEETING] Status: CONNECTING" << std::endl; break; case MEETING_STATUS_INMEETING: std::cout << "[MEETING] Status: IN MEETING" << std::endl; if (onInMeetingCallback) { onInMeetingCallback(); // Trigger custom logic } break; case MEETING_STATUS_ENDED: std::cout << "[MEETING] Status: ENDED (Reason: " << iResult << ")" << std::endl; if (onMeetingEnded) { onMeetingEnded(); // Trigger custom logic } break; case MEETING_STATUS_FAILED: std::cout << "[MEETING] Status: FAILED (Error: " << iResult << ")" << std::endl; break; default: std::cout << "[MEETING] Status: UNKNOWN (" << status << ")" << std::endl; break; } } ``` --- ## Complete Header/Source File Template ### Header File (AuthServiceEventListener.h) ```cpp #pragma once #include #include #include #include using namespace ZOOM_SDK_NAMESPACE; class AuthServiceEventListener : public IAuthServiceEvent { public: // Constructor with callback AuthServiceEventListener(void (*onComplete)()); // All 6 required methods void onAuthenticationReturn(AuthResult ret) override; void onLoginReturnWithReason(LOGINSTATUS ret, IAccountInfo* info, LoginFailReason reason) override; void onLogout() override; void onZoomIdentityExpired() override; void onZoomAuthIdentityExpired() override; #if defined(WIN32) void onNotificationServiceStatus(SDKNotificationServiceStatus status, SDKNotificationServiceError error) override; #endif private: void (*onAuthComplete)(); }; ``` ### Source File (AuthServiceEventListener.cpp) ```cpp #include "AuthServiceEventListener.h" AuthServiceEventListener::AuthServiceEventListener(void (*onComplete)()) : onAuthComplete(onComplete) {} void AuthServiceEventListener::onAuthenticationReturn(AuthResult ret) { if (ret == AUTHRET_SUCCESS) { std::cout << "[AUTH] Authentication successful!" << std::endl; if (onAuthComplete) { onAuthComplete(); } } else { std::cout << "[AUTH] Authentication failed: " << ret << std::endl; } } void AuthServiceEventListener::onLoginReturnWithReason(LOGINSTATUS ret, IAccountInfo* info, LoginFailReason reason) { std::cout << "[AUTH] Login return (not used for JWT): " << ret << std::endl; } void AuthServiceEventListener::onLogout() { std::cout << "[AUTH] Logout" << std::endl; } void AuthServiceEventListener::onZoomIdentityExpired() { std::cout << "[AUTH] Zoom identity expired!" << std::endl; } void AuthServiceEventListener::onZoomAuthIdentityExpired() { std::cout << "[AUTH] Zoom auth identity expiring soon!" << std::endl; } #if defined(WIN32) void AuthServiceEventListener::onNotificationServiceStatus(SDKNotificationServiceStatus status, SDKNotificationServiceError error) { std::cout << "[AUTH] Notification service status: " << status << ", error: " << error << std::endl; } #endif ``` --- ## Troubleshooting ### Error: "Cannot instantiate abstract class" **Cause**: You're missing one or more pure virtual method implementations. **Solution**: 1. Read the compiler error carefully - it lists the missing methods 2. Look up the method signature in the SDK header file 3. Add the method to both your .h and .cpp files 4. Use `override` keyword to catch signature mismatches **Example error**: ``` error C2259: 'AuthServiceEventListener': cannot instantiate abstract class note: due to following members: 'void IAuthServiceEvent::onNotificationServiceStatus(...)': is abstract ``` **Fix**: Add the missing method: ```cpp // In .h file #if defined(WIN32) void onNotificationServiceStatus(SDKNotificationServiceStatus status, SDKNotificationServiceError error) override; #endif // In .cpp file #if defined(WIN32) void AuthServiceEventListener::onNotificationServiceStatus(SDKNotificationServiceStatus status, SDKNotificationServiceError error) { // Empty implementation is fine if you don't need this } #endif ``` ### Error: "No suitable user-defined conversion" **Cause**: Method signature doesn't match exactly (wrong parameter types, missing const, etc.). **Solution**: Copy the signature EXACTLY from the SDK header file, including: - `const` qualifiers - Pointer vs reference (`*` vs `&`) - Parameter order - Return type ### WIN32 Methods Not Compiling **Cause**: Forgot `#if defined(WIN32)` wrapper. **Solution**: Wrap WIN32-only methods in both .h and .cpp files: ```cpp #if defined(WIN32) void onNotificationServiceStatus(...) override; #endif ``` --- --- ## Custom UI Interfaces These interfaces are required when using Custom UI mode (`ENABLE_CUSTOMIZED_UI_FLAG`). ### ICustomizedUIMgrEvent (3 methods required) **File**: `SDK/x64/h/customized_ui/customized_ui_mgr.h` ```cpp class CustomUIMgrEventListener : public ICustomizedUIMgrEvent { public: // Method 1: Video container destroyed by SDK (e.g., meeting ended) void onVideoContainerDestroyed(ICustomizedVideoContainer* pContainer) override; // Method 2: Share render destroyed by SDK void onShareRenderDestroyed(ICustomizedShareRender* pRender) override; // Method 3: Immersive container destroyed by SDK void onImmersiveContainerDestroyed() override; }; ``` **Important notes**: - These fire when the SDK destroys containers on its own (e.g., meeting ends) - You MUST null out your pointers in these callbacks to avoid dangling references - All 3 are always required --- ### ICustomizedVideoContainerEvent (6 methods required) **File**: `SDK/x64/h/customized_ui/customized_video_container.h` ```cpp class VideoContainerEventListener : public ICustomizedVideoContainerEvent { public: // Method 1: User changed for a video render element void onRenderUserChanged(IVideoRenderElement* pElement, unsigned int userid) override; // Method 2: Data type changed (video, avatar, screen name) void onRenderDataTypeChanged(IVideoRenderElement* pElement, VideoRenderDataType dataType) override; // Method 3: Layout notification — container resized, recompute element positions void onLayoutNotification(RECT wnd_client_rect) override; // Method 4: A video render element was destroyed void onVideoRenderElementDestroyed(IVideoRenderElement* pElement) override; // Method 5: Window messages from SDK child HWND (mouse, keyboard) void onWindowMsgNotification(UINT uMsg, WPARAM wParam, LPARAM lParam) override; // Method 6: Video subscription failed for an element void onSubscribeUserFail(ZoomSDKVideoSubscribeFailReason fail_reason, IVideoRenderElement* pElement) override; }; ``` **Important notes**: - `onLayoutNotification` is where you re-layout video elements after container resize - `onWindowMsgNotification` forwards input from SDK's child HWND (see [Custom UI Architecture](../concepts/custom-ui-architecture.md)) - `VideoRenderDataType` values: `VideoRenderData_Video`, `VideoRenderData_Avatar`, `VideoRenderData_ScreenName` - `ZoomSDKVideoSubscribeFailReason` values: `ViewOnly`, `NotInMeeting`, `HasSubscribe1080POr720`, `HasSubscribeTwo720P`, `HasSubscribeExceededLimit`, `TooFrequentCall` --- ### ICustomizedShareRenderEvent (3 methods required) **File**: `SDK/x64/h/customized_ui/customized_share_render.h` ```cpp class ShareRenderEventListener : public ICustomizedShareRenderEvent { public: // Method 1: Started receiving shared content void onSharingContentStartReceiving() override; // Method 2: Share source changed or sharing closed void onSharingSourceNotification(unsigned int nShareSourceID) override; // Method 3: Window messages from share render's child HWND void onWindowMsgNotification(UINT uMsg, WPARAM wParam, LPARAM lParam) override; }; ``` **Important notes**: - When `onSharingSourceNotification` fires with a new ID, call `SetShareSourceID(nShareSourceID)` and `Show()` - When sharing stops, `nShareSourceID` will be 0 — call `Hide()` --- ### Quick Reference: Custom UI Method Counts | Interface | Methods | File | |-----------|---------|------| | `ICustomizedUIMgrEvent` | 3 | `customized_ui/customized_ui_mgr.h` | | `ICustomizedVideoContainerEvent` | 6 | `customized_ui/customized_video_container.h` | | `ICustomizedShareRenderEvent` | 3 | `customized_ui/customized_share_render.h` | | `ICustomizedImmersiveContainerEvent` | 1 | `customized_ui/customized_immersive_container.h` | | **Total Custom UI methods** | **13** | | --- ## SDK Version Differences Different SDK versions may have different required methods. This guide is for **SDK v6.7.2.26830**. If you're using a different version: 1. Run `grep "= 0" SDK/x64/h/auth_service_interface.h` to see your version's methods 2. Run `grep "= 0" SDK/x64/h/meeting_service_interface.h` 3. Compare against this guide to identify new or removed methods --- ## Quick Reference Commands ```bash # List all pure virtual methods in SDK grep "= 0" SDK/x64/h/*.h # Count methods per interface grep -c "= 0" SDK/x64/h/auth_service_interface.h # Should be 6 grep -c "= 0" SDK/x64/h/meeting_service_interface.h # Should be 9 # Find method signature grep -A 5 "onAuthenticationReturn" SDK/x64/h/auth_service_interface.h # Verify your implementation has all methods grep "override" src/AuthServiceEventListener.h # Should match SDK count ``` --- ## Related Documentation - [Build Errors Guide](../troubleshooting/build-errors.md) - Header dependency issues - [Authentication Pattern](../examples/authentication-pattern.md) - Using IAuthServiceEvent - [Windows Reference](windows-reference.md) - General SDK setup --- **Last Updated**: Based on Zoom Windows Meeting SDK v6.7.2.26830