1. RE: wrapping DX

-----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

new topic     » topic index » view message » categorize

2. RE: wrapping DX

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

new topic     » goto parent     » topic index » view message » categorize

3. RE: wrapping DX

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

new topic     » goto parent     » topic index » view message » categorize

4. RE: wrapping DX

> -----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

new topic     » goto parent     » topic index » view message » categorize

5. RE: wrapping DX

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

new topic     » goto parent     » topic index » view message » categorize

6. RE: wrapping DX

>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
>

new topic     » goto parent     » topic index » view message » categorize

7. RE: wrapping DX

> -----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

new topic     » goto parent     » topic index » view message » categorize

8. RE: wrapping DX

> -----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

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu