2017-10-19 12 views
1

Je crée une application scriptable en utilisant l'API native windows et le moteur JavaScript chakrart. J'ai des interfaces comme suit dans mon IDL:Propriétés indexées basées sur Chakra et 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); 
}; 

Je suis en mesure d'ajouter les objets natifs au moteur chakrart sans problème (en utilisant JsVariantToValue puis définir une propriété sur l'objet global du contexte actuel). Toutefois, lorsque je tente de définir un gestionnaire d'événements, le message d'exception "Objet ne prend pas en charge cette propriété ou cette méthode" s'affiche.

J'ai essayé les variations de syntaxe suivantes:

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

Ce dernier est proche de la façon dont cela se fait à l'aide vbscript:

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

Si j'utilise la syntaxe de méthode dans le IDL comme ce qui suit cela fonctionne, je préférerais simplement utiliser l'assignation de propriété si possible.

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

Et notez aussi que les affectations de propriétés simples fonctionnent, il est seulement quand j'essaie propriétés indexées qu'il casse. Je comprends que JavaScript fait quelque chose de très différent avec la syntaxe object [prop], au moins pour les objets JavaScript natifs. Est-ce simplement une incompatibilité dans la couche d'interopérabilité de chakrart?

+0

Donc, je n'ai pas de réponse pour vous, mais je suis sur le point d'essayer de faire quelque chose de similaire et je suis curieux de savoir exactement comment vous avez enregistré votre objet natif? Avez-vous créé un VARIANT de type VT_DISPATCH contenant le pointeur IDispatch de votre objet, passez-le à JsVariantToValue, puis enregistrez cette valeur en tant que propriété sur l'objet global? –

+1

C'est exactement ce que j'ai fait. Cela signifie également que je suis coincé en utilisant ChakraRT plutôt que d'être en mesure d'utiliser ChakraCore, ChakraCore est les parties portables du moteur mais IDispatch n'est pas, donc ... J'ai aussi écrit une fonction qui prend les pointeurs et les registres IDispatch et ITypeInfo tous les membres dispatchables en tant que propriétés du global. Cela est dû au fait que l'exécution de JavaScript à l'exécution n'a rien de tel que l'indicateur SCRIPTITEM_GLOBALMEMBERS d'IActiveScript :: AddNamedItem s. Et désolé pour la suppression de ma réponse à plusieurs reprises, je suis aveugle et la boîte d'édition se comporte mal avec mon lecteur d'écran. – SoronelHaetir

Répondre

0

J'ai confirmé un moyen d'effectuer cela avec la syntaxe désirée (App.Event ['foo'] = someHandler;). Comme mentionné, je savais déjà JavaScript traite le nom [ « foo »] comme une recherche de membre sur le nom

Demandez l'objet App mettre en œuvre un propget pour l'événement qui retourne un objet avec une coutume (interface non-double) mise en œuvre IDispatch. Cet objet conserve une carte de noms à DISPID et chaque fois qu'un nom inconnu est demandé via GetIDsOfNames, un DISPID non attribué précédemment est renvoyé. Notez que pour respecter les règles de IDispatch, l'objet doit garder la trace des noms même si un gestionnaire null est attribué ultérieurement à un nom donné, afin que le même DISPID soit toujours renvoyé pour un nom particulier.

+0

J'ai géré le contact avec l'équipe de ChakraRT et ils ont confirmé que le support d'IDispatch est strict et que les propriétés indexées ne fonctionneront pas. Cela étant dit tant qu'un seul indexeur est nécessaire (comme dans mon exemple) et que cette valeur peut être convertie en une chaîne utilisable (comme dans mon exemple), la solution de contournement que j'ai donnée fonctionnera. Cependant, si vous avez besoin d'un objet pour travailler plusieurs langues (en particulier si vous avez besoin à la fois de JavaScript et de VBScript), il vaudrait peut-être mieux utiliser la méthode route (GetEvent/SetEvent de ma question initiale). – SoronelHaetir