Malonu kai visas projektas būna parašytas viena kalba, nemalonu kai jį tenka sudurinėti iš dalių parašytų skirtingomis kalbomis, dar nemaloniau kai viena iš jų yra “managed”, o kita “unmanaged”.
Šį kartą aš noriu papasakoti kaip susikurti COM objektą C# kalboje, o po to jį išsikviesti iš C++ kalba parašytos programos.
Pirmiausiai kursime COM objektą. Kuriant COM objektus su C# svarbu žinoti, kad klasė ir visi metodai turi būti public, visi metodai turi būti deklaruoti interface.
Susikuriame Class Library tipo projektą pixelcom, jums nebūtina savo projekto pavadinti taip pat, tiesiog atsiminkite, jog tikslus pavadinimas ateityje bus labai svarbus.
Prieš pradedant rašyti dar reikia žinoti, kad klasėms ir interfeisams reikia GIUDs (Globally Unique Identifiers). Jie yra generuojami guidgen.exe, kuris bent jau pas mane yra C:\Program Files\Microsoft Visual Studio\Common\Tools, pas jus kur nors panašiu adresu irgi turėtų slėptis.
Pasileidę programą pasirinkite 4 variantą Registry Format.
![]()
Dabar jau galime parašyti truputį kodo:
namespace pixelcom { [Guid("4D3F96C6-20DF-4e16-B70C-DA09A50BE005")] public interface Pixel_Interface { void myMessage(string sometext); Int16 mySum(Int16 first, Int16 second); } [Guid("E69097E2-70A1-482e-8027-26C154677F58"), ClassInterface(ClassInterfaceType.None)] public class npCOM : Pixel_Interface { public npCOM() { } public void myMessage(string sometext) { MessageBox.Show(sometext); } public Int16 mySum(Int16 first, Int16 second) { return (Int16)(first+second); } } }
Kaip matote dvi iš pirmo žvilgsnio labai paprastos funkcijos, į ką reiktų atkreipti dėmesį? Pirmiausiai tai MessageBox.Show neveiks be using System.Windows.Forms, taip pat dar reiktų įsidėti using System.Runtime.InteropServices, kad kompiliatorius suprastų kas per velnias tas GUID yra. Antras dalykas - tai Int16 mySum(int first, int second) arba kitaip sakant short, kodėl ne int? Bent jau man, čia buvo cirkas su tipų suderinamumu, int16 - short, int64 - long, o nei int, nei int32 niekur nevažiuoja.
Jau turime kodą, tačiau prieš sukurdami COM objektą dar turime jį užregistruoti. Pirmiausiai pasirinkę Soliution Explorer ir ant projekto pavadinimo paspaudę dešinį pasirinkite Propertiesir uždėkite varnelę Application-> Assembly Information-> Make assembly COM-Visible ir Build-> Register for COM interop. Kad būtų sukurtas COM objektas, reikia, kad jūsų klasė turėtų strong name, kuris yra sukuriamas su SN.EXE (Pastaba: ne visos (ypač egzotiškesnės) bibliotekos turi strong name). Pas mane kompiuteryje tas failas yra pasislėpęs C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin adresu. Strong name kūrimas vykdomas tokia komanda:
sn -k pixelcom.snkAtsidarykite AssemblyInfo.cs ir kur nors įterpkite tokią eilutę:
[assembly: AssemblyKeyFile("pixelcom.snk")]
Sukompiliuokite.
Sveikinu sukūrėte COM objektą.
Dabar pereikime prie antrosios dalies, sukurtą COM objektą iškviesime iš C++ kalba pasirašytos programos.
#import <Pilnas kelias>pixelcom.tlb" named_guids raw_interfaces_onlyReikia nurodyti pilną kelią iki sukurto .tlb failo, kuris turėtų būti šalia jūsų projekto sugeneruoto DLL. (Jeigu yra tik DLL, tai .tlb failą galima susikurti REGASM pixelcom.dll /tlb:pixelcom.tlb)
CoInitialize(NULL); //Inicijuojamas COM objekto užkrovimas pixelcom::Pixel_InterfacePtr myObject; HRESULT hRes = myObject.CreateInstance(pixelcom::CLSID_npCOM); BSTR bstr; bstr = ::SysAllocString(L"Tekstas"); myObject->myMessage(bstr); short res=1; // mySum funkcijos rezultatas bus saugomas šitame kintamajame myObject->mySum(5,2,&res); CoUninitialize (); //Atšaukiamas COM objektas
Turbūt reiktų pakomentuoti kodą. Pirmiausiai inicijuomas COM objekto užkrovimas, apsirašomas mano sukurto COM objekto kintamasis namespace::interfacePtr, sukuriamas tas kintamasis kintamojo_pavadinimas.CreateInstance(namespace::CLSID_klase). BSTR - basic string, įmanoma naudoti ir kitus string tipo kintamuosius, bet tam reikia truputėlį daugiau pastangų.
Rodos, tai viskas, ką norėjau parodyti. COM technologija yra jau su gana ilga žila barzdele, todėl, matyt, kasdien su ja nesusiduriate.
2007-04-11 | 8:51
O SysFreeString kas iškvies? HRESULT’us kas patikrins? :)
2007-04-11 | 18:12
pabandysiu truputėli pataisyti kodą
rodos turėtų būti taip:
[code]
HRESULT hRes = myObject.CreateInstance(pixelcom::CLSID_npCOM);
if(hRes == S_OK)
{
BSTR bstr;
bstr = ::SysAllocString(L“Tekstas”);
myObject->myMessage(bstr);
SysFreeString(bstr);
short res=1;
myObject->mySum(5,2,&res);
}
[/code]
2007-05-01 | 14:47
[…] Sutinku, kad 99% blogosferos turėtų pasinaudoti jūsų patarimu “išsitraukti galvas iš šiknų” ir suprasti, kad rašymas apie “šiandien valgiau” yra šlamštas. Deja, negaliu sutikti, kad mes nesame antrosios interneto kartos kūrėjai. Na, ok. Pafantazuokime ir įsivaizduokime internetą be blogų. Ką matome? Forumus, kuriuose šūkauja trylikamečiai paaugliai siekdami dėmesio ir keletą portalų, kurie formuoja mūsų nuomonę apie vieną ar kitą dalyką. Internetas būtų statiškas ir nuobodus. Turbūt pusė dabartinio interneto turinio yra parašyta blogerių dėka. Jeigu ne blogai iki šiol nežinočiau kaip kuriami COM objektai, kaip išsikepti pavasarišką sumuštinuką, ar kaip užsirišti šlipsą. Jei ne Vaido blogas, nebūčiau sužinojęs ir sudalyvavęs PHP Security konferencijoje. Blogų skaitymas man yra pramoga, kurios pagalba pažįstu pasaulį, mokausi iš kitų klaidų ir sužinau vis kažką naujo. Argi tai nenuostabu? Neabejoju, kad šį mano įrašą skaitantis žmogus galėtų išvardinti bent 10-20 naujų dalykų, kuriuos jis sužinojo per pastarąją savaitę vien tik skaitydamas kitų žmonių mintis. Mes kuriame turinį, mes jį skaitome. Nebūkime perdėtai konservatyvių pažiūrų ir priimkime naujoves. […]