From: Matthew Mastracci Newsgroups: comp.os.msdos.djgpp Subject: Source to COM implementation in DJGPP Date: Mon, 8 Sep 1997 20:01:45 -0600 Organization: The University of Calgary Lines: 250 Message-ID: <5v2anv$f7g@ds2.acs.ucalgary.ca> NNTP-Posting-Host: mmastrac AT acs2 DOT acs DOT ucalgary DOT ca Mime-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII To: djgpp AT delorie DOT com DJ-Gateway: from newsgroup comp.os.msdos.djgpp Precedence: bulk I've been working on a COM port for DJGPP for the last little while and I've managed to implement the more important stuff from MSVC's implementation here. For those who don't know, COM is a way to polymorphically handle object by way of interfaces. It takes advantage of the vfptr table which is a C++ standard. I don't know how fast DJGPP's vfptr table is compared to MSVC's. I know that MSVC will literally compile the vfptr table into a series of jmp's. DJGPP seems to use lookups. If anyone knows anything about speed effects of this, please let me know. I'd like to know if anyone is interested in this. If not, it'll probably be a big waste of time for me ;). It would be great for things like graphics/sound packages, because you could just define some interfaces such as: interface ISoundDevice : virtual public IUnknown { void Initialize(); void PlaySound(void * Buffer, int Size, int Channel); void StopSound(int Channel); String& GetName(); } or interface IGraphicsDevice : virtual public IUnknown { void StartGraphics(int Width, int Height, int Color); void PutPixel(int x, int y, int Color); void EndGraphics(); String& GetName(); } ... etc ... Eventually, you can just drop those into .DXE files and use them as "plug-and-play" drivers. With functions like "GetName()", you can even get the driver names from files you've never seen. Now, the stuff I've mananaged to implement is: - IID structures/comparison - QueryInterface/helper macros - A working demo I don't, however, have this stuff done (it's in the works): - AddRef/Release - Various other things required - Support for .DXE's like .DLL's Stuff that's different from MSVC COM (if you've used it): - Interfaces must derive from IUnknown as virtual public, instead of public. Therefore: interface IX : IUnknown becomes interface IX : virtual public IUnknown This is to solve the ambiguous base class problem that I have when trying to get IUnknown from any object supporting two interfaces. For those who are interested, here's the source to the demo/COM "library". If anyone has any suggestions/comments/etc, please feel free to send them my way. None of the COM stuff has been moved to a .h file, but this compiles from the command-line: gcc -o com.exe com.cpp -Wall You'll see some odd warnings, but they don't affect the compiled .EXE: --- begin snip --- #include #define interface struct #define PURE = 0 #define UINT32 unsigned long #define UINT16 unsigned short #define UINT8 unsigned char #define HRESULT long #define SUCCEEDED(hr) (hr >= 0) #define FAILED(hr) (hr < 0) #define S_OK 0x0000000 #define S_ERROR 0xFFFFFFF #define E_NO_INTERFACE 0x8000000 #define COM_QUERYINTERFACE_ENTRY(x, y) \ if (iid == x) \ *ppv = ((y *)(this)); struct IID { UINT32 Data1; UINT16 Data2; UINT16 Data3; UINT8 Data4[8]; }; IID IID_IUnknown = { 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; IID IID_IX = { 0x00000001, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; IID IID_IY = { 0x00000002, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; bool operator ==(IID& iid1, IID& iid2) { return (iid1.Data1 == iid2.Data1 && iid1.Data2 == iid2.Data2 && iid1.Data3 == iid2.Data3 && iid1.Data4 == iid2.Data4); } interface IUnknown { virtual HRESULT QueryInterface(IID& iid, void ** ppv) = 0; virtual long AddRef() = 0; virtual long Release() = 0; }; interface IX : virtual IUnknown { virtual void fx1() = 0; virtual void fx2() = 0; }; interface IY : virtual IUnknown { virtual void fyA() = 0; virtual void fyB() = 0; }; class CA : public IX, public IY { public: virtual HRESULT QueryInterface(IID& iid, void ** ppv); virtual long AddRef() { } virtual long Release() { } virtual void fx1() { cout << "CA's fx1()" << endl; } virtual void fx2() { cout << "CA's fx2()" << endl; } virtual void fyA() { cout << "CA's fyA()" << endl; } virtual void fyB() { cout << "CA's fyB()" << endl; } }; class CB : public IX, public IY { public: virtual HRESULT QueryInterface(IID& iid, void ** ppv); virtual long AddRef() { } virtual long Release() { } virtual void fx1() { cout << "CB's fx1()" << endl; } virtual void fx2() { cout << "CB's fx2()" << endl; } virtual void fyA() { cout << "CB's fyA()" << endl; } virtual void fyB() { cout << "CB's fyB()" << endl; } }; HRESULT CA::QueryInterface(IID& iid, void ** ppv) { *ppv = NULL; COM_QUERYINTERFACE_ENTRY(IID_IUnknown, IUnknown); COM_QUERYINTERFACE_ENTRY(IID_IX, IX); COM_QUERYINTERFACE_ENTRY(IID_IY, IY); return (*ppv != NULL ? S_OK : E_NO_INTERFACE); } HRESULT CB::QueryInterface(IID& iid, void ** ppv) { *ppv = NULL; COM_QUERYINTERFACE_ENTRY(IID_IUnknown, IUnknown); COM_QUERYINTERFACE_ENTRY(IID_IX, IX); COM_QUERYINTERFACE_ENTRY(IID_IY, IY); return (*ppv != NULL ? S_OK : E_NO_INTERFACE); } int main(void) { CA * pA = new CA; CB * pB = new CB; IX * pX; IY * pY; IUnknown * pUnknown; pA->QueryInterface(IID_IUnknown, (void**)&pUnknown); if (SUCCEEDED(pUnknown->QueryInterface(IID_IX, (void**)&pX))) { pX->fx1(); if (SUCCEEDED(pX->QueryInterface(IID_IY, (void**)&pY))) { pY->fyA(); IUnknown * pYUnknown; if (SUCCEEDED(pY->QueryInterface(IID_IUnknown, (void**)&pYUnknown))) { if (pYUnknown == pUnknown) { cout << "IUnknown was properly returned from IY." << endl; } else { cout << "IUnknown from IY is different from IUnknown from class!" << endl; } } else { cout << "Couldn't get IUnknown from IY!" << endl; } } else { cout << "Couldn't get IY from IX!" << endl; } } else { cout << "Couldn't get IX from IUnknown" << endl; } delete pB; delete pA; return 0; } --- end snip --- /\/\att /\/\astracci mmastrac AT acs DOT ucalgary DOT ca GCS/GE d- s+:+ a--- C++++ UA P+ L E-- W+ N++ o K+ w+ O M- V PS++ PE++ Y+ PGP t+++ 5+++ X++ R++ tv+ b+++ DI++++ I G++ e h r* z?