J'ai un ancien contrôle COM (Core) qui accepte un IUnknown
dans un lavabo. Le but est de permettre au Core de lire/écrire des données via cette interface de récepteur. Les pointeurs Core/Sink sont actuellement utilisés dans les systèmes hérités et ne sont pas facilement modifiables.Implémentation d'un «évier» COM dans le code géré (C#)
Le problème que j'ai est quand je tente d'appeler le noyau à partir du code managé et transmettre un objet qui (tente) pour implémenter le récepteur dans le code managé. J'ai débogué le noyau au point qu'il se prépare à appeler l'évier. Avant (et non après) l'appel, je reçois un message semblable à:
Run-Time Échec de la vérification # 0 - La valeur de l'ESP n'a pas été correctement conservé après un appel de fonction ...
J'ai vu et travaillé à travers ceux-ci dans le code hérité pur, mais l'introduction du code managé m'a rendu perplexe.
Voici les plus petites représentations des deux interfaces que je crois nécessaires.
interface ICore : IDispatch
{
[id(1), helpstring("method Init")] HRESULT Init([in] IUnknown *pDataManSink);
HRESULT FireOnImport([in] LPCOLESTR pszFormName, [in] LPCOLESTR pszTagName, [in] VARIANT pszData);
... more methods
}
accès aux données « puits » à partir du IDL (réduit pour la démonstration des problèmes de facilité)
interface IDataManagerSinkEx : IUnknown
{
[helpstring("method ReadData")] HRESULT ReadData([in] LPCTSTR pszDataKey, [out, retval] BSTR* pbsData);
[helpstring("method WriteData")] HRESULT WriteData([in] LPCTSTR pszDataKey, [in] LPCTSTR pszData);
[helpstring("method ReadDataEx")] HRESULT ReadTagEx([in] LPCTSTR pszDataKey, [out] short *pwExtraInfoOut, [out, retval] BSTR *pbsData);
[helpstring("method WriteDataEx")] HRESULT WriteTagEx([in] LPCTSTR pszDataKey, [in] short wExtraInfo, [in] LPCTSTR pszData);
}
J'ai essayé une variété d'implémentations de l'évier en C#, sans résultat ou le changement de conditions d'erreur. Voici l'implémentation la plus courante, et oui, j'ai codé à la main la définition de l'interface, en utilisant celle du type lib ne fonctionnait pas. (même problème)
[ComImport]
[Guid("AB79770E-8143-45E6-B082-E985E6DFA5CB")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IMyDataManagerSinkEx
{
[PreserveSig]
int ReadData([MarshalAs(UnmanagedType.LPStr)]string pszDataKey, out string data);
[PreserveSig]
int WriteTag([MarshalAs(UnmanagedType.LPStr)]string pszDataKey, [MarshalAs(UnmanagedType.LPStr)]string pszData);
[PreserveSig]
int ReadTagEx([MarshalAs(UnmanagedType.LPStr)]string pszDataKey, out short pwExraInfoOut, out string dataOut);
[PreserveSig]
int WriteTagEx([MarshalAs(UnmanagedType.LPStr)]string pszDataKey, short wExtraInfo, [MarshalAs(UnmanagedType.LPStr)]string pszData);
}
class public SinkImpl : IMyDataManagerSinkEx
{
[PreserveSig]
public int ReadData([MarshalAs(UnmanagedType.LPStr)]string pszDataKey, out string data)
{
throw new NotImplementedException();
}
[PreserveSig]
public int WriteTag([MarshalAs(UnmanagedType.LPStr)]string pszDataKey, [MarshalAs(UnmanagedType.LPStr)]string pszData)
{
throw new NotImplementedException();
}
[PreserveSig]
public int ReadTagEx([MarshalAs(UnmanagedType.LPStr)]string pszDataKey, out short pwExraInfoOut, out string dataOut)
{
throw new NotImplementedException();
}
[PreserveSig]
public int WriteTagEx([MarshalAs(UnmanagedType.LPStr)]string pszDataKey, short wExtraInfo, [MarshalAs(UnmanagedType.LPStr)]string pszData)
{
throw new NotImplementedException();
}
}
Peut-être intéressant: http://stackoverflow.com/questions/1787422/an-idiomatic-way-of-wrapping-a-possibly-transient-object –
Votre serveur COM natif est-il construit avec MBCS ou Unicode? –
@Ben, merci pour le lien, cependant, cela ne semble pas aider. @Sheng Jiang, le serveur COM est construit avec MBCS. Je peux y apporter des modifications et construire la source; Toutefois, en raison d'autres limitations, il doit rester MBCS et ne peut pas être déplacé vers Unicode. – DevSolo