디버거 데이터 모델 C++ 스크립팅
이 항목에서는 디버거 데이터 모델 C++ 디버거 데이터 모델 C++ 스크립팅을 사용하여 스크립팅을 사용하여 디버거 엔진에서 자동화를 지원하는 방법을 설명합니다.
디버거 데이터 모델의 스크립트 관리
개체 만들기 및 확장성에 대한 중앙 기관으로서의 데이터 모델 관리자 역할 외에도 스크립트의 추상 개념 관리를 담당합니다. 데이터 모델 관리자의 스크립트 관리자 부분에서 스크립트는 데이터 모델에 새 기능을 확장하거나 제공하기 위해 공급자가 동적으로 로드, 언로드 및 잠재적으로 디버그할 수 있는 스크립트입니다.
스크립트 공급자는 언어(예: NatVis, JavaScript 등)를 데이터 모델에 연결하는 구성 요소입니다. 하나 이상의 파일 확장명(예: ")을 등록합니다. 공급자가 처리하는 NatVis", ".js")는 디버거 클라이언트 또는 사용자 인터페이스가 공급자에 위임하여 해당 특정 확장자를 사용하여 스크립트 파일을 로드할 수 있도록 허용합니다.
핵심 스크립트 관리자: IDataModelScriptManager
핵심 스크립트 관리자 인터페이스는 다음과 같이 정의됩니다.
DECLARE_INTERFACE_(IDataModelScriptManager, IUnknown)
{
STDMETHOD(GetDefaultNameBinder)(_COM_Outptr_ IDataModelNameBinder **ppNameBinder) PURE;
STDMETHOD(RegisterScriptProvider)(_In_ IDataModelScriptProvider *provider) PURE;
STDMETHOD(UnregisterScriptProvider)(_In_ IDataModelScriptProvider *provider) PURE;
STDMETHOD(FindProviderForScriptType)(_In_ PCWSTR scriptType, _COM_Outptr_ IDataModelScriptProvider **provider) PURE;
STDMETHOD(FindProviderForScriptExtension)(_In_ PCWSTR scriptExtension, _COM_Outptr_ IDataModelScriptProvider **provider) PURE;
STDMETHOD(EnumerateScriptProviders)(_COM_Outptr_ IDataModelScriptProviderEnumerator **enumerator) PURE;
}
GetDefaultNameBinder 메서드는 데이터 모델의 기본 스크립트 이름 바인더를 반환합니다. 이름 바인더는 개체의 컨텍스트 내에서 이름을 확인하는 구성 요소입니다. instance "foo.bar" 식이 지정된 경우 개체 foo의 컨텍스트에서 이름 표시줄을 resolve 이름 바인더가 호출됩니다. 여기에 반환된 바인더는 데이터 모델에 대한 기본 규칙 집합을 따릅니다. 스크립트 공급자는 이 바인더를 사용하여 공급자 간에 이름 확인의 일관성을 제공할 수 있습니다.
RegisterScriptProvider 메서드는 데이터 모델에 새 언어를 브리징할 수 있는 새 스크립트 공급자가 있음을 데이터 모델에 알릴 수 있습니다. 이 메서드가 호출되면 스크립트 관리자는 지정된 스크립트 공급자를 즉시 다시 호출하고 관리하는 스크립트의 속성을 문의합니다. 지정된 스크립트 공급자가 나타내는 이름 또는 파일 확장명 아래에 등록된 공급자가 이미 있는 경우 이 메서드는 실패합니다. 단일 스크립트 공급자만 특정 이름 또는 파일 확장명 처리기로 등록할 수 있습니다.
UnregisterScriptProvider 메서드는 RegisterScriptProvider 메서드에 대한 호출을 실행 취소합니다. 수동 스크립트 공급자가 지정한 이름 및 파일 확장명은 더 이상 연결되지 않습니다. 등록 취소 후에도 스크립트 공급자에 대한 상당한 수의 미해결 COM 참조가 있을 수 있다는 점에 유의해야 합니다. 이 메서드는 지정된 스크립트 공급자가 관리하는 형식의 스크립트 로드/생성만 방지합니다. 해당 공급자가 로드한 스크립트가 여전히 로드되거나 디버거의 개체 모델(또는 데이터 모델)을 조작한 경우 이러한 조작에는 여전히 스크립트에 대한 참조가 있을 수 있습니다. 스크립트에서 구문을 직접 참조하는 데이터 모델, 메서드 또는 개체가 있을 수 있습니다. 스크립트 공급자는 이를 처리할 준비가 되어 있어야 합니다.
FindProviderForScriptType 메서드는 스크립트 관리자에서 이 메서드에 표시된 대로 스크립트 형식 문자열이 있는 공급자를 검색합니다. 찾을 수 없는 경우 이 메서드는 실패합니다. 그렇지 않으면 이러한 스크립트 공급자가 호출자에게 반환됩니다.
EnumerateScriptProviders 메서드는 RegisterScriptProvider 메서드에 대한 이전 호출을 통해 스크립트 관리자에 등록된 모든 스크립트 공급자를 열거하는 열거자를 반환합니다.
스크립트 공급자 열거형: IDataModelScriptProviderEnumerator
EnumerateScriptProviders 메서드는 다음 형식의 열거자를 반환합니다.
DECLARE_INTERFACE_(IDataModelScriptProviderEnumerator, IUnknown)
{
STDMETHOD(Reset)() PURE;
STDMETHOD(GetNext)(_COM_Outptr_ IDataModelScriptProvider **provider) PURE;
}
Reset 메서드는 첫 번째 요소를 반환하기 전에 열거자를 위치로 이동합니다.
GetNext 메서드는 열거자를 한 요소 앞으로 이동하고 해당 요소에 있는 스크립트 공급자를 반환합니다. 열거자가 열거형의 끝에 도달하면 E_BOUNDS 반환됩니다. 이 오류를 받은 후 GetNext 메서드를 호출하면 E_BOUNDS 무기한으로 반환됩니다.
스크립팅을 위한 디버거 데이터 모델 C++ 호스트 인터페이스
스크립팅에서 호스트의 역할
디버그 호스트는 디버그 대상의 형식 시스템의 특성을 이해하고, 디버그 대상의 언어로 식을 평가하는 등 매우 낮은 수준의 일련의 인터페이스를 노출합니다. 일반적으로 스크립팅과 같은 상위 수준 구문에 대해 걱정하지 않습니다. 이러한 기능은 전체 디버거 애플리케이션 또는 이러한 기능을 제공하는 확장에 남아 있습니다. 그러나 이에 대한 예외가 있습니다. 데이터 모델에서 제공하는 전체 스크립팅 환경에 참여하려는 디버그 호스트는 스크립트에 컨텍스트를 제공하기 위해 몇 가지 간단한 인터페이스를 구현해야 합니다. 실제로 디버그 호스트는 스크립팅 환경에서 함수 및 기타 스크립트 제공 기능을 데이터 모델의 네임스페이스 내에 배치하려는 위치를 제어합니다. 이 프로세스에 참여하면 호스트가 식 계산기인 instance 이러한 함수의 사용을 허용하거나 허용하지 않을 수 있습니다. 호스트의 관점에서 관련된 인터페이스는 다음과 같습니다.
인터페이스 | Description |
---|---|
IDebugHostScriptHost | 스크립팅 환경에 참여할 디버그 호스트의 기능을 나타내는 인터페이스입니다. 이 인터페이스를 사용하면 개체를 배치할 위치를 스크립팅 엔진에 알리는 컨텍스트를 만들 수 있습니다. |
IDataModelScriptHostContext | 스크립트 공급자가 스크립트 내용에 대한 컨테이너로 사용하는 호스트 인터페이스입니다. 디버거 애플리케이션의 개체 모델에 대해 수행하는 조작 이외의 스크립트 내용이 표시되는 방식은 특정 디버그 호스트에 달려 있습니다. 이 인터페이스를 사용하면 스크립트 공급자가 콘텐츠를 배치할 위치에 대한 정보를 가져올 수 있습니다. 자세한 내용은 이 항목의 뒷부분에 있는 데이터 모델 C++ 스크립팅 인터페이스 를 참조하세요. |
디버그 호스트의 스크립트 호스트: IDebugHostScriptHost
IDebugHostScriptHost 인터페이스는 스크립트 공급자가 새로 만든 스크립트에 대한 디버그 호스트에서 컨텍스트를 가져오는 데 사용하는 인터페이스입니다. 이 컨텍스트에는 스크립트 공급자가 데이터 모델과 스크립팅 환경 사이에 모든 브리지를 배치할 수 있는 개체(디버그 호스트에서 제공)가 포함됩니다. 이러한 브리지는 instance 스크립트 함수를 호출하는 데이터 모델 메서드일 수 있습니다. 이렇게 하면 데이터 모델 쪽의 호출자가 IModelMethod 인터페이스에서 Call 메서드를 활용하여 스크립트 메서드를 호출할 수 있습니다.
IDebugHostScriptHost 인터페이스는 다음과 같이 정의됩니다.
DECLARE_INTERFACE_(IDebugHostScriptHost, IUnknown)
{
STDMETHOD(CreateContext)(_In_ IDataModelScript* script, _COM_Outptr_ IDataModelScriptHostContext** scriptContext) PURE;
}
CreateContext 메서드는 스크립트 공급자가 스크립트의 내용을 배치할 새 컨텍스트를 만들기 위해 호출됩니다. 이러한 컨텍스트는 데이터 모델 C++ 스크립팅 인터페이스 페이지에 자세히 설명된 IDataModelScriptHostContext 인터페이스로 표시됩니다.
디버거 데이터 모델 C++ 스크립팅 인터페이스
스크립팅 및 스크립트 인터페이스
데이터 모델의 전체 아키텍처를 사용하면 타사에서 일부 언어와 데이터 모델의 개체 모델 간에 브리지를 정의할 수 있습니다. 일반적으로 브리지되는 언어는 데이터 모델의 환경이 매우 동적이므로 스크립팅 언어입니다. 언어와 데이터 모델의 개체 모델 간에 이 브리지를 정의하고 구현하는 구성 요소를 스크립트 공급자라고 합니다. 초기화되면 스크립트 공급자는 데이터 모델 관리자의 스크립트 관리자 부분에 자신을 등록하고 확장성을 관리하는 모든 인터페이스는 이후에 스크립트 공급자가 관리하는 언어로 작성된 스크립트의 편집, 로드, 언로드 및 잠재적으로 디버깅을 허용합니다.
Windows용 디버깅 도구는 현재 두 개의 스크립트 공급자를 정의합니다.
- NatVis 공급자입니다. 이 공급자는 NatVis XML과 데이터 모델 간의 DbgEng.dll 및 브리지 내에 포함되므로 네이티브/언어 데이터 형식을 시각화할 수 있습니다.
- JavaScript 공급자입니다. 이 공급자는 레거시 디버거 확장인 JsProvider.dll 내에 포함되어 있습니다. JavaScript 언어로 작성된 스크립트와 데이터 모델을 연결하여 임의의 형태의 디버거 제어 및 확장성을 허용합니다.
데이터 모델에 다른 언어(예: Python 등)를 연결하는 새 공급자를 작성할 수 있습니다. 이러한 기능은 현재 로드를 위해 레거시 디버거 확장에 캡슐화되어 있습니다. 스크립트 공급자 자체는 레거시 엔진 인터페이스와의 종속성을 최소화해야 하며 가능한 경우에만 데이터 모델 API를 활용해야 합니다. 이렇게 하면 공급자를 훨씬 더 쉽게 다른 환경으로 이식할 수 있습니다.
스크립트 공급자와 관련된 두 가지 인터페이스 클래스가 있습니다. 인터페이스의 첫 번째 클래스는 스크립트 공급자 및 관리하는 스크립트의 일반적인 관리를 위한 것입니다. 두 번째 인터페이스 클래스는 스크립트 디버깅을 지원하는 것입니다. 첫 번째 집합에 대한 지원은 필수이지만 두 번째 집합에 대한 지원은 선택 사항이며 모든 공급자에 대해 의미가 없을 수 있습니다.
일반적인 관리 인터페이스는 다음과 같습니다.
인터페이스 | Description |
---|---|
IDataModelScriptProvider | 스크립트 공급자가 구현해야 하는 핵심 인터페이스입니다. 특정 유형의 스크립트에 대한 공급자의 지원을 보급하고 특정 파일 확장자에 등록하기 위해 데이터 모델 관리자의 스크립트 관리자 부분에 등록된 인터페이스입니다. |
IDataModelScript | 공급자가 관리하는 특정 스크립트의 추상화입니다. 로드되거나 편집되는 각 스크립트에는 별도의 IDataModelScript instance |
IDataModelScriptClient | 사용자 인터페이스에 정보를 전달하기 위해 스크립트 공급자가 사용하는 클라이언트 인터페이스입니다. 스크립트 공급자는 이 인터페이스를 구현하지 않습니다. 스크립트 공급자를 사용하려는 데이터 모델을 호스트하는 애플리케이션은 그렇게 합니다. 스크립트 공급자는 스크립트 클라이언트의 메서드를 호출하여 상태, 오류 등을 보고합니다. |
IDataModelScriptHostContext | 스크립트 공급자가 스크립트 내용에 대한 컨테이너로 사용하는 호스트 인터페이스입니다. 디버거 애플리케이션의 개체 모델에 대해 수행하는 조작 이외의 스크립트 내용이 표시되는 방식은 특정 디버그 호스트에 달려 있습니다. 이 인터페이스를 사용하면 스크립트 공급자가 콘텐츠를 배치할 위치에 대한 정보를 가져올 수 있습니다. |
IDataModelScriptTemplate | 스크립트 공급자는 사용자가 스크립트를 작성하기 위한 시작 지점 역할을 하는 하나 이상의 템플릿을 제공할 수 있습니다. 기본 제공 편집기를 제공하는 디버거 애플리케이션은 이 인터페이스를 통해 공급자가 보급한 템플릿 콘텐츠로 새 스크립트를 미리 채울 수 있습니다. |
IDataModelScriptTemplateEnumerator | 스크립트 공급자가 지원하는 다양한 템플릿을 모두 보급하기 위해 구현하는 열거자 인터페이스입니다. |
IDataModelNameBinder | 이름 바인더 - 컨텍스트의 이름을 값과 연결할 수 있는 개체입니다. "foo.bar"과 같은 지정된 식의 경우 이름 바인더는 개체 "foo"의 컨텍스트에서 이름 "bar"를 바인딩하고 값 또는 참조를 생성할 수 있습니다. 이름 바인더는 일반적으로 스크립트 공급자에 의해 구현되지 않습니다. 오히려 데이터 모델에서 기본 바인더를 획득하고 스크립트 공급자가 사용할 수 있습니다. |
디버그 인터페이스는 다음과 같습니다.
인터페이스 | Description |
---|---|
IDataModelScriptDebug | 스크립트를 디버깅할 수 있도록 스크립트 공급자가 제공해야 하는 핵심 인터페이스입니다. 스크립트를 디버깅할 수 있는 경우 IDataModelScript 인터페이스의 구현 클래스는 IDataModelScriptDebug에 대해 QueryInterface여야 합니다. |
IDataModelScriptDebugClient | 스크립트 디버깅 기능을 제공하려는 사용자 인터페이스는 IDataModelScriptDebugClient 인터페이스를 구현합니다. 스크립트 공급자는 이 인터페이스를 사용하여 디버그 정보를 앞뒤로 전달합니다(예: 발생하는 이벤트, 중단점 등...) |
IDataModelScriptDebugStack | 스크립트 공급자는 이 인터페이스를 구현하여 호출 스택의 개념을 스크립트 디버거에 노출합니다. |
IDataModelScriptDebugStackFrame | 스크립트 공급자는 호출 스택 내에서 특정 스택 프레임의 개념을 노출하기 위해 이 인터페이스를 구현합니다. |
IDataModelScriptDebugVariableSetEnumerator | 스크립트 공급자는 변수 집합을 노출하기 위해 이 인터페이스를 구현합니다. 이 집합은 함수에 대한 매개 변수 집합, 지역 변수 집합 또는 특정 scope 내의 변수 집합을 나타낼 수 있습니다. 정확한 의미는 인터페이스를 획득한 방법에 따라 달라집니다. |
IDataModelScriptDebugBreakpoint | 스크립트 공급자는 이 인터페이스를 구현하여 스크립트 내에서 특정 중단점의 개념과 제어를 노출합니다. |
IDataModelScriptDebugBreakpointEnumerator | 스크립트 공급자는 이를 구현하여 현재 스크립트 내에 있는 모든 중단점을 열거합니다(사용 여부에 관계없이). |
핵심 스크립트 공급자: IDataModelScriptProvider
스크립트 공급자가 되려는 모든 확장은 IDataModelScriptProvider 인터페이스의 구현을 제공하고 RegisterScriptProvider 메서드를 통해 데이터 모델 관리자의 스크립트 관리자 부분에 등록해야 합니다. 구현해야 하는 이 핵심 인터페이스는 다음과 같이 정의됩니다.
DECLARE_INTERFACE_(IDataModelScriptProvider, IUnknown)
{
STDMETHOD(GetName)(_Out_ BSTR *name) PURE;
STDMETHOD(GetExtension)(_Out_ BSTR *extension) PURE;
STDMETHOD(CreateScript)(_COM_Outptr_ IDataModelScript **script) PURE;
STDMETHOD(GetDefaultTemplateContent)(_COM_Outptr_ IDataModelScriptTemplate **templateContent) PURE;
STDMETHOD(EnumerateTemplates)(_COM_Outptr_ IDataModelScriptTemplateEnumerator **enumerator) PURE;
}
GetName 메서드는 공급자가 SysAllocString 메서드를 통해 할당된 문자열로 관리하는 스크립트 형식(또는 언어)의 이름을 반환합니다. 호출자는 SysFreeString을 통해 반환된 문자열의 해제를 담당합니다. 이 메서드에서 반환될 수 있는 문자열의 예는 "JavaScript" 또는 "NatVis"입니다. 반환된 문자열은 데이터 모델을 호스팅하는 디버거 애플리케이션의 사용자 인터페이스에 나타날 수 있습니다. 두 스크립트 공급자가 동일한 이름을 반환할 수 없습니다(대/소문자를 구분하지 않음).
GetExtension 메서드는 이 공급자가 관리하는 스크립트의 파일 확장명(점 없음)을 SysAllocString 메서드를 통해 할당된 문자열로 반환합니다. 데이터 모델을 호스팅하는 디버거 애플리케이션(스크립팅 지원)은 이 확장명으로 스크립트 파일의 열기를 스크립트 공급자에게 위임합니다. 호출자는 SysFreeString을 통해 반환된 문자열의 해제를 담당합니다. 이 메서드에서 반환될 수 있는 문자열의 예는 "js" 또는 "NatVis"입니다.
CreateScript 메서드가 호출되어 새 스크립트를 만듭니다. 스크립트 공급자는 이 메서드가 호출될 때마다 반환된 IDataModelScript 인터페이스가 나타내는 새 스크립트와 빈 스크립트를 반환해야 합니다. 이 메서드는 사용자 인터페이스가 사용자가 편집할 새 빈 스크립트를 만드는지 또는 디버거 애플리케이션이 디스크에서 스크립트를 로드하는지 여부에 관계없이 호출됩니다. 공급자가 파일 I/O에 관여하지 않습니다. IDataModelScript의 메서드에 전달된 스트림을 통해 호스팅 애플리케이션의 요청만 처리합니다.
GetDefaultTemplateContent 메서드는 공급자의 기본 템플릿 콘텐츠에 대한 인터페이스를 반환합니다. 스크립트 공급자가 새로 만든 스크립트에 대한 편집 창에 미리 채워지게 하는 콘텐츠입니다. 스크립트 공급자에 템플릿이 없거나 기본 콘텐츠로 지정된 템플릿 콘텐츠가 없는 경우 스크립트 공급자는 이 메서드의 E_NOTIMPL 반환할 수 있습니다.
EnumerateTemplates 메서드는 스크립트 공급자가 제공하는 다양한 템플릿을 열거할 수 있는 열거자를 반환합니다. 템플릿 콘텐츠는 스크립트 공급자가 새 스크립트를 만들 때 편집 창에 "미리 채워지게" 하려는 내용입니다. 지원되는 템플릿이 여러 개 있는 경우 해당 템플릿의 이름을 지정할 수 있으며(예: "명령적 스크립트", "확장 스크립트") 데이터 모델을 호스트하는 디버거 애플리케이션은 사용자에게 "템플릿"을 제공하는 방법을 선택할 수 있습니다.
핵심 스크립트 인터페이스: IDataModelScript
공급자가 구현하는 개별 스크립트를 관리하는 기본 인터페이스는 IDataModelScript 인터페이스입니다. 이 인터페이스를 구현하는 구성 요소는 클라이언트가 새 빈 스크립트를 만들고 IDataModelScriptProvider에서 CreateScript 메서드를 호출할 때 반환됩니다.
공급자가 만든 각 스크립트는 독립적인 사일로에 있어야 합니다. 한 스크립트는 데이터 모델을 통해 외부 개체와의 명시적 상호 작용을 제외하고는 다른 스크립트에 영향을 주지 않아야 합니다. 두 스크립트는 instance 대해 일부 형식 또는 개념(예: 프로세스가 무엇인지에 대한 디버거의 개념)을 확장할 수 있습니다. 그런 다음, 두 스크립트는 외부 프로세스 개체를 통해 서로의 필드에 액세스할 수 있습니다.
인터페이스는 다음과 같이 정의됩니다.
DECLARE_INTERFACE_(IDataModelScript, IUnknown)
{
STDMETHOD(GetName)(_Out_ BSTR *scriptName) PURE;
STDMETHOD(Rename)(_In_ PCWSTR scriptName) PURE;
STDMETHOD(Populate)(_In_ IStream *contentStream) PURE;
STDMETHOD(Execute)(_In_ IDataModelScriptClient *client) PURE;
STDMETHOD(Unlink)() PURE;
STDMETHOD(IsInvocable)(_Out_ bool *isInvocable) PURE;
STDMETHOD(InvokeMain)(_In_ IDataModelScriptClient *client) PURE;
}
GetName 메서드는 SysAllocString 함수를 통해 스크립트의 이름을 할당된 문자열로 반환합니다. 스크립트에 아직 이름이 없으면 메서드는 null BSTR을 반환해야 합니다. 이 상황에서는 실패하지 않아야 합니다. Rename 메서드 호출을 통해 스크립트의 이름이 명시적으로 변경되면 GetName 메서드는 새로 할당된 이름을 반환해야 합니다.
Rename 메서드는 스크립트에 새 이름을 할당합니다. 이 이름을 저장하고 GetName 메서드를 호출할 때 반환하는 것은 스크립트 구현의 책임입니다. 이는 사용자 인터페이스가 스크립트로 새 이름으로 저장을 선택할 때 종종 호출됩니다. 스크립트 이름을 바꾸는 것은 호스팅 애플리케이션이 스크립트의 콘텐츠를 프로젝션하도록 선택하는 위치에 영향을 줄 수 있습니다.
Populate 메서드는 스크립트의 "콘텐츠"를 변경하거나 동기화하기 위해 클라이언트에서 호출됩니다. 스크립트의 코드가 변경되었음을 스크립트 공급자에게 알리는 알림입니다. 이 메서드는 스크립트를 실행하거나 스크립트가 조작하는 개체를 변경하지 않는다는 점에 유의해야 합니다. 이는 스크립트 공급자가 자체 내부 상태를 동기화할 수 있도록 스크립트의 콘텐츠가 변경되었음을 알리는 알림일 뿐입니다.
Execute 메서드는 마지막으로 성공한 Populate 호출에서 지시한 대로 스크립트의 콘텐츠를 실행하고 해당 콘텐츠에 따라 디버거의 개체 모델을 수정합니다. 언어(또는 스크립트 공급자)가 사용자 인터페이스에서 가상의 "스크립트 실행" 단추를 클릭할 때 작성자가 호출하려는 "기본 함수"를 정의하는 경우 이러한 "기본 함수"는 실행 작업 중에 호출되지 않습니다. 실행 작업은 초기화 및 개체 모델 조작만 수행하는 것으로 간주될 수 있습니다(예: 루트 코드 실행 및 확장성 지점 설정).
Unlink 메서드는 실행 작업을 실행 취소합니다. 스크립트를 실행하는 동안 설정된 개체 모델 조작 또는 확장 지점은 실행 취소됩니다. 연결 해제 작업 후 스크립트는 Execute 호출을 통해 다시 실행되거나 해제될 수 있습니다.
IsInvocable 메서드는 스크립트가 호출할 수 없는지, 즉 언어 또는 공급자가 정의한 "기본 함수"가 있는지 여부를 반환합니다. 이러한 "기본 함수"는 개념적으로 사용자 인터페이스에서 가상의 "스크립트 실행" 단추를 누른 경우 스크립트 작성자가 호출하려는 것입니다.
스크립트에 UI 호출에서 실행하려는 "기본 함수"가 있는 경우 IsInvocable 메서드의 실제 반환을 통해 이러한 함수를 나타냅니다. 그런 다음 사용자 인터페이스는 InvokeMain 메서드를 호출하여 실제로 스크립트를 "호출"할 수 있습니다. 이는 모든 루트 코드를 실행하고 스크립트를 기본 호스트의 네임스페이스에 연결하는 Execute 와 다릅니다.
**스크립트 클라이언트: IDataModelScriptClient **
스크립트를 관리하고 이 개념에 대한 사용자 인터페이스(그래픽 또는 콘솔 여부)를 갖고자 하는 데이터 모델을 호스팅하는 애플리케이션은 IDataModelScriptClient 인터페이스를 구현합니다. 이 인터페이스는 오류 및 이벤트 정보를 사용자 인터페이스에 다시 전달하기 위해 실행 또는 호출 중에 스크립트 공급자 또는 스크립트에 전달됩니다.
IDataModelScriptClient 인터페이스는 다음과 같이 정의됩니다.
DECLARE_INTERFACE_(IDataModelScriptClient, IUnknown)
{
STDMETHOD(ReportError)(_In_ ErrorClass errClass, _In_ HRESULT hrFail, _In_opt_ PCWSTR message, _In_ ULONG line, _In_ ULONG position) PURE;
}
스크립트를 실행하거나 호출하는 동안 오류가 발생하면 스크립트 공급자는 ReportError 메서드를 호출하여 사용자 인터페이스에 오류를 알립니다.
스크립트에 대한 호스트 컨텍스트: IDataModelScriptHostContext
디버그 호스트는 데이터 모델 스크립트 콘텐츠를 프로젝트하는 방법과 위치에 약간의 영향을 줍니다. 각 스크립트는 스크립트에 브리지를 배치할 컨텍스트(예: 호출할 수 있는 함수 개체 등)를 호스트에 요청해야 합니다. 이 컨텍스트는 IDebugHostScriptHost에서 CreateContext 메서드를 호출하고 IDataModelScriptHostContext를 가져와서 검색됩니다.
IDataModelScriptHostContext 인터페이스는 다음과 같이 정의됩니다.
DECLARE_INTERFACE_(IDataModelScriptHostContext, IUnknown)
{
STDMETHOD(NotifyScriptChange)(_In_ IDataModelScript* script, _In_ ScriptChangeKind changeKind) PURE;
STDMETHOD(GetNamespaceObject)(_COM_Outptr_ IModelObject** namespaceObject) PURE;
}
스크립트 공급자는 연결된 컨텍스트에서 NotifyScriptChange 메서드에 대한 메서드 호출을 통해 발생하는 특정 작업에 대해 디버그 호스트에 알려야 합니다. 이러한 작업은 ScriptChangeKind 열거형의 멤버로 정의됩니다.
GetNamespaceObject 메서드는 스크립트 공급자가 데이터 모델과 스크립트 사이에 브리지를 배치할 수 있는 개체를 반환합니다. 여기서는 instance 스크립트 공급자가 데이터 모델 메서드 개체(IModelMethod 인터페이스가 IModelObject에 박스형)를 배치할 수 있으며, 이 개체는 스크립트에서 해당 명명된 함수를 호출합니다.
새로 만든 스크립트에 대한 템플릿: IDataModelScriptTemplate
새 스크립트에 대해 미리 채워진 콘텐츠를 제공하려는 스크립트 공급자(예: 사용자가 디버거 사용자 인터페이스에서 스크립트를 작성하는 데 도움이 되도록)는 하나 이상의 스크립트 템플릿을 제공하여 이 작업을 수행할 수 있습니다. 이러한 템플릿은 IDataModelScriptTemplate 인터페이스를 구현하고 스크립트 공급자의 GetDefaultTemplate 메서드 또는 EnumerateTemplates 메서드를 통해 반환되는 구성 요소입니다.
IDataModelScriptTemplate 인터페이스는 다음과 같이 정의됩니다.
DECLARE_INTERFACE_(IDataModelScriptTemplate, IUnknown)
{
STDMETHOD(GetName)(_Out_ BSTR *templateName) PURE;
STDMETHOD(GetDescription)(_Out_ BSTR *templateDescription) PURE;
STDMETHOD(GetContent)(_COM_Outptr_ IStream **contentStream) PURE;
}
GetName 메서드는 템플릿의 이름을 반환합니다. 템플릿에 이름이 없는 경우 E_NOTIMPL 실패할 수 있습니다. 단일 기본 템플릿(있는 경우)은 이름을 가질 필요가 없습니다. 다른 모든 템플릿은 다음과 같습니다. 이러한 이름은 만들 템플릿을 선택하는 메뉴의 일부로 사용자 인터페이스에 표시될 수 있습니다.
GetDescription 메서드는 템플릿에 대한 설명을 반환합니다. 이러한 설명은 사용자가 템플릿이 수행하도록 설계된 작업을 이해하는 데 도움이 되도록 보다 설명적인 인터페이스로 사용자에게 제공됩니다. 템플릿은 설명이 없는 경우 이 메서드에서 E_NOTIMPL 반환할 수 있습니다.
GetContent 메서드는 템플릿의 콘텐츠(또는 코드)를 반환합니다. 사용자가 이 템플릿에서 새 스크립트를 만들기로 선택한 경우 편집 창에 미리 채워집니다. 템플릿은 클라이언트가 끌어올 수 있는 콘텐츠를 통해 표준 스트림을 만들고 반환하는 역할을 합니다.
공급자 템플릿 콘텐츠 열거: IDataModelScriptTemplateEnumerator
스크립트 공급자는 일부 사용자 인터페이스에서 새로 만든 스크립트에 콘텐츠를 미리 채우는 하나 이상의 템플릿을 제공할 수 있습니다. 이러한 템플릿이 제공된 경우 스크립트 공급자는 EnumerateTemplates 메서드를 호출할 때 반환되는 열거자를 구현해야 합니다.
이러한 열거자는 IDataModelScriptTemplateEnumerator 인터페이스의 구현이며 다음과 같이 정의됩니다.
DECLARE_INTERFACE_(IDataModelScriptTemplateEnumerator, IUnknown)
{
STDMETHOD(Reset)() PURE;
STDMETHOD(GetNext)(_COM_Outptr_ IDataModelScriptTemplate **templateContent) PURE;
}
Reset 메서드는 첫 번째 템플릿이 생성되기 전에 열거자를 처음 만들 때의 위치로 다시 설정합니다.
GetNext 메서드는 열거자를 다음 템플릿으로 이동하고 반환합니다. 열거형이 끝나면 열거자는 E_BOUNDS 반환합니다. E_BOUNDS 마커가 적중되면 다시 설정 호출이 이루어질 때까지 열거자는 E_BOUNDS 오류를 무기한 생성합니다.
이름의 의미 해결: IDataModelNameBinder
데이터 모델은 스크립트 공급자가 지정된 컨텍스트에서 지정된 이름의 의미를 결정하는 표준 방법(예: 다양한 스크립트 공급자에서 작동하는 foo.bar 막대의 의미 결정)을 제공합니다. 이 메커니즘을 이름 바인더라고 하며 IDataModelNameBinder 인터페이스로 표시됩니다. 이러한 바인더는 이름이 확인되는 방법과 개체에서 이름이 여러 번 정의된 충돌 해결 방법을 다루는 방법에 대한 규칙 집합을 캡슐화합니다. 이러한 규칙의 일부에는 프로젝션된 이름(데이터 모델에서 추가한 이름)이 네이티브 이름(디버그되는 언어의 형식 시스템에 있는 이름)에 대해 확인하는 방법과 같은 사항이 포함됩니다.
스크립트 공급자 간에 어느 정도 일관성을 제공하기 위해 데이터 모델의 스크립트 관리자는 기본 이름 바인더를 제공합니다. 이 기본 이름 바인더는 IDataModelScriptManager 인터페이스에서 GetDefaultNameBinder 메서드를 호출하여 가져올 수 있습니다. 이름 바인더 인터페이스는 다음과 같이 정의됩니다.
DECLARE_INTERFACE_(IDataModelNameBinder, IUnknown)
{
STDMETHOD(BindValue)(_In_ IModelObject* contextObject, _In_ PCWSTR name, _COM_Errorptr_ IModelObject** value, _COM_Outptr_opt_result_maybenull_ IKeyStore** metadata) PURE;
STDMETHOD(BindReference)(_In_ IModelObject* contextObject, _In_ PCWSTR name, _COM_Errorptr_ IModelObject** reference, _COM_Outptr_opt_result_maybenull_ IKeyStore** metadata) PURE;
STDMETHOD(EnumerateValues)(_In_ IModelObject* contextObject, _COM_Outptr_ IKeyEnumerator** enumerator) PURE;
STDMETHOD(EnumerateReferences)(_In_ IModelObject* contextObject, _COM_Outptr_ IKeyEnumerator** enumerator) PURE;
}
BindValue 메서드는 바인딩 규칙 집합에 따라 지정된 개체에 해당하는 contextObject.name 수행합니다. 이 바인딩의 결과는 값입니다. 값으로 기본 스크립트 공급자는 값을 사용하여 이름을 다시 할당할 수 없습니다.
BindReference 메서드는 바인딩 규칙 집합에 따라 지정된 개체에서 contextObject.name 동일한 작업을 수행한다는 점에서 BindValue와 유사합니다. 그러나 이 메서드의 바인딩 결과는 값 대신 참조입니다. 참조로 스크립트 공급자는 참조를 활용하여 이름에 다시 할당을 수행할 수 있습니다.
EnumerateValues 메서드는 BindValue 메서드의 규칙에 따라 개체에 바인딩할 이름 및 값 집합을 열거합니다. 동일한 값을 가진 여러 이름(기본 클래스, 부모 모델 등)을 반환할 수 있는 IModelObject의 EnumerateKeys, EnumerateValues 및 유사한 메서드와 달리 이 열거자는 BindValue 및 BindReference와 바인딩할 특정 이름 집합만 반환합니다. 이름은 중복되지 않습니다. IModelObject 메서드를 호출하는 것보다 이름 바인더를 통해 개체를 열거하는 비용이 훨씬 더 높습니다.
EnumerateReferences 메서드는 BindReference 메서드의 규칙에 따라 개체에 바인딩할 이름 및 참조 집합을 열거합니다. 동일한 값을 가진 여러 이름(기본 클래스, 부모 모델 등)을 반환할 수 있는 IModelObject의 EnumerateKeys, EnumerateValues 및 유사한 메서드와 달리 이 열거자는 BindValue 및 BindReference와 바인딩할 특정 이름 집합만 반환합니다. 이름은 중복되지 않습니다. IModelObject 메서드를 호출하는 것보다 이름 바인더를 통해 개체를 열거하는 비용이 훨씬 더 높습니다.
디버거 데이터 모델 C++ 스크립트 디버깅 인터페이스
데이터 모델의 스크립트 공급자를 위한 인프라는 스크립트 디버깅에 대한 개념도 제공합니다. 디버깅 기능을 디버그 호스트 및 데이터 모델을 호스트하는 디버거 애플리케이션에 노출하려는 모든 스크립트는 디버깅 가능한 스크립트가 IDataModelScript 인터페이스 외에도 IDataModelScriptDebug 인터페이스를 구현하도록 하여 이 작업을 수행할 수 있습니다. 스크립트에 이 인터페이스가 있으면 인프라에 디버깅할 수 있음을 나타냅니다.
IDataModelScriptDebug 인터페이스는 스크립트 공급자의 디버그 기능에 액세스하기 위한 시작점이지만 전체 디버그 기능을 제공하는 다른 인터페이스 집합에 의해 조인됩니다.
디버그 인터페이스는 다음과 같습니다.
인터페이스 | Description |
---|---|
IDataModelScriptDebug | 스크립트를 디버깅할 수 있도록 스크립트 공급자가 제공해야 하는 핵심 인터페이스입니다. 스크립트를 디버깅할 수 있는 경우 IDataModelScript 인터페이스의 구현 클래스는 IDataModelScriptDebug에 대해 QueryInterface여야 합니다. |
IDataModelScriptDebugClient | 스크립트 디버깅 기능을 제공하려는 사용자 인터페이스는 IDataModelScriptDebugClient 인터페이스를 구현합니다. 스크립트 공급자는 이 인터페이스를 사용하여 디버그 정보를 앞뒤로 전달합니다(예: 발생하는 이벤트, 중단점 등...) |
IDataModelScriptDebugStack | 스크립트 공급자는 호출 스택의 개념을 스크립트 디버거에 노출하기 위해 이 인터페이스를 구현합니다. |
IDataModelScriptDebugStackFrame | 스크립트 공급자는 호출 스택 내에서 특정 스택 프레임의 개념을 노출하기 위해 이 인터페이스를 구현합니다. |
IDataModelScriptDebugVariableSetEnumerator | 스크립트 공급자는 변수 집합을 노출하기 위해 이 인터페이스를 구현합니다. 이 집합은 함수에 대한 매개 변수 집합, 지역 변수 집합 또는 특정 scope 내의 변수 집합을 나타낼 수 있습니다. 정확한 의미는 인터페이스를 획득하는 방법에 따라 달라집니다. |
IDataModelScriptDebugBreakpoint | 스크립트 공급자는 이 인터페이스를 구현하여 스크립트 내에서 특정 중단점의 개념과 제어를 노출합니다. |
IDataModelScriptDebugBreakpointEnumerator | 스크립트 공급자는 이를 구현하여 현재 스크립트 내에 있는 모든 중단점을 열거합니다(사용 여부에 관계없이). |
일반적인 관리 인터페이스는 다음과 같습니다.
인터페이스 | Description |
---|---|
IDataModelScriptProvider | 스크립트 공급자가 구현해야 하는 핵심 인터페이스입니다. 특정 유형의 스크립트에 대한 공급자의 지원을 보급하고 특정 파일 확장자에 등록하기 위해 데이터 모델 관리자의 스크립트 관리자 부분에 등록된 인터페이스입니다. |
IDataModelScript | 공급자가 관리하는 특정 스크립트의 추상화입니다. 로드되거나 편집되는 각 스크립트에는 별도의 IDataModelScript instance |
IDataModelScriptClient | 사용자 인터페이스에 정보를 전달하기 위해 스크립트 공급자가 사용하는 클라이언트 인터페이스입니다. 스크립트 공급자는 이 인터페이스를 구현하지 않습니다. 스크립트 공급자를 사용하려는 데이터 모델을 호스트하는 애플리케이션은 그렇게 합니다. 스크립트 공급자는 스크립트 클라이언트의 메서드를 호출하여 상태, 오류 등을 보고합니다. |
IDataModelScriptHostContext | 스크립트 공급자가 스크립트 내용에 대한 컨테이너로 사용하는 호스트 인터페이스입니다. 디버거 애플리케이션의 개체 모델에 대해 수행하는 조작 이외의 스크립트 내용이 표시되는 방식은 특정 디버그 호스트에 달려 있습니다. 이 인터페이스를 사용하면 스크립트 공급자가 콘텐츠를 배치할 위치에 대한 정보를 가져올 수 있습니다. |
IDataModelScriptTemplate | 스크립트 공급자는 사용자가 스크립트를 작성하기 위한 시작 지점 역할을 하는 하나 이상의 템플릿을 제공할 수 있습니다. 기본 제공 편집기를 제공하는 디버거 애플리케이션은 이 인터페이스를 통해 공급자가 보급한 템플릿 콘텐츠로 새 스크립트를 미리 채울 수 있습니다. |
IDataModelScriptTemplateEnumerator | 스크립트 공급자가 지원하는 다양한 템플릿을 모두 보급하기 위해 구현하는 열거자 인터페이스입니다. |
IDataModelNameBinder | 이름 바인더 - 컨텍스트의 이름을 값과 연결할 수 있는 개체입니다. "foo.bar"과 같은 지정된 식의 경우 이름 바인더는 개체 "foo"의 컨텍스트에서 이름 "bar"를 바인딩하고 값 또는 참조를 생성할 수 있습니다. 이름 바인더는 일반적으로 스크립트 공급자에 의해 구현되지 않습니다. 오히려 데이터 모델에서 기본 바인더를 획득하고 스크립트 공급자가 사용할 수 있습니다. |
스크립트 디버깅 가능: IDataModelScriptDebug
디버깅할 수 있는 모든 스크립트는 IDataModelScript를 구현하는 동일한 구성 요소에 IDataModelScriptDebug 인터페이스가 있음을 통해 이 기능을 나타냅니다. 데이터 모델을 호스트하는 디버그 호스트 또는 디버거 애플리케이션에 의한 이 인터페이스에 대한 쿼리는 디버그 기능의 존재를 나타냅니다.
IDataModelScriptDebug 인터페이스는 다음과 같이 정의됩니다.
DECLARE_INTERFACE_(IDataModelScriptDebug, IUnknown)
{
STDMETHOD_(ScriptDebugState, GetDebugState)() PURE;
STDMETHOD(GetCurrentPosition)(_Out_ ScriptDebugPosition *currentPosition, _Out_opt_ ScriptDebugPosition *positionSpanEnd, _Out_opt_ BSTR *lineText) PURE;
STDMETHOD(GetStack)(_COM_Outptr_ IDataModelScriptDebugStack **stack) PURE;
STDMETHOD(SetBreakpoint)(_In_ ULONG linePosition, _In_ ULONG columnPosition, _COM_Outptr_ IDataModelScriptDebugBreakpoint **breakpoint) PURE;
STDMETHOD(FindBreakpointById)(_In_ ULONG64 breakpointId, _COM_Outptr_ IDataModelScriptDebugBreakpoint **breakpoint) PURE;
STDMETHOD(EnumerateBreakpoints)(_COM_Outptr_ IDataModelScriptDebugBreakpointEnumerator **breakpointEnum) PURE;
STDMETHOD(GetEventFilter)(_In_ ScriptDebugEventFilter eventFilter, _Out_ bool *isBreakEnabled) PURE;
STDMETHOD(SetEventFilter)(_In_ ScriptDebugEventFilter eventFilter, _In_ bool isBreakEnabled) PURE;
STDMETHOD(StartDebugging)(_In_ IDataModelScriptDebugClient *debugClient) PURE;
STDMETHOD(StopDebugging)(_In_ IDataModelScriptDebugClient *debugClient) PURE;
}
GetDebugState 메서드는 스크립트의 현재 상태(예: 실행 중인지 여부)를 반환합니다. 상태는 ScriptDebugState 열거형 내의 값으로 정의됩니다.
GetCurrentPosition' 메서드는 스크립트 내의 현재 위치를 반환합니다. 이 호출은 스크립트가 GetScriptState 호출이 ScriptDebugBreak를 반환하는 디버거로 분할된 경우에만 호출할 수 있습니다. 이 메서드에 대한 다른 호출이 잘못되었으며 실패합니다.
GetStack 메서드는 중단 위치에서 현재 호출 스택을 가져옵니다. 이 메서드는 스크립트가 디버거로 분할된 경우에만 호출할 수 있습니다.
SetBreakpoint 메서드는 스크립트 내에서 중단점을 설정합니다. 구현은 수동 선 및 열 위치를 자유롭게 조정하여 적절한 코드 위치로 이동할 수 있습니다. 중단점이 배치된 실제 줄 및 열 번호는 반환된 IDataModelScriptDebugBreakpoint 인터페이스에서 메서드 호출을 통해 검색할 수 있습니다.
SetBreakpoint 메서드를 통해 스크립트 내에서 만들어진 각 중단점에는 구현에 의해 고유 식별자(64비트 부호 없는 정수)가 할당됩니다. FindBreakpointById 메서드는 지정된 식별자에서 중단점에 대한 인터페이스를 가져오는 데 사용됩니다.
EnumerateBreakpoints 메서드는 특정 스크립트 내에서 설정된 모든 중단점을 열거할 수 있는 열거자를 반환합니다.
GetEventFilter 메서드는 특정 이벤트에 대해 "이벤트 중단"이 사용되는지 여부를 반환합니다. "이벤트 중단"을 일으킬 수 있는 이벤트는 ScriptDebugEventFilter 열거형의 멤버에 의해 설명됩니다.
SetEventFilter 메서드는 ScriptDebugEventFilter 열거형의 멤버가 정의한 대로 특정 이벤트에 대한 "이벤트 중단" 동작을 변경합니다. 사용 가능한 이벤트의 전체 목록(및 이 열거형에 대한 설명)은 GetEventFilter 메서드에 대한 설명서에서 찾을 수 있습니다.
StartDebugging 메서드는 특정 스크립트에 대한 디버거를 "켭니다". 디버깅을 시작하는 동작으로 인해 실행 중단 또는 단계별 실행이 적극적으로 수행되지는 않습니다. 스크립트를 디버깅할 수 있도록 하고 클라이언트가 디버깅 인터페이스와 통신할 수 있는 인터페이스 집합을 제공합니다.
StopDebugging 메서드는 디버깅을 중지하려는 클라이언트에 의해 호출됩니다. 이 메서드 호출은 StartDebugging이 성공적으로 수행된 후 언제든지 수행할 수 있습니다(예: 중단 중, 스크립트가 실행되는 동안 등). 호출은 즉시 모든 디버깅 작업을 중단하고 StartDebugging이 호출되기 전에 상태를 다시 로 다시 설정합니다.
디버깅 인터페이스: IDataModelScriptDebugClient
스크립트 디버깅과 관련된 인터페이스를 제공하려는 디버그 호스트 또는 디버거 애플리케이션은 스크립트에 대한 디버그 인터페이스의 StartDebugging 메서드를 통해 스크립트 디버거에 IDataModelScriptDebugClient 인터페이스의 구현을 제공해야 합니다.
IDataModelScriptDebugClient는 디버그 이벤트가 전달되고 컨트롤이 스크립트 실행 엔진에서 디버거 인터페이스로 이동되는 통신 채널입니다. 다음과 같이 정의됩니다.
DECLARE_INTERFACE_(IDataModelScriptDebugClient, IUnknown)
{
STDMETHOD(NotifyDebugEvent)(_In_ ScriptDebugEventInformation *pEventInfo, _In_ IDataModelScript *pScript, _In_opt_ IModelObject *pEventDataObject, _Inout_ ScriptExecutionKind *resumeEventKind) PURE;
}
스크립트 디버거에 침입하는 이벤트가 발생할 때마다 디버그 코드 자체는 NotifyDebugEvent 메서드를 통해 인터페이스를 호출합니다. 이 메서드는 동기적이며, 인터페이스가 이벤트에서 반환될 때까지 스크립트 실행이 다시 시작되지 않습니다. 스크립트 디버거의 정의는 간단하기 위한 것입니다. 처리가 필요한 중첩된 이벤트는 전혀 없습니다. 디버그 이벤트는 ScriptDebugEventInformation이라는 변형 레코드에 의해 정의됩니다. 이벤트 정보의 유효한 필드는 주로 DebugEvent 멤버에 의해 정의됩니다. ScriptDebugEvent 열거형의 멤버가 설명한 대로 발생한 이벤트의 종류를 정의합니다.
호출 스택: IDataModelScriptDebugStack
스크립트 디버거에 침입하는 이벤트가 발생하면 디버깅 인터페이스는 중단 위치에 대한 호출 스택을 검색하려고 합니다. GetStack 메서드를 통해 수행됩니다. 이러한 스택은 아래에 표시된 대로 정의된 IDataModelScriptDebugStack을 통해 표현됩니다.
전체 스택은 여러 스크립트 및/또는 여러 스크립트 공급자에 걸쳐 있을 수 있습니다. 특정 스크립트의 디버그 인터페이스에서 GetStack 메서드에 대한 단일 호출에서 반환되는 호출 스택은 해당 스크립트의 범위 내에서 호출 스택의 세그먼트만 반환해야 합니다. 동일한 공급자의 두 스크립트가 상호 작용하는 경우 스크립트 디버그 엔진이 여러 스크립트 컨텍스트에 걸쳐 호출 스택을 검색할 수 있습니다. GetStack 메서드는 다른 스크립트에 있는 스택 부분을 반환해서는 안 됩니다. 대신 이 상황을 감지할 수 있는 경우 스크립트의 경계 프레임인 스택 프레임은 해당 스택 프레임에서 IsTransitionPoint 및 GetTransition 메서드의 구현을 통해 전환 프레임으로 표시되어야 합니다. 디버거 인터페이스는 존재하는 여러 스택 세그먼트의 전체 스택을 함께 연결합니다.
이러한 방식으로 전환을 구현하거나 디버그 인터페이스가 지역 변수, 매개 변수, 중단점 및 기타 스크립트 관련 구문에 대한 문의를 잘못된 스크립트 컨텍스트로 안내할 수 있어야 합니다. 그러면 디버거 인터페이스에서 정의되지 않은 동작이 발생합니다.
DECLARE_INTERFACE_(IDataModelScriptDebugStack, IUnknown)
{
STDMETHOD_(ULONG64, GetFrameCount)() PURE;
STDMETHOD(GetStackFrame)(_In_ ULONG64 frameNumber, _COM_Outptr_ IDataModelScriptDebugStackFrame **stackFrame) PURE;
}
GetFrameCount 메서드는 호출 스택의 이 세그먼트에 있는 스택 프레임 수를 반환합니다. 공급자가 다른 스크립트 컨텍스트 또는 다른 공급자의 프레임을 검색할 수 있는 경우 이 스택 세그먼트의 진입 프레임에서 IsTransitionPoint 및 GetTransition 메서드를 구현하여 호출자에게 이를 표시해야 합니다.
GetStackFrame은 스택 세그먼트에서 특정 스택 프레임을 가져옵니다. 호출 스택에는 0부터 시작하는 인덱싱 시스템이 있습니다. 중단 이벤트가 발생한 현재 스택 프레임은 프레임 0입니다. 현재 메서드의 호출자는 프레임 1(등)입니다.
손상 시 상태 검사: IDataModelScriptDebugStackFrame
스크립트 디버거로 나눌 때 호출 스택의 특정 프레임은 중단이 발생한 스택 세그먼트를 나타내는 IDataModelScriptDebugStack 인터페이스의 GetStackFrame 메서드 호출을 통해 검색할 수 있습니다. 이 프레임을 나타내기 위해 반환되는 IDataModelScriptDebugStackFrame 인터페이스는 다음과 같이 정의됩니다.
DECLARE_INTERFACE_(IDataModelScriptDebugStackFrame, IUnknown)
{
STDMETHOD(GetName)(_Out_ BSTR *name) PURE;
STDMETHOD(GetPosition)(_Out_ ScriptDebugPosition *position, _Out_opt_ ScriptDebugPosition *positionSpanEnd, _Out_opt_ BSTR *lineText) PURE;
STDMETHOD(IsTransitionPoint)(_Out_ bool *isTransitionPoint) PURE;
STDMETHOD(GetTransition)(_COM_Outptr_ IDataModelScript **transitionScript, _Out_ bool *isTransitionContiguous) PURE;
STDMETHOD(Evaluate)(_In_ PCWSTR pwszExpression, _COM_Outptr_ IModelObject **ppResult) PURE;
STDMETHOD(EnumerateLocals)(_COM_Outptr_ IDataModelScriptDebugVariableSetEnumerator **variablesEnum) PURE;
STDMETHOD(EnumerateArguments)(_COM_Outptr_ IDataModelScriptDebugVariableSetEnumerator **variablesEnum) PURE;
}
GetName 메서드는 이 프레임의 표시 이름(예: 함수 이름)을 반환합니다. 이러한 이름은 디버거 인터페이스에서 사용자에게 표시되는 스택 백트레이스 내에 표시됩니다.
GetPosition 메서드는 스택 프레임이 나타내는 스크립트 내의 위치를 반환합니다. 이 메서드는 스크립트가 이 프레임이 포함된 스택이 나타내는 중단 내에 있는 경우에만 호출할 수 있습니다. 이 프레임 내의 선 및 열 위치는 항상 반환됩니다. 디버거가 스크립트 내에서 "실행 위치"의 범위를 반환할 수 있는 경우 positionSpanEnd 인수에서 끝 위치를 반환할 수 있습니다. 디버거가 이를 수행할 수 없는 경우 범위 끝의 줄 및 열 값(요청된 경우)을 0으로 설정해야 합니다.
IDataModelScriptDebugStack 인터페이스는 한 스크립트의 컨텍스트 내에 포함된 호출 스택의 해당 부분인 호출 스택의 세그먼트를 나타냅니다. 디버거가 한 스크립트에서 다른 스크립트(또는 한 스크립트 공급자에서 다른 스크립트 공급자로)로의 전환을 검색할 수 있는 경우 IsTransitionPoint 메서드를 구현하고 true 또는 false를 적절하게 반환하여 이를 나타낼 수 있습니다. 세그먼트가 적용되는 스크립트에 입력한 호출 스택 프레임은 전환 지점으로 간주되어야 합니다. 다른 모든 프레임은 그렇지 않습니다.
지정된 스택 프레임이 IsTransition 메서드에 의해 결정된 전환 지점인 경우(전환 지점 정의에 대한 설명서 참조) GetTransition 메서드는 전환에 대한 정보를 반환합니다. 특히 이 메서드는 이 IDataModelScriptDebugStackFrame을 포함하는 스택 세그먼트가 나타내는 스크립트를 호출한 이전 스크립트를 반환합니다.
Evaluate 메서드는 이 메서드가 호출된 IDataModelScriptDebugStackFrame 인터페이스가 나타내는 스택 프레임의 컨텍스트에서 (스크립트 공급자의 언어) 식을 평가합니다. 식 계산 결과는 스크립트 공급자에서 IModelObject로 마샬링되어야 합니다. 결과 IModelObject의 속성 및 기타 구문은 디버거가 중단 상태에 있는 동안 모두 가져올 수 있어야 합니다.
EnumerateLocals 메서드는 이 메서드가 호출된 IDataModelScriptDebugStackFrame 인터페이스가 나타내는 스택 프레임의 컨텍스트에서 scope 있는 모든 지역 변수에 대해 변수 집합(IDataModelScriptDebugVariableSetEnumerator 인터페이스로 표시됨)을 반환합니다.
EnumerateArguments 메서드는 이 메서드가 호출된 IDataModelScriptDebugStackFrame 인터페이스가 나타내는 스택 프레임에서 호출된 함수의 모든 함수 인수에 대해 변수 집합(IDataModelScriptDebugVariableSetEnumerator 인터페이스로 표시됨)을 반환합니다.
변수 보기: IDataModelScriptDebugVariableSetEnumerator
디버그되는 스크립트의 변수 집합(특정 scope, 함수의 로컬, 함수의 인수 등)은 IDataModelScriptDebugVariableSetEnumerator 인터페이스를 통해 정의된 변수 집합으로 표시됩니다.
DECLARE_INTERFACE_(IDataModelScriptDebugVariableSetEnumerator, IUnknown)
{
STDMETHOD(Reset)() PURE;
STDMETHOD(GetNext)(_Out_ BSTR *variableName, _COM_Outptr_opt_ IModelObject **variableValue, _COM_Outptr_opt_result_maybenull_ IKeyStore **variableMetadata) PURE;
}
Reset 메서드는 열거자의 위치를 생성 직후 위치( 즉, 집합의 첫 번째 요소 앞)로 다시 설정합니다.
GetNext 메서드는 열거자를 집합의 다음 변수로 이동하고 변수의 이름, 값 및 관련 메타데이터를 반환합니다. 열거자가 집합의 끝에 도달하면 오류 E_BOUNDS 반환됩니다. GetNext 메서드에서 E_BOUNDS 마커가 반환되면 중간 초기화 호출이 이루어지지 않는 한 다시 호출될 때 E_BOUNDS 계속 생성됩니다.
중단점: IDataModelScriptDebugBreakpoint
스크립트 중단점은 지정된 스크립트의 디버그 인터페이스에서 SetBreakpoint 메서드를 통해 설정됩니다. 이러한 중단점은 고유 ID와 다음과 같이 정의된 IDataModelScriptDebugBreakpoint 인터페이스의 구현으로 표시됩니다.
DECLARE_INTERFACE_(IDataModelScriptDebugBreakpoint, IUnknown)
{
STDMETHOD_(ULONG64, GetId)() PURE;
STDMETHOD_(bool, IsEnabled)() PURE;
STDMETHOD_(void, Enable)() PURE;
STDMETHOD_(void, Disable)() PURE;
STDMETHOD_(void, Remove)() PURE;
STDMETHOD(GetPosition)(_Out_ ScriptDebugPosition *position, _Out_opt_ ScriptDebugPosition *positionSpanEnd, _Out_opt_ BSTR *lineText) PURE;
}
GetId 메서드는 스크립트 공급자의 디버그 엔진에서 할당한 고유 식별자를 중단점에 반환합니다. 이 식별자는 포함된 스크립트의 컨텍스트 내에서 고유해야 합니다. 중단점 식별자는 공급자에 고유할 수 있습니다. 그러나 필수는 아닙니다.
IsEnabled 메서드는 중단점 사용 여부를 반환합니다. 비활성화된 중단점은 여전히 존재하며 스크립트에 대한 중단점 목록에 여전히 있으며 일시적으로 "꺼져" 있을 뿐입니다. 모든 중단점은 활성화된 상태로 만들어야 합니다.
사용
Enable 메서드를 사용하면 중단점이 활성화됩니다. 중단점이 비활성화된 경우 이 메서드를 호출한 후 "중단점을 적중"하면 디버거가 중단됩니다.
사용 안 함
Disable 메서드는 중단점을 사용하지 않도록 설정합니다. 이 호출 후에는 이 메서드를 호출한 후 "중단점 적중"이 디버거에 침입하지 않습니다. 중단점은 여전히 존재하지만 "꺼짐"으로 간주됩니다.
Remove 메서드는 포함된 목록에서 중단점을 제거합니다. 이 메서드가 반환된 후에 중단점이 더 이상 의미 체계적으로 존재하지 않습니다. 중단점을 나타내는 IDataModelScriptDebugBreakpoint 인터페이스는 호출 후 분리된 것으로 간주됩니다. 이 호출 후에는 해제하는 것 외에 다른 어떤 것도 (법적으로) 수행할 수 없습니다.
GetPosition 메서드는 스크립트 내에서 중단점의 위치를 반환합니다. 스크립트 디버거는 중단점이 있는 소스 코드 내에서 줄과 열을 반환해야 합니다. 이렇게 할 수 있는 경우 positionSpanEnd 인수에 정의된 끝 위치를 입력하여 중단점이 나타내는 원본 범위를 반환할 수도 있습니다. 디버거가 이 범위를 생성할 수 없고 호출자가 요청하는 경우 범위의 끝 위치의 줄 및 열 필드를 0으로 채워 값을 제공할 수 없음을 나타냅니다.
중단점 열거형: IDataModelScriptDebugBreakpointEnumerator
스크립트 공급자가 디버깅을 지원하는 경우 각 스크립트와 연결된 모든 중단점을 추적하고 해당 중단점을 디버그 인터페이스에 열거할 수 있어야 합니다. 중단점에 대한 열거자는 지정된 스크립트에 대한 디버그 인터페이스의 EnumerateBreakpoints 메서드를 통해 획득되며 다음과 같이 정의됩니다.
DECLARE_INTERFACE_(IDataModelScriptDebugBreakpointEnumerator, IUnknown)
{
STDMETHOD(Reset)() PURE;
STDMETHOD(GetNext)(_COM_Outptr_ IDataModelScriptDebugBreakpoint **breakpoint) PURE;
}
Reset 메서드는 열거자의 위치를 열거자가 생성된 직후의 위치( 즉, 첫 번째 열거형 중단점 이전)로 다시 설정합니다.
GetNext 메서드는 열거자를 열거할 다음 중단점으로 앞으로 이동하고 해당 중단점에 대한 IDataModelScriptDebugBreakpoint 인터페이스를 반환합니다. 열거자가 열거형의 끝에 도달하면 E_BOUNDS 반환합니다. E_BOUNDS 오류가 발생하면 Reset 메서드에 대한 중간 호출이 이루어지지 않는 한 GetNext 메서드에 대한 후속 호출은 E_BOUNDS 계속 생성됩니다.
참고 항목
이 항목은 C++에서 액세스할 수 있는 인터페이스, 이를 사용하여 C++ 기반 디버거 확장을 빌드하는 방법, C++ 데이터 모델 확장에서 다른 데이터 모델 구문(예: JavaScript 또는 NatVis)을 사용하는 방법을 설명하는 시리즈의 일부입니다.