Page 1 of 1

Simple way to use variable parameters for Procedures

Posted: Fri Mar 16, 2012 6:26 pm
by ts-soft

Code: Select all

;==================================================================
; ###  Example to use variable parameters for Procedures    ###
; Author:            Thomas <ts-soft> Schulz
; Date:              Mrz 16, 2012
; Version:           1.0
; Target OS:         All
; Target Compiler:   PureBasic 4.40 and later
;==================================================================

EnableExplicit

Structure V_ARG
  Type.l
  StructureUnion
    a.a
    b.b
    c.c
    d.d
    f.f
    i.i
    l.l
    *s.String
    q.q
    u.u
    w.w
  EndStructureUnion
EndStructure

Procedure V_ARG_Add(Array V_ARG.V_ARG(1), Type.l, *value)
  Protected index = ArraySize(V_ARG())
  Protected *v.Quad = *value
  ReDim V_ARG(index + 1)

  With V_ARG(index)
    \Type = Type
    \q = *v\q
  EndWith
EndProcedure

; example
Procedure Foo(Array V_ARG.V_ARG(1))
  Protected i
  Protected count = ArraySize(V_ARG())
  Debug "Count of parameters: " + Str(count)
  Debug ""
  For i = 0 To count - 1
    With V_ARG(i)
      Select \Type
        Case #PB_Ascii
          Debug "Parameter " + Str(i + 1) + " = UByte, Value = " + Str(V_ARG(i)\a)
        Case #PB_Byte
          Debug "Parameter " + Str(i + 1) + " = Byte, Value = " + Str(V_ARG(i)\b)
        Case #PB_Character
          Debug "Parameter " + Str(i + 1) + " = Char, Value = " + Str(V_ARG(i)\c)
        Case #PB_Double
          Debug "Parameter " + Str(i + 1) + " = Double, Value = " + StrD(V_ARG(i)\d)
        Case #PB_Float
          Debug "Parameter " + Str(i + 1) + " = FLoat, Value = " + StrF(V_ARG(i)\f)
        Case #PB_Integer
          Debug "Parameter " + Str(i + 1) + " = Integer, Value = " + Str(V_ARG(i)\i)
        Case #PB_Long
          Debug "Parameter " + Str(i + 1) + " = Long, Value = " + Str(V_ARG(i)\l)
        Case #PB_Quad
          Debug "Parameter" + Str(i + 1) + " = Quad, Value = " + Str(V_ARG(i)\q)
        Case #PB_String
          Debug "Parameter " + Str(i + 1) + " = String, Value = " + PeekS(V_ARG(i)\s)
        Case #PB_Unicode
          Debug "Parameter " + Str(i + 1) + " = UWord, Value = " + Str(V_ARG(i)\u)
        Case #PB_Word
          Debug "Parameter " + Str(i + 1) + " = Word, Value = " + Str(V_ARG(i)\w)
      EndSelect
    EndWith
  Next
EndProcedure

Dim para_array.V_ARG(0)

