[SOLVED] Getting cva_arg to work with UDT

General FreeBASIC programming questions.
Post Reply
shadow008
Posts: 86
Joined: Nov 26, 2013 2:43

[SOLVED] Getting cva_arg to work with UDT

Post by shadow008 »

Edit: SOLVED: they don't work, see fxm's post for workaround

Consider the following code:

Code: Select all

type mytype
    x as integer
end type

sub runthing cdecl (count as integer, ...)
    
    dim test as mytype
    dim args as cva_list
    
    cva_start(args, count)
    
    test = cva_arg(args, mytype)
    
    cva_end(args)
    
end sub

dim thing as mytype

runthing(1, 2)
Is there something more I'm supposed to do to get cva_arg to work with a UDT? It seems like the compiler emits a "void" in place of where the UDT struct is supposed to be, as apparent in the compiler error:
D:\Freebasic\FBIDETEMP.c: In function 'RUNTHING':
D:\Freebasic\FBIDETEMP.c:28:96: error: second argument to 'va_arg' is of incomplete type 'void'
28 | __builtin_memcpy( &TEST$1, (struct $6MYTYPE*)&__builtin_va_arg( *(__builtin_va_list*)&ARGS$1, void), 8 );
| ^~~~
At least it's getting the size right...

If I change the second argument of cva_arg to a builtin type like "integer", we see the following C code emitted and everything is happy:

Code: Select all

TEST$1 = __builtin_va_arg( *(__builtin_va_list*)&ARGS$1, int64);
Looks like a bug, but I'm willing to believe I'm missing something. I can use pointers in the meantime, but it's a rather disappointing workaround.
Last edited by shadow008 on Mar 13, 2023 19:19, edited 1 time in total.
fxm
Moderator
Posts: 12109
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: [Bug?] Getting cva_arg to work with UDT

Post by fxm »

Only numeric types and pointers are supported as variable arguments:
- All bytes and shorts passed on variable arguments are implicitly converted to integers.
- All singles passed on variable arguments are implicitly converted to doubles.
- Strings (or Wstrings) can be directly passed by user, in which case a Zstring Ptr (or a Wstring Ptr) to the string (or the wstring) data is taken into account as internal passed argument.
fxm
Moderator
Posts: 12109
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: [Bug?] Getting cva_arg to work with UDT

Post by fxm »

UDT instances can be passes through pointers.
Example from the Programmer's Guide / Variadic Arguments (on this page I tried to gather all useful information for coding):

Code: Select all

' Variadic sub:
'    The first(fixed) parameter provides the number of elements.
'    The variable arguments are all UDT Ptr.

Type UDT
    Dim As String s
    Dim As Single d
End Type

Sub printUDT CDecl (ByVal count As Integer, ...)
    Dim args As cva_list
    Dim pu As UDT Ptr
   
    cva_start(args, count)

    For i As Integer = 1 To count
        pu = cva_arg(args, UDT Ptr)
        Print pu->s, pu->d
    Next
   
    cva_end(args)
End Sub

Dim As UDT u1, u2, u3
u1.s = "4*Atn(1)" : u1.d = 4 * Atn(1)
u2.s = "Sqr(2)"   : u2.d = Sqr(2)
u3.s = "Log(10)"  : u3.d = Log(10)

printUDT(3, @u1, @u2, @u3)

Sleep

' Output:
' 4*Atn(1)       3.141593
' Sqr(2)         1.414214
' Log(10)        2.302585
shadow008
Posts: 86
Joined: Nov 26, 2013 2:43

Re: [SOLVED] Getting cva_arg to work with UDT

Post by shadow008 »

I sorta figured that might be the case, though I guess I didn't read the docs well enough. The pointer workaround was what I was already doing. Thank you for the clarification though.

For discussions sake though, how difficult would it be to support UDTs if we assume they will only work with the default constructor? For instance, C's va_arg works with structs out of the box; va_arg will assign a copy of the struct (I think?). It would be acceptable in Freebasic if it accepted a UDT (i.e. a struct) while disregarding any assignment (Let) overloading, as we are working with a c library. That sounds like a nice to have if the work to implement it is trivial. Though I suspect this is a rarely used feature so maybe not worth bothering with.
Post Reply