News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Calling a function ptr from a struct

Started by Matthew, May 02, 2012, 10:21:19 AM

Previous topic - Next topic

Matthew


SceneUpdateFunctionPtr TYPEDEF PROTO
SceneRenderFunctionPtr TYPEDEF PROTO

LPSCENEUPDATE TYPEDEF PTR SceneUpdateFunctionPtr
LPSCENERENDER TYPEDEF PTR SceneRenderFunctionPtr

Scene struct
Update LPSCENEUPDATE ?
Render LPSCENERENDER ?
Scene ends

LPSCENE TYPEDEF PTR Scene

.data
myscene Scene <offset Update, offset Render>
.code
Update proc
    ret
Update endp

Render proc
    ret
Render endp

main proc
    invoke myfunction, addr myscene
   
 

    ret
main endp

myfunction proc lpCurrentScene:LPSCENE
    ; I want to call lpCurrentScene->Update(), then call lpCurrentScene->Render()

    mov eax, lpCurrentScene
    assume eax:LPSCENE
    call [eax].Update
    assume eax:nothing

    mov eax, lpCurrentScene
    assume eax:LPSCENE
    call [eax].Render
    assume eax:nothing

    ret
myfunction endp


Is this the best way to call the function pointers stored in the struct?
Is there a way of calling those functions without assume eax:LPSCENE ?

I have tryed a few other ways, but was greeted with access violations  :red

fearless

movzx eax, dword ptr [lpCurrentScene.Scene.Update]
call eax


if calls to update or render need (or will need in future) any params, you can push them before the call eax

Not sure if the above code will work, as im not sure how the typedefs will resolve each other (as dwords in your scene struct? Update -> typedef ptr SceneUpdateFunctionPtr -> TYPEDEF PROTO ?)
ƒearless

Matthew

movzx eax, dword ptr [lpCurrentScene.Scene.Update]

movzx doesnt work because, of invalid instruction operand.

I think this is because movzx expects the value to be less than 32 bits if im using eax register, so it can zero pad it.
So I changed the instruction to mov and then i get access violation.

I also wonder if there is a way to use invoke with this, so i get the type validation checks in the case I need to pass parameters in the future.

fearless

if i was doing something similar id probably structure it like this:

myfunction PROTO :DWORD
Update PROTO
Render PROTO
main PROTO

SCENE struct
    Update DD 0
    Render DD 0
SCENE ends

.data
myscene SCENE <offset Update, offset Render>

Update proc
    ret
Update endp

Render proc
    ret
Render endp

main proc
    invoke myfunction, addr myscene
    ret
main endp

myfunction proc lpCurrentScene:DWORD
    movzx eax, dword ptr [lpCurrentScene.SCENE.Update]
    call eax
    movzx eax, dword ptr [lpCurrentScene.SCENE.Render]
    call eax
    ret
myfunction endp


Not sure it that is what your looking for, or if future development means the above code might need adjusting still to account for other features, parameters etc etc
ƒearless

Matthew

Your answer gave me an idea, and this seems to work...


mov eax, lpCurrentScene
call dword ptr [eax].Scene.Update

mov eax, lpCurrentScene
call dword ptr [eax].Scene.Render


Is a way to allow invoke to work with this?


Matthew

Figured it out...


mov eax, lpCurrentScene
invoke LPSCENEUPDATE PTR [eax].Scene.Update

mov eax, lpCurrentScene
invoke LPSCENERENDER PTR [eax].Scene.Render


Thanks for your help, I got there in the end  :dance:

fearless

No problem, glad it all worked out :D
ƒearless

dedndave

nice work guys   :U

i can see where there might be some other uses for this   :bg

Vortex

Hi Matthew,

A macro like the following can do the job for you :


coinvoke MACRO ppv:REQ,interface:REQ,member:REQ,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,p16

    FOR arg,<p16,p15,p14,p13,p12,p11,p10,p9,p8,p7,p6,p5,p4,p3,p2,p1>

        IFNB <arg>

            push arg

        ENDIF

    ENDM

    mov     eax,ppv
    push    eax
    mov     eax,DWORD PTR [eax]
    call    @CatStr(interface,<.>,member)[eax]

ENDM


coinvoke pShell,IShellDispatch,ShutdownWindows