Define Text.String
Text\s = "Feel the ..Pure.. Power"
V_ARG_Add(para_array(), #PB_String, @Text)

Define pi.d = #PI
V_ARG_Add(para_array(), #PB_Double, @pi)

Define word.w = 65535
V_ARG_Add(para_array(), #PB_Word, @word)
V_ARG_Add(para_array(), #PB_Unicode, @word)

Foo(para_array())

Have Fun :D

Re: Simple way to use variable parameters for Procedures

Posted: Sat Mar 17, 2012 2:44 am
by IdeasVacuum
woa, that's too clever......... :mrgreen:

Re: Simple way to use variable parameters for Procedures

Posted: Sat Mar 17, 2012 5:57 pm
by rsts
IdeasVacuum wrote:woa, that's too clever......... :mrgreen:
Mr Soft is VERY clever :)

Thanks for sharing.

Re: Simple way to use variable parameters for Procedures

Posted: Sat Mar 17, 2012 6:03 pm
by ts-soft
You can use this, for example a interpreter like program, using only one prototype for all functions.
It is simple, as the title say, but it is a hint for some projects.

Re: Simple way to use variable parameters for Procedures

Posted: Sun Jan 12, 2014 8:02 pm
by NicTheQuick
This version makes it a little bit easier to use. The type and size of a variable will be set automatically (since PB V5.1). But be careful if the variable has the same name as a structure. In this case there will be pop out a compiler error.

Code: Select all

;==================================================================
; ###  Example to use variable parameters for Procedures    ###
; Author:            Thomas <ts-soft> Schulz & <NicTheQuick>
; Date:              Mrz 16, 2012
; Version:           1.1
; Target OS:         All
; Target Compiler:   PureBasic 5.10 and later
;==================================================================

EnableExplicit

Structure V_ARG
   Type.l
   StructureUnion
      a.a
      b.b
      c.c
      d.d
      f.f
      i.i
      l.l
      q.q
      u.u
      w.w
   EndStructureUnion
   s.s
EndStructure

Procedure V_ARG_Add_(Array V_ARG.V_ARG(1), Type.l, size.i, *value)
   Protected index = ArraySize(V_ARG())
   ReDim V_ARG(index + 1)
   
   With V_ARG(index)
      \Type = Type
      If (Type = #PB_String)
         \s = PeekS(*value)
      Else
         CopyMemory(*value, @V_ARG(index) + OffsetOf(V_ARG\a), size)
      EndIf
   EndWith
EndProcedure

Macro V_ARG_Add(v_arg, value)
CompilerIf TypeOf(value) = #PB_Structure
	CompilerError "The variable has no native type. This is not supported."
CompilerEndIf
   V_ARG_Add_(v_arg, TypeOf(value), SizeOf(value), @value)
EndMacro

; example
Procedure Foo(Array V_ARG.V_ARG(1))
   Protected i.i
   Protected count.i = ArraySize(V_ARG())
   Debug "Count of parameters: " + Str(count)
   Debug ""
   For i = 0 To count - 1
      With V_ARG(i)
         Debug \Type
         Select \Type
            Case #PB_Ascii
               Debug "Parameter " + Str(i + 1) + " = UByte, Value = " + Str(V_ARG(i)\a)
            Case #PB_Byte
               Debug "Parameter " + Str(i + 1) + " = Byte, Value = " + Str(V_ARG(i)\b)
            Case #PB_Character
               Debug "Parameter " + Str(i + 1) + " = Char, Value = " + Str(V_ARG(i)\c)
            Case #PB_Double
               Debug "Parameter " + Str(i + 1) + " = Double, Value = " + StrD(V_ARG(i)\d)
            Case #PB_Float
               Debug "Parameter " + Str(i + 1) + " = FLoat, Value = " + StrF(V_ARG(i)\f)
            Case #PB_Integer
               Debug "Parameter " + Str(i + 1) + " = Integer, Value = " + Str(V_ARG(i)\i)
            Case #PB_Long
               Debug "Parameter " + Str(i + 1) + " = Long, Value = " + Str(V_ARG(i)\l)
            Case #PB_Quad
               Debug "Parameter" + Str(i + 1) + " = Quad, Value = " + Str(V_ARG(i)\q)
            Case #PB_String
               Debug "Parameter " + Str(i + 1) + " = String, Value = " + V_ARG(i)\s
            Case #PB_Unicode
               Debug "Parameter " + Str(i + 1) + " = UWord, Value = " + Str(V_ARG(i)\u)
            Case #PB_Word
               Debug "Parameter " + Str(i + 1) + " = Word, Value = " + Str(V_ARG(i)\w)
         EndSelect
      EndWith
   Next
EndProcedure

Dim para_array.V_ARG(0)

Define Text.s
Text = "Feel the ..Pure.. Power"
V_ARG_Add(para_array(), Text)

Define pi.d = #PI
V_ARG_Add(para_array(), pi)

Define word1.w = 65535
V_ARG_Add(para_array(), word1)
V_ARG_Add(para_array(), word1)

Foo(para_array()) 

Re: Simple way to use variable parameters for Procedures

Posted: Mon Jan 13, 2014 12:13 pm
by Kwai chang caine
Very usefull code, thanks a lot for sharing 8)

Re: Simple way to use variable parameters for Procedures

Posted: Thu Sep 03, 2015 7:35 pm
by GPI
My Variant :)
Call supports here up to 10 parameters.

Code: Select all

;==================================================================
; ###  Example to use variable parameters for Procedures    ###
; Author:            Thomas <ts-soft> Schulz & <NicTheQuick>
; Date:              Mrz 16, 2012
; Version:           1.1
; Target OS:         All
; Target Compiler:   PureBasic 5.10 and later
;==================================================================



EnableExplicit


Macro MacroQuote
  "
EndMacro


Structure V_ARG
  Type.l
  StructureUnion
    a.a
    b.b
    c.c
    d.d
    f.f
    i.i
    l.l
    q.q
    u.u
    w.w
  EndStructureUnion
  s.s
EndStructure

Procedure V_ARG_Add_(Array V_ARG.V_ARG(1), Type.l, size.i, *value)
  Protected index = ArraySize(V_ARG())
  ReDim V_ARG(index + 1)
  
  With V_ARG(index)
    \Type = Type
    If (Type = #PB_String)
      \s = PeekS(*value)
    Else
      CopyMemory(*value, @V_ARG(index) + OffsetOf(V_ARG\a), size)
    EndIf
  EndWith
EndProcedure

Macro V_ARG_START
  Dim __varg.V_ARG(0)
EndMacro
  
  

Macro V_ARG_Add(value)
  CompilerIf TypeOf(value) = #PB_Structure
    CompilerError "The variable has no native type. This is not supported."
  CompilerEndIf
  V_ARG_Add_(__varg(), TypeOf(value), SizeOf(value), @value)
EndMacro

Macro V_ARG_LIST
  __varg()
EndMacro

Macro V_ARG_END
  FreeArray(__varg())
EndMacro

Macro Call(ret,proc,a1=,a2=,a3=,a4=,a5=,a6=,a7=,a8=,a9=,a10=)
  V_ARG_START
  CompilerIf  MacroQuote#a1#Macroquote<>""
    V_ARG_Add(a1)
  CompilerEndIf
  CompilerIf  MacroQuote#a2#Macroquote<>""
    V_ARG_Add(a2)
  CompilerEndIf
  CompilerIf  MacroQuote#a3#Macroquote<>""
    V_ARG_Add(a3)
  CompilerEndIf
  CompilerIf  MacroQuote#a4#Macroquote<>""
    V_ARG_Add(a4)
  CompilerEndIf
  CompilerIf  MacroQuote#a5#Macroquote<>""
    V_ARG_Add(a5)
  CompilerEndIf
  CompilerIf  MacroQuote#a6#Macroquote<>""
    V_ARG_Add(a6)
  CompilerEndIf
  CompilerIf  MacroQuote#a7#Macroquote<>""
    V_ARG_Add(a7)
  CompilerEndIf
  CompilerIf  MacroQuote#a8#Macroquote<>""
    V_ARG_Add(a8)
  CompilerEndIf
  CompilerIf  MacroQuote#a9#Macroquote<>""
    V_ARG_Add(a9)
  CompilerEndIf
  CompilerIf  MacroQuote#a10#Macroquote<>""
    V_ARG_Add(a10)
  CompilerEndIf
  CompilerIf MacroQuote#ret#MacroQuote="#Null"
    proc ( V_ARG_LIST )
  CompilerElse
    ret = proc ( V_ARG_LIST )
  CompilerEndIf
  
    V_ARG_END

EndMacro



; example
Procedure Foo(Array V_ARG.V_ARG(1))
  Protected i.i
  Protected count.i = ArraySize(V_ARG())
  Debug "Count of parameters: " + Str(count)
  Debug ""
  For i = 0 To count - 1
    With V_ARG(i)
      Debug \Type
      Select \Type
        Case #PB_Ascii
          Debug "Parameter " + Str(i + 1) + " = UByte, Value = " + Str(V_ARG(i)\a)
        Case #PB_Byte
          Debug "Parameter " + Str(i + 1) + " = Byte, Value = " + Str(V_ARG(i)\b)
        Case #PB_Character
          Debug "Parameter " + Str(i + 1) + " = Char, Value = " + Str(V_ARG(i)\c)
        Case #PB_Double
          Debug "Parameter " + Str(i + 1) + " = Double, Value = " + StrD(V_ARG(i)\d)
        Case #PB_Float
          Debug "Parameter " + Str(i + 1) + " = FLoat, Value = " + StrF(V_ARG(i)\f)
        Case #PB_Integer
          Debug "Parameter " + Str(i + 1) + " = Integer, Value = " + Str(V_ARG(i)\i)
        Case #PB_Long
          Debug "Parameter " + Str(i + 1) + " = Long, Value = " + Str(V_ARG(i)\l)
        Case #PB_Quad
          Debug "Parameter" + Str(i + 1) + " = Quad, Value = " + Str(V_ARG(i)\q)
        Case #PB_String
          Debug "Parameter " + Str(i + 1) + " = String, Value = " + V_ARG(i)\s
        Case #PB_Unicode
          Debug "Parameter " + Str(i + 1) + " = UWord, Value = " + Str(V_ARG(i)\u)
        Case #PB_Word
          Debug "Parameter " + Str(i + 1) + " = Word, Value = " + Str(V_ARG(i)\w)
      EndSelect
    EndWith
  Next
  ProcedureReturn count
EndProcedure

V_ARG_START

Define Text.s
Text = "Feel the ..Pure.. Power"
V_ARG_Add( Text)

Define pi.d = #PI
V_ARG_Add( pi)

Define word1.w = 65535
V_ARG_Add(word1)
V_ARG_Add( word1)

Foo(V_ARG_LIST) 

V_ARG_END

Call(#Null,Foo,text,pi,word1,pi,word1)

Call(#Null,Foo,text,pi,pi,pi,pi)

Define ret.i
call(ret,Foo,pi,text)
Debug "Return:"+Str(ret)


Re: Simple way to use variable parameters for Procedures

Posted: Tue Nov 03, 2015 6:00 pm
by NicTheQuick
Make it a "Threaded Dim" and you also have thread support. :)