스스로 IDispatch 실현:: Invoke 방법

2729 단어
여러 가지 이유 로 하나의 IWebBrowser 지침 만 받 을 수 있 는 상황 에서 javascript 의 window. external. XXX 호출 을 받 으 려 면 어 쩔 수 없 이 IDocHostUIHandler 와 IDispatch 를 실현 하 였 으 며, 사용 편 의 를 위해 서 는 MFC 와 유사 한 DISPATECH 가 필요 합 니 다.MAP: 우선 DISPATCH 방법의 ID, 이름, this 포인터, 함수 주소, 반환 값 형식, 매개 변수 유형 목록 을 하나의 구조 체 로 저장 합 니 다.이것들 은 모두 아무런 난이도 가 없다.그리고 IDispatch:: GetIDsOfnames 에서 방법 이름 을 통 해 방법 ID 를 찾 아 되 돌려 줍 니 다.가장 관건 적 인 것 은 IDispatch: Invoke 방법의 실현, 가 변 매개 변수 호출 을 어떻게 실현 하 느 냐 하 는 것 이다.
4. 567917. Invoke 방법의 매개 변수 와 대응 하 는 저 장 된 구조 체 정보 에 따라 매개 변수 개수, 매개 변수 유형, 반환 값 유형 에 대해 안전 검 사 를 한다
4. 567917. 저 장 된 함수 주소 포인터 때문에 함수 원형 (MFC 의 DISPATCH MAP 와 마찬가지 로 매개 변수 개수, 유형 과 반환 값 유형 이 모두 정 해 지지 않 음) 을 확정 할 수 없습니다. 어 셈 블 리 콜 명령 으로 직접 호출 하려 고 할 수 밖 에 없 지만 매개 변수 가 스 택 에 들 어 가 는 것 은 또 하나의 어 려 운 문제 입 니 다
VC + + 안의 표준this call 호출 약속 은 순서대로 파 라 메 터 를 스 택 에 넣 고 this 포인터 를 ECX 레지스터 에 기록 합 니 다. 그래서 저 는 먼저 매개 변수 유형 에 따라 모든 파 라 메 터 를 하나의 buffer 에 정렬 하여 모든 매개 변수 총 길이 size 를 얻 은 다음 에 스 택 에서 길 이 를 size 로 분배 하 는 공간 에서 buffer 를 분 배 된 스 택 에 직접 복사 합 니 다.그 다음 에 콜 명령 으로 함 수 를 호출 합 니 다. 그 중에서 주의해 야 할 것 이 있 습 니 다. 하 나 는 원래 레지스터 의 저장 과 호출 후의 복원 입 니 다.둘째, EBP 를 수정 하지 마 십시오. 그렇지 않 으 면 뒤의 어 셈 블 리 명령 에서 원래 의 부분 변 수 를 직접 사용 할 수 없습니다. 임시 변수 와 매개 변 수 는 실제 적 으로 EBP 라 는 스 택 프레임 을 통 해 빠르게 접근 하기 때 문 입 니 다 (방문 매개 변 수 는 EBP + XX, 방문 부분 변 수 는 EBP - XX).셋째, 스 택 의 균형 을 유지 하고 레지스터 가 스 택 에 들 어가 고 스 택 을 나 가 며 분 배 된 스 택 공간 방출 등 이다
4. 567917. 반환 값 을 가 져 오 면 32 비트 반환 값 은 EAX 에 저 장 됩 니 다. 64 비트 반환 값 은 각각 EDX 와 EAX 에 높 고 낮 음 32 비트 를 저장 합 니 다. 제 방법 은 64 비트 변수 로 EDX 와 EAX 값 을 직접 추출 한 다음 에 함수 의 실제 반환 값 유형 에 따라 대응 하 는 8 / 32 / 64 비트 를 찾 는 것 입 니 다. 어 셈 블 리 에서 이런 판단 을 하 는 것 은 매우 번 거 롭 기 때 문 입 니 다.이 EDX 와 EAX 의 값 을 가 져 오 는 것 은 프로그램 에 영향 을 주지 않 습 니 다
다음은 핵심 코드 입 니 다.
_asm{
        push ecx;
        mov ecx, pthis;  // this    ECX
        push ebx;
        mov ebx, esp;   //    ,    ebp,               
        sub esp, liSize;   //        liSize      

        push esi;       //memcpy begin         copy       
        push edi;
        push ecx;
        mov ecx, liSize
        mov esi, pStack;
        mov edi, ebx;
        sub edi, liSize
        rep movsb;
        pop ecx;
        pop edi;
        pop esi;        //memcpy end

        call fn;       //    
        mov esp, ebx;
        pop ebx;
        
        mov dword ptr[result], eax; //                    
        lea eax, [result];
        add eax, 4;
        mov dword ptr[eax], edx;   //     64         32 
    }

나중에 야 마이크로소프트 에 API 가 이 기능 을 실현 했다 는 것 을 알 게 되 었 다.
HRESULT DispInvoke(
  void *_this,
  ITypeInfo *ptinfo,
  DISPID dispidMember,
  WORD wFlags,
  DISPPARAMS *pparams,
  VARIANT *pvarResult,
  EXCEPINFO *pexcepinfo,
  UINT *puArgErr
);

좋은 웹페이지 즐겨찾기