NePo
Balandis 11, 2007

Kuriam COM objektus

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 objektą C# kalboje, o po to jį išsikviesti iš C++ kalba parašytos programos.

Pirmiausiai kursime objektą. Kuriant 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.
npguid.jpg
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 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 -Visible ir Build-> Register for interop. Kad būtų sukurtas 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.snk

Atsidarykite AssemblyInfo.cs ir kur nors įterpkite tokią eilutę:

[assembly: AssemblyKeyFile("pixelcom.snk")]

Sukompiliuokite.
Sveikinu sukūrėte objektą.

Dabar pereikime prie antrosios dalies, sukurtą objektą iškviesime iš C++ kalba pasirašytos programos.

#import <Pilnas kelias>pixelcom.tlb" named_guids raw_interfaces_only

Reikia 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 objekto užkrovimas, apsirašomas mano sukurto 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. technologija yra jau su gana ilga žila barzdele, todėl, matyt, kasdien su ja nesusiduriate.

Panašūs straipsniai


“Kuriam COM objektus” komentarų: 3

  1. Aras Pranckevičius

    O SysFreeString kas iškvies? HRESULT’us kas patikrins? :)

  2. NePo

    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]

  3. Slave 2.0 » Blog Archive » Ar blogeriai - avigalviai?

    […] 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. […]

Rašyti komentarą

Jūs privalote prisijungti jeigu norite rašyti komentarą.