ISomeClass : IUnknown
{
HRESULT SomeMethod( in la, out la, out retval la);
}
ComClassesLib.SomeClass cl = new ComClassesLib.SomeClass();
string str = cl.SomeMethod();
interface ISomeClass : IUnknown{
[, helpstring("method SomeMethod")] HRESULT SomeMethod([in] BSTR ostr, [out,retval] BSTR* pstr);
};
////////////////////////////////////////////////////////////
library ComClassesLib
{
importlib("stdole2.tlb");
[
uuid(232ED11B-118D-463F-AEE4-B569220A4504)
]
coclass SomeClass
{
[default] interface ISomeClass;
};
};
class ATL_NO_VTABLE CSomeClass :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CSomeClass, &CLSID_SomeClass>,
public ISomeClass
{
public:
STDMETHOD(SomeMethod)(BSTR ostr, BSTR* pstr);
}
STDMETHODIMP CSomeClass::SomeMethod(BSTR ostr, BSTR* pstr)
{
CString mstr(ostr);
mstr.Replace(' ', '_');
*pstr = mstr.AllocSysString();
return S_OK;
}
почти не работал с ком-обьектами, но наверняка надо высвободить память вручную, с каких делов сборщик будет это делать за тебя, ссылку на обьект он съест, когда она перестанет быть нужна, а сам обьект не в его власти, если он сам себя высвободит, то все ок, если нет останется в памяти - зависит от реализации самого ком-обьекта, вероятнее всего что сам он этого делать не будетВопрос в следующем:
Так до конца и не понял, нужно ли мне явно реализовывать метод Release() для ISomeClass, чтобы уменьшать кол-во объектов и освобождать память или же освобождение происходит и так? И высвободится ли ком, когда "cl" уничтожится мусорщиком?
Насколько я понимаю COM объект считает ссылки на себя сам, это изначально задумано
QueryInterface; AddRef; Release
GC пнятия не имеет о неуправляемом коде и вообще не его это дело лезть в COM Объекты
если ты с объектом работаешь как с .NET компонентом а не лезешь напрямую, проблем не должно быть.
не напрямую. при вставке библиотеки в проект студия создает интероп и представляет объект как .net структуру. на мсдне описаны два способа, один такой, а другой конвертация таблицы типов библиотеки в .net используя tblimp.exe, тогда вообще она воспринимается проектом как .net, и этот же способ более рекомендуемый. Но хотелось разобраться с первым, он необходим если я понятия не имею как реализован используемый COM, насколько я понял.
ATL за тебя уже все что надо реализовал, т.е. про Iunknown можешь не волноваться.
C# за тебя все почистит когда сообразит что больше никто референса на объект не держит. Но такое бывает редко и какие-то сопли неучтенных референсов остаются.
Так что если очень надо - Marshal.ReleaseComObject, это железно грохнет твой объект, если ты конечно все правильно сделал в его реализации (т.е. не через жопу).
TLB обычно есть всегда, а без него ты не узнаешь нихера про методы и сигнатуры. Ну а если все только на бумаге, то да - Interop в зубы и удачи.
Отлично. Спасибо за четкий ответ.
Прочитал что-то вроде того, что нужно наследовать ком и использовать IDisposable, тогда при финализации произойдет релиз.
The runtime creates exactly one RCW for each COM object, regardless of the number of references that exist on that object. The runtime maintains a single RCW per process for each object. If you create an RCW in one application domain or apartment, and then pass a reference to another application domain or apartment, a proxy to the first object will be used. As the following illustration shows, any number of managed clients can hold a reference to the COM objects that expose INew and INewer interfaces.
Using metadata derived from a type library, the runtime creates both the COM object being called and a wrapper for that object. Each RCW maintains a cache of interface pointers on the COM object it wraps and releases its reference on the COM object when the RCW is no longer needed. The runtime performs garbage collection on the RCW.