PDA

View Full Version : COM Interface behind the scenes.



Colin
28-09-2011, 03:29 PM
Hi there, i'm looking for information on COM interfaces, i want to extend my programming language to support COM interfaces so i can write a few directx applications with it, but first need good documentation or explanation on what is going on behind the scenes.

e.g. where is the GUID passed to and when?, what is returned from GetDevice, is it a table with a list of pointers to the class functions or?

Hope someone can help, thanks in advance.

code_glitch
30-09-2011, 03:44 PM
COM as in Communications? GUID rings bell, but in the GPT partition scheme for hard disks area...

JSoftware
30-09-2011, 04:55 PM
This page is quite good at explaining it: http://en.wikipedia.org/wiki/Component_Object_Model#Technical_details

You are right, that you get a pointer to a virtual function table. It's basically a large list of functions that come in the order they are defined in the type definition

To call AddRef on a COM interface in eax do something like this:


push eax // Reference to self
mov eax, [eax] // Get the function list
call [eax+4] // Second function (AddRef)


To call Begin_QueryInterface(SomeGuid) in AsyncIUnknown(inheriting directly from IUnknown, which has 3 functions):


push SomeGuid // Reference to GUID
push eax // Reference to self
mov eax, [eax] // Get the function list
call [eax+3*4] // First function in AsyncIUnknown (AddRef)


GUIDs aren't really used with DirectX as far as I know, since you create all interfaces through the device

More reading: http://www.polberger.se/components/read/com-technical-foundation.html

Colin
30-09-2011, 05:38 PM
excellent, thanks JSoftware, your snippets were all i needed to understand what i need to implement the basics into Ziron, Thanks again.

Colin
07-10-2011, 01:37 PM
just wanted to reply to say thanks again for the info, i started yesterday and finished yesterday, well it only took an hour or so to implement plus write a test app, with a little bug fixing with my assembler, but now it works great and simple :)



IDirect3DDevice9 dx_device;
IDirect3D9 dx_object = Direct3DCreate9(D3D_SDK_VERSION);

edi = dx_object;
eax = edi.CreateDevice(0, D3DDEVTYPE_HAL, hMainFRM, 64, @presParams, @dx_device);

edi = dx_device;
// Set up message loop
while (eax <> WM_QUIT) {
//etc


i wrote a small test app that creates window, inits dx and just changes colour etc of window, only 3kb :)



program WIN32GUI 'DX9Sample';

#include 'user32.zir';
#include 'kernel32.zir';
#include 'messages.zir';
#include 'colors.zir';

#include 'directx/direct3d9.zir';

//////////////////////////////

//directx globals
D3DPRESENT_PARAMETERS presParams;
/////////

//other variables
tagWndClassA wndClass;
tagMsg msg;
DWord hInstance = GetModuleHandleA(nil);
//

//handles
DWord hMainFRM;
//

//////////////////////////////


function WindowProc(DWord hWnd; DWord uMsg; DWord wParam; DWord lParam) {
if (uMsg == WM_COMMAND) {
eax = DefWindowProcA(hWnd, uMsg, wParam, lParam);
ret
} elseif (uMsg == WM_DESTROY) {
PostQuitMessage(0);
} else {
eax = DefWindowProcA(hWnd, uMsg, wParam, lParam);
}
}


const className = 'ZMainFRM';


wndClass.hbrBackground = COLOR_BACKGROUND;
wndClass.hInstance = hInstance;
wndClass.lpszClassName = className;
wndClass.lpfnWndProc = @WindowProc;

RegisterClassA(@wndClass);
hMainFRM = CreateWindowExA(0, className, 'Ziron DirectX9 Demo', WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 1024, 768, 0, 0, hInstance, nil);
ShowWindow(hMainFRM, SW_SHOWNORMAL);

presParams.hDeviceWindow = hMainFRM;
presParams.Windowed = True;
presParams.BackBufferWidth = 1024;
presParams.BackBufferHeight = 768;
presParams.BackBufferCount = 1;
presParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
presParams.AutoDepthStencilFormat = D3DFMT_D24X8;
presParams.EnableAutoDepthStencil = True;

IDirect3DDevice9 dx_device;
IDirect3D9 dx_object = Direct3DCreate9(D3D_SDK_VERSION);

edi = dx_object;
eax = edi.CreateDevice(0, D3DDEVTYPE_HAL, hMainFRM, 64, @presParams, @dx_device);

//edi as nothing;

edi = dx_device;
push esi;
esi = 0xFF000000;

// Set up message loop
while (eax <> WM_QUIT) {
edi.clear(0, nil, 3, esi, 1.0, 0);
edi.BeginScene;
//

//render something here :)

//
edi.EndScene;
edi.Present(nil, nil, 0, nil);

add esi, 0x512

eax = PeekMessage(@msg, 0, 0, 0, 1);
if (eax) {
TranslateMessage(@msg);
DispatchMessageA(@msg);

eax = msg.message;
}
}

edi as nothing;
pop esi

ExitProcess(0);