PDA

View Full Version : Optional Parameters (a joke)



ReneMiner
15-05-2014, 12:57
Some Parameters in humans life are optional:



Type t_human
Age As Long
IQ As Long
GetMature As Function
End Type

Function t_human.GetMature( ByVal become_older As Number,
Optional ByVal become_smarter As Boolean
) As DWord

Me.Age += become_older

If become_Smarter Then
Incr Me.IQ
EndIf

Function = VarPtr( Me )

End Function

John Spikowski
15-05-2014, 18:20
Hi Rene,

The C stdarg.h (http://en.wikipedia.org/wiki/Stdarg.h) is the cross platform way of handing variadic functions. The last time I visited this topic, Jose Roca indicated PowerBASIC didn't support the use of variadic style functions. I would be interested in how you guys address and solve this issue.


John

John Spikowski
15-05-2014, 23:39
Here is a challenge for you Rene. Create a ThinBASIC user function that is a wrapper for printf().



printf("Color %s, number1 %d, number2 %05d, hex %#x, float %5.2f, unsigned value %u.\n","red", 123456, 89, 255, 3.14159, 250);


Output:

Color red, number1 123456, number2 00089, hex 0xff, float 3.14, unsigned value 250.

ErosOlmi
15-05-2014, 23:54
Not Exactly the same but ... StrFormat$ (http://www.thinbasic.com/public/products/thinBasic/help/html/strformat$.htm) does a nice job.


Uses "Console"

PrintL StrFormat$("Color {1}, number1 {2}, number2 {3}, hex {4}, float {5}, unsigned value {6}", "red", 123456, 89, 255, 3.14159, 250)

WaitKey


Output:

Color red, number1 123456, number2 89, hex 255, float 3.14159, unsigned value 250

John Spikowski
16-05-2014, 00:02
Nice!

Unfortunately that doesn't help with accessing C libraries with variadic functions.

Here is a common function I use in IUP as a container.


Ihandle* IupVbox(Ihandle *child, ...);



child, ... : List of the identifiers that will be placed in the box. NULL must be used to define the end of the list in C. It can be empty.


ThinBASIC should be the easiest of the BASIC interpreters to get variadic functions working. Since TB is being interpreted on the fly, variable parameters should be a walk in the park.

ReneMiner
16-05-2014, 10:22
I love my Ignore List :D

John Spikowski
16-05-2014, 18:48
I love my Ignore List

Reality put you on its ignore list years ago. :D

Petr Schreiber
17-05-2014, 10:11
I remember the discussion regarding variadic functions popping out in the past.

I still think it works perfectly enough to pass array of something in case I need to pass lot of ... something.

Array assignment is easy to do in ThinBASIC:


' -- Assign five values from the element 1
myArray(1) = 1, 2, 3, 4, 5

MyFunction( myArray )

Even with variadic functions, you access the parameters with index later :)

I think in most real world cases you don't hardcode tons of parameters, but you receive them by processing some data source, often not knowning their total amount.
During such a process, you will most probably put them into some kind of collection anyway.

Too many parameters for function are also generally considered one of the cases of "code smell", although the variadics are a bit special case.
I recommend checking out "Refactoring fundamentals" at Plural sight to get more info on keeping the code nice, really inspiring.


Petr

John Spikowski
17-05-2014, 17:27
Petr,

I agree there are more elegant ways to pass lists of arguments in a function. I pass complex SB matrix structures all the time as arguments. The problem is most C libraries use veriadic functions and if you wish to use those libraries then you need a stdarg.h like interface.

John

José Roca
17-05-2014, 23:59
The last time I visited this topic, Jose Roca indicated PowerBASIC didn't support the use of variadic style functions.


Meaning that you can't write one with PB, not that you can't call one implemented in a C DLL.

John Spikowski
18-05-2014, 07:03
Hi José,

Thanks for chiming in. It would be great if you could post an example of what you mean. I just converted a BaCon MID veriadic function to C BASIC. How would you write this function in PowerBASIC or a C wrapper for it?



FUNCTION char PTR cbrt_mid(char PTR cbrt_src, ...)
BEGIN_FUNCTION
DIM AS va_list cbrt_ap;
DIM AS long cbrt_start, cbrt_len, cbrt_l;
IF (cbrt_src EQ NULL) THEN_DO RETURN_FUNCTION("");
va_start(cbrt_ap, cbrt_src);
cbrt_start = va_arg(cbrt_ap, long);
IF (cbrt_start < 1) THEN_DO RETURN_FUNCTION(cbrt_src);
cbrt_l = strlen(cbrt_src);
IF (cbrt_start > cbrt_l) THEN_DO RETURN_FUNCTION("");
cbrt_len = va_arg(cbrt_ap, long);
IF (cbrt_len < 0 OR cbrt_start + cbrt_len > cbrt_l) THEN_DO cbrt_len = cbrt_l - cbrt_start + 1;
INCR cbrt_sbuffer_ptr;
IF (cbrt_sbuffer_ptr >= 256) THEN_DO cbrt_sbuffer_ptr = 0;
cbrt_sbuffer[cbrt_sbuffer_ptr] = (char PTR)__sbuf_realloc(cbrt_sbuffer[cbrt_sbuffer_ptr], (cbrt_len + 1) * sizeof(char));
memcpy(cbrt_sbuffer[cbrt_sbuffer_ptr], cbrt_src + (cbrt_start - 1) * sizeof(char), cbrt_len * sizeof(char));
cbrt_sbuffer[cbrt_sbuffer_ptr][cbrt_len] = '\0';
va_end(cbrt_ap);
RETURN_FUNCTION (char PTR)(cbrt_sbuffer[cbrt_sbuffer_ptr]);
END_FUNCTION

José Roca
18-05-2014, 16:42
Meaning that you can't write one with PB, not that you can't call one implemented in a C DLL.


I think that I have been clear. It starts saying that you can't write a variadic function with PB, so I don't understand why you reply asking me to write one. But if you write one in C, compile it to a DLL and export it, you can call it with PB.

John Spikowski
18-05-2014, 18:36
Okay. I understand what you're saying. It's not calling veriadic functions that is the problem for PB, it's writing one in PB.

Mike's offer still sounds like the best deal going.

José Roca
18-05-2014, 20:09
> Mike's offer still sounds like the best deal going.

Hard to know, since he has deleted his post.

mike lobanovsky
19-05-2014, 01:33
Hard to know, since he has deleted his post.

Hi José,

I was plain sorry for spawning involuntarily yet one more flaming and trolling thread. If I could, I would've deleted the entire thread but I succeeded only in deleting my own message.

Since there was no response in any form from Eros even though he had seen my message, I decided my suggestion was rejected.

Nonetheless, it's absolutely feasible. You can still see both BASIC-style argtable[] and C-style va_arg solutions of variadic calls to DLL functions in the BCX sources under the names of BCX_DynaCallA and BCX_DynaCallB, respectively. Credits to my contributions to BCX are long gone from Bob Wishlaw's annals and the both solutions have degenerated over time under somebody's short-sighted guidance to STDCALL-only calls and integer-only returns. But they can be easily restored/repaired to accept STDCALL/CDECL calls in the same code and to support integer, long long, single and double returns. The number and data types of call arguments really don't matter and can be whatever the callee functions are ready to accept.

The BCX_DynaCallA solution can be re-implemented in PowerBASIC without any problem. If Eros would yet change his mind and accept my proposal, I'd still like to be notified about it explicitly to be able to formulate my express permission as the code author to use this code in a closed-source project.


Regards,

José Roca
19-05-2014, 03:02
As I said, there are no problems calling variadic functions with PowerBASIC. I have done it several times.

For example, to call the wsprintfA function, I have used the following declare:



DECLARE FUNCTION wsprintfA CDECL IMPORT "USER32.DLL" ALIAS "wsprintfA" ( _
BYREF lpOut AS ASCIIZ _ ' __out LPSTR lpOut
, BYREF lpFmt AS ASCIIZ _ ' __in LPCSTR lpFmt
, OPTIONAL ANY, ANY, ANY,ANY, ANY, ANY, ANY, ANY, ANY, ANY, ANY, ANY, ANY, ANY, ANY, ANY) AS LONG


and called it in one of my examples as:



wsprintfA szCaption, $WindowCaption & " (%i FPS)", BYVAL fps


It works very well, despite John's opinion that my declares are bad translated, crippled, hand manipulated, multi-aliased, and his advise to not convert headers to libraries PB can't support (strangely, they work).

mike lobanovsky
19-05-2014, 04:11
Yes José,

Yours is also a nice (and reasonable) palliation for a pseudo-definite number of function arguments. Mine targets an indefinite number of them but is slightly slower by perhaps half a dozen CPU clocks per each argument. This however isn't the decisive factor in a purely interpretative environment of thinBasic.

Well, now it's up to Eros to decide if he wants to use either approach in his re-implementation of variadic function calls in thinBasic and if thinBasic needs this feature at all in the first place. :)

John Spikowski
19-05-2014, 04:28
It works very well, despite John's opinion that my declares are bad translated, crippled, hand manipulated, multi-aliased, and his advise to not convert headers to libraries PB can't support (strangely, they work).

Did I say all that in one post? :D

Your approach is much like what Peter (BaCon author) did for the GTK-Server FFI interface. As you say, it works, why fix it?



if thinBasic needs this feature at all in the first place.


Maybe thinBasic can get by but SB is dependent on 3rd party C open source libraries when used other than in embedded environments. I would say 10% or more of the IUP API calls are variadic based. I'm forking BaCon's runtime library to C BASIC and so far 2 of the 3 functions I converted are variadic functions.

All calls to Script BASIC extension module DLL/SO shared object functions are veriadic based.