Pass Structure To Prototype/Procedure By Value?

Just starting out? Need help? Post your questions and find answers here.
User avatar
skywalk
Addict
Addict
Posts: 4211
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Pass Structure To Prototype/Procedure By Value?

Post by skywalk »

I had to create a Prototype to an external dll which passes a structure by value. I wondered why it is not supported? And is the workaround of passing a copy of the structure below correct? I am fuzzy on this...

Code: Select all

PASS STRUCTURES TO FUNCTION:   C     PB
1. By value.                   1     0 - Why?
2. By reference(address).      1     1
3. As Global variable.         1     1

Code: Select all

Structure myStruc
  i.i
  x.d
  y.d
EndStructure
Global mySt.myStruc
mySt\i = 1
mySt\x = 2.1
mySt\y = 3.1

;Prototype UseStrucByVal(p.myStruc, Var2.i)   ;<-- ByVal  = Syntax error.
PrototypeC UseStrucByVal(*p_myStruc, Var2.i)  ;<-- ByCopy = OK.

;Procedure UseStrucByVal(p.myStruc, Var2.i)   ;<-- ByVal  = Syntax error.
ProcedureC UseStrucByVal(*p_myStruc, var2.i)  ;<-- ByCopy = OK.
  Debug "-- UseStrucByVal --"
  Debug PeekI(*p_myStruc + 0)
  Debug PeekD(*p_myStruc + OffsetOf(myStruc\x))
  Debug PeekD(*p_myStruc + OffsetOf(myStruc\y))
  PokeI(*p_myStruc + 0, var2)
EndProcedure
Procedure UseStrucByRef(*p.myStruc, Var2.i)   ;<-- ByRef  = OK.
  Debug "-- UseStrucByRef --"
  Debug *p\i
  Debug *p\x
  Debug *p\y
EndProcedure

Define doProtoByVal.UseStrucByVal = @UseStrucByVal()
Define.i *p = AllocateMemory(SizeOf(myStruc))
CopyStructure(@mySt, *p, myStruc)

UseStrucByVal(*p, 99)
UseStrucByRef(@mySt, 99)
UseStrucByVal(*p, 99)     ;<-- Show edited copy of mySt
ShowCallstack()
doProtoByVal(*p, 999)
FreeMemory(*p)
UseStrucByRef(@mySt, 99)  ;<-- Show unedited mySt
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
DontTalkToMe
Enthusiast
Enthusiast
Posts: 334
Joined: Mon Feb 04, 2013 5:28 pm

Re: Pass Structure To Prototype/Procedure By Value?

Post by DontTalkToMe »

It's not supported and it's not possible unless the structure is very small (and you still need to be lucky)

http://purebasic.fr/english/viewtopic.php?f=13&t=61916

http://www.purebasic.fr/english/viewtop ... 13&t=47006

Also even different C compilers implements this in different ways, sometimes the structure is passed via the stack, sometimes by registers.

Binary compatibility hence is not guaranteed and unfortunately this is good enough reason to not support it (when calling not PB code, intra-PB of course could be implemented).

Possible solutions if the trick mentioned in the threads above is not feasible: write a C wrapper using a compatible compiler to build a layer which bridge the two conventions, or write specific code probably in asm once you have determined how the structure is passed in the binary implementation you want to call.
User avatar
skywalk
Addict
Addict
Posts: 4211
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: Pass Structure To Prototype/Procedure By Value?

Post by skywalk »

Wait, what?
Isn't the point of a compiler to do those necessary steps that are clearly defined for a confined set of datatypes and calling conventions? My understanding is C initially only supported ByRef Struct's, but modern C compilers extended support to ByVal. I see no mention of the perils you outline? Maybe it is later on when you attempt to compile with larger struct's? But I cannot find it in the few C compiler manuals I read.
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
User avatar
Lunasole
Addict
Addict
Posts: 1091
Joined: Mon Oct 26, 2015 2:55 am
Location: UA
Contact:

Re: Pass Structure To Prototype/Procedure By Value?

Post by Lunasole »

DontTalkToMe wrote: Possible solutions if the trick mentioned in the threads above is not feasible: write a C wrapper using a compatible compiler to build a layer which bridge the two conventions, or write specific code probably in asm once you have determined how the structure is passed in the binary implementation you want to call.
Yes, the wrappers or modification of original function are the only solution as for me.
Fortunately I recently not often seeing C code which is written so badly and requires byval.

Btw, I just had some idea - what if pass structure as a list of arguments? Can it work somehow (by fact the byval structure in C is not byval as I remember)?

Code: Select all

; for example, here is function which wants structure byval
Procedure A (STRUCTUREBYVAL)

; but let declare it this way when importing it
Procedure A (STRUCTUREFIELD1, STRUCTUREFIELD2, ..., STRUCTUREFIELD20)
"W̷i̷s̷h̷i̷n̷g o̷n a s̷t̷a̷r"
DontTalkToMe
Enthusiast
Enthusiast
Posts: 334
Joined: Mon Feb 04, 2013 5:28 pm

Re: Pass Structure To Prototype/Procedure By Value?

Post by DontTalkToMe »

http://stackoverflow.com/questions/1617 ... -passing-a
http://stackoverflow.com/questions/2677 ... ction-in-c
http://www.agner.org/optimize/calling_conventions.pdf, page 20

the pdf above is for C++ compilers, but the methods outlined there for structures are used by recent C compilers too.

anyway the problem is the implementation is compiler specific, and it's even more fragmented when you put cross-platform compilers in the mix:
some generate code to copy the structure on the stack, some to allocate space in the heap and memcopy it (slower but it saves stack space), some use registers for certain sizes but maybe only on x64 and not x86, etc.
User avatar
skywalk
Addict
Addict
Posts: 4211
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: Pass Structure To Prototype/Procedure By Value?

Post by skywalk »

Yeah, reading more on this last night...My take away is there may be a possibile speed improvement when passing a structure by value because it saves the function from having to dereference constantly. And no threat of altering the original structure.
But, the overall opinion is it has limited application and is not advised if the structure is large and contains nested data structures/pointers. Or if you target multiple processors. And many more "against's" than "for's".

I came upon this requirement in a rare case and did not realize how deep a rabbit hole it becomes. :?
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
Post Reply