2017-10-19 88 views
1

我正在使用本机窗口API和chakrart JavaScript引擎创建可编写脚本的应用程序。 我喜欢在我的IDL以下接口:基于Chakra和IDispatch的索引属性

[oleautomation, dual, nonextensible, 
uuid(...)] 
interface IMyInterface : IDispatch 
{ 
[id(MYDISPID_EVENT), propget] HRESULT Event(BSTR strEventName, [out, retval] IDispatch ** ppHandler); 
[id(MYDISPID_EVENT), propput] HRESULT Event(BSTR strEventName, IDispatch * pHandler); 
}; 

我已经能够原生对象添加到chakrart发动机无故障(通过使用JsVariantToValue然后当前上下文的全局对象上设置属性)。但是,当我尝试设置事件处理程序时,我收到异常消息“对象不支持此属性或方法”。

我已经试过的语法如下变化:

object.Event["foo"] = handler; 
object.Event("foo", handler); 
object.put_Event("foo", handler); 
object.Event("foo") = handler; 

这最后接近于如何做到这一点使用来完成的VBScript:

object.Event("foo") = GetRef("handler) 

如果我使用方法的语法在IDL像下面它的工作原理,我只是希望尽可能使用财产分配。

[id(MYDISPID_GETEVENT)] HRESULT GetEvent(BSTR strEventName, [out, retval] IDispatch ** ppHandler); 
[id(MYDISPID_SETEVENT)] HRESULT SetEvent(BSTR strEventName, IDispatch * pHandler); 

而且还要注意,简单的属性分配确实有效,它只有当我尝试索引属性,它打破。我明白JavaScript至少对于本地JavaScript对象来说与对象[prop]语法有很大不同。这可能仅仅是一个不兼容的chakrart互操作层?

+0

所以我没有给你答案,但我即将尝试做类似的事情,并且很好奇你是如何注册你的本地对象的?您是否创建了一个类型为VT_DISPATCH的VARIANT,其中包含对象的IDispatch指针,将它传递给JsVariantToValue,然后将该值作为全局对象的属性注册? –

+1

这正是我所做的。这也意味着我卡住了使用ChakraRT而不是能够使用ChakraCore,ChakraCore是引擎的便携式部分,但IDispatch不是,所以...我也写了一个函数,它需要IDispatch和ITypeInfo指针和寄存器所有可分派的成员作为全局的属性。这是因为JavaScript运行时托管没有像IActiveScript :: AddNamedItem s SCRIPTITEM_GLOBALMEMBERS标志。 抱歉多次删除我的回复,我失明了,编辑框与我的屏幕阅读器表现不佳。 – SoronelHaetir

回答

0

我已经确认了一种使用所需语法(App.Event ['foo'] = someHandler;)执行此操作的方法。正如前面提到的,我已经知道JavaScript会将名称['foo'视为成员名称

让App对象为Event实现propget,该对象具有自定义(非双接口)IDispatch实现。该对象将名称映射到DISPID,并且每当通过GetIDsOfNames请求未知名称时,都会返回一个先前未分配的DISPID。

请注意,为了符合IDispatch的规则,即使稍后将空处理程序分配给给定名称,对象也需要跟踪名称,以便始终为特定名称返回相同的DISPID。

+0

我与ChakraRT团队进行了联系,他们确认IDispatch的支持是最基本的,而且索引的属性不起作用。只要只需要一个索引器(就像我的例子中那样),并且该值可以转换为可用的字符串(同样在我的示例中),我所给出的解决方法就会起作用。但是,如果您需要一个对象来工作多语言(特别是如果你需要JavaScript和VBScript),它可能会更好,只是去方法路线(从我原来的问题GetEvent/SetEvent)。 – SoronelHaetir