Jump to content

dllstruct member accessible via struct fields in dll?


Recommended Posts

I am completely stucked with a wrapper function for a .dll (I swear I read the au3 help over and over, searched the forum, so maybe somebody can tell me if I am to blind or if this is not possible at all?):

I want to pass data to a C-function which takes it as a struct ("prop"), then access it via the struct field names (e.g. "prop.direction_x"):

IParticleEmitter * DLL_EXPORT IrrAddParticleEmitter( IParticleSystemSceneNode* ps, IRR_PARTICLE_EMITTER prop )
{   IParticleEmitter* em = ps->createBoxEmitter(
        core::aabbox3d<f32>(prop.min_box_x,prop.min_box_y,prop.min_box_z,prop.max_box_x,prop.max_box_y,prop.max_box_z),
        core::vector3df(prop.direction_x,prop.direction_y,prop.direction_z),
        prop.min_paritlcles_per_second,prop.max_paritlcles_per_second,
        ...

So I pass a dllstruct for the "prop" to this function:

$struct = "float min_box_x;float min_box_y;float min_box_z;float max_box_x;float max_box_y;float max_box_z;" & _
                            "float direction_x;float direction_y;float direction_z;uint min_paritlcles_per_second;uint max_paritlcles_per_second;" & _
                            "int min_start_color_red;int min_start_color_green;int min_start_color_blue;" & _
                            "int max_start_color_red;int max_start_color_green;int max_start_color_blue;" & _
                            "uint min_lifetime;uint max_lifetime;" & _
                            "float min_start_sizeX;float min_start_sizeY;float max_start_sizeX;float max_start_sizeY;int max_angle_degrees"
 $EmitterStruct = DllStructCreate($struct)
    DllStructSetData($EmitterStruct, "min_box_x", $f_MinBoxX)
    DllStructSetData($EmitterStruct, "min_box_y", $f_MinBoxY)
    DllStructSetData($EmitterStruct, "min_box_z", $f_MinBoxZ)
    DllStructSetData($EmitterStruct, "max_box_x", $f_MaxBoxX)
    DllStructSetData($EmitterStruct, "max_box_y", $f_MaxBoxY)
    DllStructSetData($EmitterStruct, "max_box_z", $f_MaxBoxZ)
    DllStructSetData($EmitterStruct, "direction_x", $f_DirectionX)
    DllStructSetData($EmitterStruct, "direction_y", $f_DirectionY)
    DllStructSetData($EmitterStruct, "direction_z", $f_DirectionZ)
    DllStructSetData($EmitterStruct, "min_paritlcles_per_second", $i_MinParticlesPerSecond)
    DllStructSetData($EmitterStruct, "max_paritlcles_per_second", $i_MaxParticlesPerSecond)
    DllStructSetData($EmitterStruct, "min_start_color_red", $i_MinStartRed)
    DllStructSetData($EmitterStruct, "min_start_color_green", $i_MinStartGreen)
    DllStructSetData($EmitterStruct, "min_start_color_blue", $i_MinStartBlue)
    DllStructSetData($EmitterStruct, "max_start_color_red", $i_MaxStartRed)
    DllStructSetData($EmitterStruct, "max_start_color_green", $i_MaxStartGreen)
    DllStructSetData($EmitterStruct, "max_start_color_blue", $i_MaxStartBlue)
    DllStructSetData($EmitterStruct, "min_lifetime", $i_MinLifetime)
    DllStructSetData($EmitterStruct, "max_lifetime", $i_MaxLifetime)
    DllStructSetData($EmitterStruct, "max_angle_degrees", $i_MaxAngle)
    DllStructSetData($EmitterStruct, "min_start_sizeX", $f_MinStartSizeX)
    DllStructSetData($EmitterStruct, "min_start_sizeY", $f_MinStartSizeY)
    DllStructSetData($EmitterStruct, "max_start_sizeX", $f_MaxStartSizeX)
    DllStructSetData($EmitterStruct, "max_start_sizeY", $f_MaxStartSizeY)

$result = DllCall($_irrDll, "ptr:cdecl", "IrrAddParticleEmitter", "ptr", $h_ParticleSystem, "ptr", $EmitterStruct)

The struct itself looks absolutely ok for me, but it seems the dll-function cannot read the passed data.

Is this because of the accessing way of the C-function, or have I simply missed something?

Thanks in advance ...

Link to comment
Share on other sites

Nice short answer - but I still cannot see a light :blink:

If you mean:

$result = DllCall($_irrDll, "ptr:cdecl", "IrrAddParticleEmitter", "ptr", $h_ParticleSystem, [b]"ptr", dllstructgetptr($EmitterStruct)[/b])

Was one of the things I tried this night without success ...

Link to comment
Share on other sites

Try something like this:

$aCall = DllCall($_irrDll, "ptr:cdecl", "IrrAddParticleEmitter", "ptr*", 0, "ptr", DllStructGetPtr($EmitterStruct))
;...here you check errors and then...
$hPossiblyWhatYouWant = $aCall[1]

Or depending what $h_ParticleSystem is (but you say you already tried):

$aCall = DllCall($_irrDll, "ptr:cdecl", "IrrAddParticleEmitter", "handle", $h_ParticleSystem, "ptr", DllStructGetPtr($EmitterStruct))

Or:

$aCall = DllCall($_irrDll, "ptr:cdecl", "IrrAddParticleEmitter", "ptr*", $h_ParticleSystem, "ptr", DllStructGetPtr($EmitterStruct))
Edited by trancexx

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

... think you mean

$result = DllCall($_irrDll, "ptr:cdecl", "IrrAddParticleEmitter", "ptr", $h_ParticleSystem, "ptr*", DllStructGetPtr($EmitterStruct))

instead of ..., "ptr*", 0, ...

but also creating a runtime error after some time. Rest of script should be without problems, so I bet on the struct parameter ...

Do you know if a dll can read the dllstruct via "structName.Membername" as quoted in my first post?

Or:

Not really - $h_ParticleSystem is already a pointer. Other functions in script use it the same way (but without a dllstruct) without crash. Commenting out the evil "IrrAddParticleEmitter" (then a default emitter is used) works fine ... Edited by linus
Link to comment
Share on other sites

Do you know if a dll can read the dllstruct via "structName.Membername" as quoted in my first post?

Structure is just a memory space (filled or not) that you provide/make.

Accessing structure is other name for reading (binary) data at specific address.

Dot operator in c(++) is used to access data members.

Three sentences from the above make your question sound weird actually.

Edited by trancexx

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

... make your question sound weird actually.

I know I know ... But after anatomising && surrounding the problem it's beginning to run out of my logic ... - also I agree to all of your three sentences :blink: Time to take a step back and rethink it tomorrow. Hope it's none of those strange side effect things ...

Nevertheless, thanks!

Link to comment
Share on other sites

  • 2 months later...

Just to make my own "weird" question more clear - and maybe save others from running into the complete wrong direction:

If having a dll function like

IParticleEmitter * DLL_EXPORT IrrAddParticleEmitter( IParticleSystemSceneNode* ps, IRR_PARTICLE_EMITTER prop )

where IRR_PARTICLE_EMITTER is a struct, then using a pointer seems not really to be a solution, because function is expecting the struct BY VALUE, not by reference.

Finally I got it working by passing simply every struct member as sequence:

DllCall($_irrDll, "ptr:cdecl", "IrrAddParticleEmitter", "UINT_PTR", $particleSystem, _
                "float", -7, "float", 0, "float", -7, "float", 7, "float", 1, "float", 7, "float", 0, "float", 0.04, "float", 0, _
        "UINT", 80, "UINT", 100, "int", 255, "int", 255, "int", 255, "int", 255, "int", 255, "int", 255, "UINT", 800, "UINT", 2000, _
        "float", 15, "float", 15, "float", 15, "float", 15, "int", 15)
Link to comment
Share on other sites

Yes, sometimes it is not understandable how the parameters should be "transfered into the function".

In this case (something is going wrong with the dll-call) i always start a debugger/disassembler and....have a look how the function is called and which parameters are expected:

.text:1002B990                 public IrrAddParticleEmitter
.text:1002B990 IrrAddParticleEmitter proc near
.text:1002B990
.text:1002B990 var_5C          = dword ptr -5Ch
.text:1002B990 var_58          = dword ptr -58h
.text:1002B990 var_54          = dword ptr -54h
.text:1002B990 var_44          = dword ptr -44h
.text:1002B990 var_40          = dword ptr -40h
.text:1002B990 var_3C          = dword ptr -3Ch
.text:1002B990 var_38          = dword ptr -38h
.text:1002B990 var_34          = dword ptr -34h
.text:1002B990 var_30          = dword ptr -30h
.text:1002B990 var_24          = dword ptr -24h
.text:1002B990 var_20          = dword ptr -20h
.text:1002B990 var_1C          = dword ptr -1Ch
.text:1002B990 var_18          = dword ptr -18h
.text:1002B990 var_14          = dword ptr -14h
.text:1002B990 var_10          = dword ptr -10h
.text:1002B990 var_C           = dword ptr -0Ch
.text:1002B990 var_8           = dword ptr -8
.text:1002B990 var_4           = dword ptr -4
.text:1002B990 arg_0           = dword ptr  4
.text:1002B990 arg_4           = dword ptr  8
.text:1002B990 arg_8           = dword ptr  0Ch
.text:1002B990 arg_C           = dword ptr  10h
.text:1002B990 arg_10          = dword ptr  14h
.text:1002B990 arg_14          = dword ptr  18h
.text:1002B990 arg_18          = dword ptr  1Ch
.text:1002B990 arg_1C          = dword ptr  20h
.text:1002B990 arg_20          = dword ptr  24h
.text:1002B990 arg_24          = dword ptr  28h
.text:1002B990 arg_28          = dword ptr  2Ch
.text:1002B990 arg_2C          = dword ptr  30h
.text:1002B990 arg_30          = byte ptr  34h
.text:1002B990 arg_34          = byte ptr  38h
.text:1002B990 arg_38          = dword ptr  3Ch
.text:1002B990 arg_3C          = byte ptr  40h
.text:1002B990 arg_40          = byte ptr  44h
.text:1002B990 arg_44          = dword ptr  48h
.text:1002B990 arg_48          = dword ptr  4Ch
.text:1002B990 arg_4C          = dword ptr  50h
.text:1002B990 arg_60          = dword ptr  64h
.text:1002B990
.text:1002B990                 sub     esp, 44h
.text:1002B993                 mov     ecx, [esp+44h+arg_44]
.text:1002B99A                 xor     eax, eax
.text:1002B99C                 mov     ah, [esp+44h+arg_3C]
there are some more arguments expected on the stack than only a pointer to a struct  ;)...
Link to comment
Share on other sites

this dllstruct thing is definetly good to make a non-C(pp)-pro's head smoking ;) But can I assume that I have really fixed my problem or do you mean the way I did is not the real one (means: one of those maybe-maybe-not solutions)?

Link to comment
Share on other sites

this dllstruct thing is definetly good to make a non-C(pp)-pro's head smoking ;) But can I assume that I have really fixed my problem or do you mean the way I did is not the real one (means: one of those maybe-maybe-not solutions)?

looks like you've got it, I think andyg was offering advice for helping to solve the ByRef, ByVal decision when calling a dll
Link to comment
Share on other sites

... I think andyg was offering advice for helping to solve the ByRef, ByVal decision when calling a dll

... and it's a really good advice - think getting those infos via debugger will save me a lot of time with things I am currently working on. But I have to out myself as a newb to this ... I know "typical "debugging of .exe projects from within e.g. Visual Studio, but think it's different handling for a dll called from au3? A small hint just to get me in the right direction would be nice!
Link to comment
Share on other sites

but think it's different handling for a dll called from au3?

no, a "call" is only a jump to an adress in the memory. The variables were usually transfered into the dll-function via the stack (which is not more than a peace of memory). The AutoIt "DllCall()"-Function is a wrapper for "push the returnadress and all variables (size is depending of the types) onto the stack and jump to the address in memory, where the Function resides. When the Function is finished, pop all parameters from the stack and jump to the (saved) returnadress, back to the calling program". In 64Bitcode there´s some diffrence, but not much  ;)

So if you disassemble code (not matter which compiler created it), the way to call a "Function()" is always the same! That's what trancexx mentioned with "Dot operator in c(++) is used to access data members." 

think getting those infos via debugger will save me a lot of time with things I am currently working on

If you understand "how" the Processor is working with your code, it's much more easyier to debug than if you only know "that" the code works until it crashes.  Edited by AndyG
Link to comment
Share on other sites

If you understand "how" the Processor is working with your code, it's much more easyier to debug than if you only know "that" the code works until it crashes.

Sometimes crazy - trying to get one thing working you learn about two additional things ;) Thanks for actually helpful info!
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...