2021-05-20, 10:05 AM
2021-05-20: Yet Another Call Improvement
Three days ago introduced using function Name<spec>, and two days ago introduced CALL@Name. These are both methods use to specify what parameters a function expects, but they are used to pass the function as a pointer to another function that already knows what parameters the pointee should take.
Given:
The specifier is in this code twice - once in the parameters of Caller to say it wants a function that takes three parameters, and once in the addressof to say that Callee is indeed a function that meets the requirements of taking three parameters.? The same basic problem exists if you?re using using or CALL@ as well - repetition of information.
Because of how this all works, you actually can?t stop this information being duplicated, but you can hide it such that users of your function never need to worry about it.? This is normally done with &:
Much cleaner than all other solutions, but how does it work?? That?s not a standard operator.? The answer is that oft-maligned feature - macros:
Using this macro (placed almost anywhere) will detect when the second parameter (Nth parameter in other calls - just depends when you want the pointer) starts with &.? If it does it replaces that parameter with a typed call to addressof, as was done in earlier examples.? The fact that th function and macro have exactly the same name is important - this allows all the methods to work, not just one.
For Dialog_ShowCallback this would be:
For BCrypt_CheckInline:
For cb_MoveDynamicObject:
The last macro parameter will detect ALL remaining function parameters after the & - you only need to explicitly specify the parameters before &.? Thus this technique works for vararg functions as well.
Three days ago introduced using function Name<spec>, and two days ago introduced CALL@Name. These are both methods use to specify what parameters a function expects, but they are used to pass the function as a pointer to another function that already knows what parameters the pointee should take.
Given:
Quote:
Caller(arg1, Func:cb<iii>, arg2)
{
____@.cb(arg1, arg2, arg1 arg2);
}
Callee(a, b, c)
{
}
main()
{
____Caller(4, addressof (Callee<iii>), 5);
}
The specifier is in this code twice - once in the parameters of Caller to say it wants a function that takes three parameters, and once in the addressof to say that Callee is indeed a function that meets the requirements of taking three parameters.? The same basic problem exists if you?re using using or CALL@ as well - repetition of information.
Because of how this all works, you actually can?t stop this information being duplicated, but you can hide it such that users of your function never need to worry about it.? This is normally done with &:
Quote:
Caller(arg1, Func:cb<iii>, arg2)
{
____@.cb(arg1, arg2, arg1 arg2);
}
Callee(a, b, c)
{
}
main()
{
____Caller(4, &Callee, 5);
}
Much cleaner than all other solutions, but how does it work?? That?s not a standard operator.? The answer is that oft-maligned feature - macros:
Quote:
#define Caller(%0,&%1,%2) Caller(%0,addressof(%1<iii>),%2)
Using this macro (placed almost anywhere) will detect when the second parameter (Nth parameter in other calls - just depends when you want the pointer) starts with &.? If it does it replaces that parameter with a typed call to addressof, as was done in earlier examples.? The fact that th function and macro have exactly the same name is important - this allows all the methods to work, not just one.
For Dialog_ShowCallback this would be:
Quote:
#define Dialog_ShowCallback(%0,&%1,%2) Dialog_ShowCallback(%0,addressof(%1<iiiis>),%2)
For BCrypt_CheckInline:
Quote:
#define BCrypt_HashInline(%0,%1,&%2) BCrypt_HashInline(%0,%1,addressof(%2<s>))
For cb_MoveDynamicObject:
Quote:
#define cb_MoveDynamicObject(&%0,%1) cb_MoveDynamicObject(addressof(%0<i>),%1)
The last macro parameter will detect ALL remaining function parameters after the & - you only need to explicitly specify the parameters before &.? Thus this technique works for vararg functions as well.