06-09-2024, 06:21 PM
The short answer is that there are cases where the declaration does not have to be exact and it will still work. You're much better off writing accurate declarations though, declaring it as a `FUNCTION` is correct.
The long answer involves discussion of x86 calling conventions, which are the underlying rules involved in calling functions. In this case it works out because (assuming 64-bit) the RAX register will be used to store the return value, and RAX is also a caller-saved register. This means that when calling the `GetCursorPos()` function the caller has to assume the function may mess with the value of RAX and back it up beforehand if it needs to be kept (regardless of whether the function actually returns anything useful in it). The `GetCursorPos()` will then place the return value in `RAX`, and the calling code will simply ignore whatever value is left in there.
Note that this does not always work, you can see in the Windows section that if a structure is too large to fit into RAX then a different convention of the caller allocating space for the result and passing it to the function is used. In this case, if you did not list the correct return value then things would go very wrong (but then, you can't actually declare such a function in QB64, so it doesn't matter that much).
The different kinds of `DECLARE LIBRARY` are also different levels of forgiving in this regard, because while `Dynamic` will force the function to be the declared type, others like regular `Declare Library` simply insert a call to the specified function and rely in the definition already being provided in the C++ code (via a header or elsewhere).
The long answer involves discussion of x86 calling conventions, which are the underlying rules involved in calling functions. In this case it works out because (assuming 64-bit) the RAX register will be used to store the return value, and RAX is also a caller-saved register. This means that when calling the `GetCursorPos()` function the caller has to assume the function may mess with the value of RAX and back it up beforehand if it needs to be kept (regardless of whether the function actually returns anything useful in it). The `GetCursorPos()` will then place the return value in `RAX`, and the calling code will simply ignore whatever value is left in there.
Note that this does not always work, you can see in the Windows section that if a structure is too large to fit into RAX then a different convention of the caller allocating space for the result and passing it to the function is used. In this case, if you did not list the correct return value then things would go very wrong (but then, you can't actually declare such a function in QB64, so it doesn't matter that much).
The different kinds of `DECLARE LIBRARY` are also different levels of forgiving in this regard, because while `Dynamic` will force the function to be the declared type, others like regular `Declare Library` simply insert a call to the specified function and rely in the definition already being provided in the C++ code (via a header or elsewhere).