У меня есть устаревший COM-контроль (Core), который принимает IUnknown
к раковине. Цель состоит в том, чтобы позволить Core считывать/записывать данные через этот интерфейс приемника. Указатели Core/Sink в настоящее время используются в устаревших системах и не легко модифицируются.Внедрение COM-раковины в управляемом (C#) коде
Проблема, с которой я сталкиваюсь, заключается в попытке вызвать ядро из управляемого кода и передать объект, который (пытается) реализовать приемник в управляемом коде. Я отлаживал Core до такой степени, что он готовится к вызову раковины. До (не после) вызова, я получаю сообщение, похожее на:
Run-Time Check Failure # 0 - значение ESP не была должным образом сохраненные через вызов функции ...
Я видел и работал с ними в чистом устаревшем коде, но введение управляемого кода вызывает у меня недоумение.
Здесь представлены наименьшие изображения двух интерфейсов, которые, я считаю, необходимы.
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
}
данные доступ «раковина», как из IDL (пониженная для проблемной легкости демонстрации)
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);
}
Я пробовал различные реализации раковины в C#, но безрезультатно или изменить в условия ошибки. Вот самая последняя реализация, и да, я вручную кодировал определение интерфейса, так как использование одного из типа lib не сработало. (Тот же вопрос)
[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();
}
}
Возможно интерес: http://stackoverflow.com/questions/1787422/an-idiomatic-way-of-wrapping-a-possible-transient-object –
Является ли ваш собственный COM-сервер построенным с помощью MBCS или Unicode? –
@Ben, спасибо за ссылку, однако, похоже, это не помогает. @ Шэн Цзян, сервер COM построен с MBCS. Я могу внести в него изменения и построить источник; однако из-за других ограничений он должен оставаться MBCS и не может быть перемещен в Юникод. – DevSolo