1. RE: wrapping DX
- Posted by Matthew Lewis <matthewwalkerlewis at YAHOO.COM> May 24, 2001
- 454 views
-----Original Message----- From: martin.stachon at worldonline.cz [mailto:martin.stachon at worldonline.cz] > Now, when we've got EuCOM, is anyone going to wrap DirectX ? I just got my hands on DX8, and did a quick wrapper of a couple of interfaces (should be enough to do a simple demo). I think EuCOM is about ready for another release. Just a few more things to do, and then update the docs. Matt Lewis
2. RE: wrapping DX
- Posted by Matthew Lewis <matthewwalkerlewis at YAHOO.COM> May 29, 2001
- 429 views
I've run into something very strange in DirectX. I'm basically converting the C++ Tutorial on MSDN into Euphoria. I'm having trouble with the IDirect3DVertexBuffer8 interface. Everything else seems to work fine, but I can't get any calls to this interface to work in Euphoria. I've written a DLL in VC++ that will make the calls fine, but I get error R6025: Pure Virtual Function Call if I try to call QueryInterface. Any other call simply returns the 'this' pointer, and if any args are passed, the program crashes, because the stack pointer gets messed up since the called function didn't clean anything up. Here's a quick rundown of my DirectX calls (with everything else deleted): -- Get the Direct3D8 object direct3d8 = c_func( d3dc, {D3D_SDK_VERSION} ) -- Get Adapter info void = call_interface_ptr( direct3d8, d_vtbl, Direct3D8_GetAdapterDisplayMode, { D3DADAPTER_DEFAULT, d3dadapter } ) -- Create the device, and get pointer to Direct3DDevice8: void = call_interface_ptr( direct3d8, d_vtbl, Direct3D8_CreateDevice, {0, 2, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, d3dpp, ppv }) -- Create the vertex buffer, and get pointer to Direct3DVertexBuffer8: void = call_interface_ptr( device, device_vtbl, Direct3DDevice8_CreateVertexBuffer, { 3 * sizeof_CUSTVERT, 0, CUSTVERT_flags, 1, ppv } ) For some reason, when I get the 'this' pointer, and the address of the vtbl, and call methods (which is exactly how I've done it with other interfaces), it doesn't work, unless I do it in VC: -- Euphoria (doesn't work): void = call_interface_ptr( vb, vb_vtbl, Direct3DVertexBuffer8_Lock, { 0, 3 * sizeof_CUSTVERT, pVertices, 0 } ) // C++ (works): extern "C" _declspec(dllexport) long __stdcall Lock( LPDIRECT3DVERTEXBUFFER8 pf, int a, int b, BYTE** c, int d) { return pf->Lock(a, b, c, d); }; I've also tried to call from C++ using an actual function pointer, the same way I do in Eu, but that fails. The only way seems to be to declare a 'proper' C++ interface object, and call the members. But only on this one interface. Any ideas? Matt Lewis > -----Original Message----- > From: martin.stachon at worldonline.cz > Please, post an URL when you will have somthing done. > > Martin
3. RE: wrapping DX
- Posted by Bernie Ryan <xotron at localnet.com> May 29, 2001
- 431 views
Matthew Lewis wrote: > > I've run into something very strange in DirectX. I'm basically > converting > the C++ Tutorial on MSDN into Euphoria. I'm having trouble with the Martin Although I don't understand your code. Here are some possible reasons for your code not working. 1. Non-virtual functions do not appear in the vtable. 2. Stack order is not correct going from C++ to Euphoria ( try reversing the parameter list ). 3. Euphoria interfaces with "C" and C++ maybe mangling the names ( inside your DLL ). 4. A Structure is not formed properly. 5. Trying to pass a structure by value. Bernie
4. RE: wrapping DX
- Posted by Matthew Lewis <matthewwalkerlewis at YAHOO.COM> May 29, 2001
- 458 views
> -----Original Message----- > From: Bernie Ryan [mailto:xotron at localnet.com] > Although I don't understand your code. > Here are some possible reasons for your code not working. > > 1. Non-virtual functions do not appear in the vtable. No, all COM interface member functions are virtual, so I don't think this would have any bearing. > 2. Stack order is not correct going from C++ to Euphoria ( > try reversing the parameter list ). Nope. Already reversed. The functions aren't even seeing the parameter list. > 3. Euphoria interfaces with "C" and C++ maybe mangling the names ( > inside your DLL ). No, I don't look for names at all. Basically, I'm handed the address to a pointer to a C++ object (the 'this' pointer for the object). The pointer contains the address of the vtable. I'm supposed to be able to use those two pieces of information to call any function in the interface (look up the address of the function, and pass the 'this' pointer as the first argument) just as if I were calling from C++. Every other interface I've encountered thus far works that way. But this one seems to know if I'm calling from C++ or not--of course, this contradicts MS's own COM specifications <insert MS joke here>. I suppose I'll have to dissassemble the darn thing to figure out what it's doing differently... > 4. A Structure is not formed properly. > 5. Trying to pass a structure by value. Thanks, Matt Lewis
5. RE: wrapping DX
- Posted by Matthew Lewis <matthewwalkerlewis at YAHOO.COM> May 29, 2001
- 442 views
Maybe some asm guru can explain why these two approaches might give different results. First, here's the code from VC++: g_pVB->Lock( 0, sizeof(g_Vertices), (BYTE**)&pVertices, 0 ) 004011AE 6A 00 push 0 004011B0 8D 45 F8 lea eax,[pVertices] 004011B3 50 push eax 004011B4 6A 3C push 3Ch 004011B6 6A 00 push 0 004011B8 8B 0D D0 79 41 00 mov ecx,dword ptr [g_pVB (004179d0)] 004011BE 8B 11 mov edx,dword ptr [ecx] 004011C0 A1 D0 79 41 00 mov eax,[g_pVB (004179d0)] 004011C5 50 push eax 004011C6 FF 52 2C call dword ptr [edx+2Ch] The arguments are pushed onto the stack in reverse order, the last being g_pVB (the 'this' pointer for the vertex buffer), which also ends up in eax when the function is called (in this case--other calls use the registers differently for some reason). Next, is the code I use in fptr.e. It's more of a generic routine, designed to call any stdcall routine. Before it's called, the number of args is poked into paramcount, the address of the param list is put into memory starting at the value put into params, the pointer to the function is poked into memory at [comfunc] and the address where the return value will be stored is put into retpointer. This routine pushes the arguments being passed onto the stack (instructions #1..#12), calls the function by pointer (#14), stores the return value (#1A) and then returns to Euphoria (#21). #60, -- 0: pusha #BB,#00,#00,#00,#00, -- 1: mov ebx, paramcount (2) #B9,#00,#00,#00,#00, -- 6: mov ecx, params (7) -- B: start: #8B,#01, -- B: mov eax, [ecx] #50, -- D: push eax #83,#C1,#04, -- E: add ecx, 4 #4B, -- 11: dec ebx #75,#F7, -- 12: jnz start #FF,#15,#00,#00,#00,#00,-- 14: call dword ptr [comfunc] (22) #A3,#00,#00,#00,#00,-- 1A: mov [retpointer], eax (27) #61, -- 20: popa #C3}, -- 21: ret The above ASM has worked flawlessly on numerous other calls (including to Eu call_back's) until I ran across the vertex buffer. I've compared the function pointers when called from VC and from Eu, and they're the same. For some reason, though, something is getting messed up along the way when Eu calls anything. Matt Lewis
6. RE: wrapping DX
- Posted by stabmaster_ at HOTMAIL.COM May 30, 2001
- 438 views
>004011B8 8B 0D D0 79 41 00 mov ecx,dword ptr [g_pVB (004179d0)] >004011BE 8B 11 mov edx,dword ptr [ecx] >004011C0 A1 D0 79 41 00 mov eax,[g_pVB (004179d0)] >004011C5 50 push eax >004011C6 FF 52 2C call dword ptr [edx+2Ch] > I assume you have checked that comfunc equals peek4u(g_pVB)+#2C (or something like that). The last PUSH is interesting. I don't really understand where this parameter is aimed, but your code (below) doesn't seem to perform the extra push. Perhaps this param has something to do with Lock() being a virtual function..? C++ isn't really my strong side so I wouldn't know. >#60, -- 0: pusha >#BB,#00,#00,#00,#00, -- 1: mov ebx, paramcount (2) >#B9,#00,#00,#00,#00, -- 6: mov ecx, params (7) > -- B: start: >#8B,#01, -- B: mov eax, [ecx] >#50, -- D: push eax >#83,#C1,#04, -- E: add ecx, 4 >#4B, -- 11: dec ebx >#75,#F7, -- 12: jnz start >#FF,#15,#00,#00,#00,#00,-- 14: call dword ptr [comfunc] (22) >#A3,#00,#00,#00,#00,-- 1A: mov [retpointer], eax (27) >#61, -- 20: popa >#C3}, -- 21: ret >
7. RE: wrapping DX
- Posted by Matthew Lewis <matthewwalkerlewis at YAHOO.COM> May 30, 2001
- 436 views
> -----Original Message----- > From: stabmaster_ at HOTMAIL.COM [mailto:stabmaster_ at HOTMAIL.COM] > > >004011B8 8B 0D D0 79 41 00 mov ecx,dword ptr > [g_pVB (004179d0)] > >004011BE 8B 11 mov edx,dword ptr [ecx] > >004011C0 A1 D0 79 41 00 mov eax,[g_pVB (004179d0)] > >004011C5 50 push eax > >004011C6 FF 52 2C call dword ptr [edx+2Ch] > > > > I assume you have checked that comfunc equals peek4u(g_pVB)+#2C (or > something like that). > The last PUSH is interesting. I don't really understand where > this parameter > is aimed, but your code (below) doesn't seem to perform the > extra push. > Perhaps this param has something to do with Lock() being a virtual > function..? C++ isn't really my strong side so I wouldn't know. The last push is the 'this' pointer. I've already added that to the arg list, so it's pushed with the other args. It's just so bizarre, because it works fine with everything but this one interface... Thanks, Matt Lewis
8. RE: wrapping DX
- Posted by Matthew Lewis <matthewwalkerlewis at YAHOO.COM> May 31, 2001
- 476 views
> -----Original Message----- > From: martin.stachon at worldonline.cz > > Please, post an URL when you will have somthing done. OK, I've sent my demo to Rob, and it's also up at http://www14.brinkster.com/matthewlewis/projects.html You'll need DirectX 8.0 (about 11MB d/l from MS). Also, I got around using a dll to call certain features by using a user supplied vertex buffer. The demo is very simple (it's basically a modified version of the tutorial on MSDN). It's a three colored triangle that spins around in a window. If you've never used DirectX, you'll definitely want to familiarize yourself with the docs on MSDN (or download them from MS if you've got a good connection). It's definitely far from simple. DX itself should probably be wrapped by someone. :) Matt Lewis