There is a large class of win32 API which fill in a buffer that a user supplies that cannot be called by FMSLogo. For example, people have requested access to GetWorkingDirectory and GetModuleFileName. For such requests for which FMSLogo has no primitive, it would be useful if they could use DLLCALL.
There are some design constraints that make this difficult:
Add a new "type specifier" for parameters that begins with a B (for byte buffer), followed by the number of bytes. The value is the name of the variable.to which the buffer should be assigned on success. DLLCALL allocates the buffer of the requested size.
So you might call GetWorkingDirectory like
MAKE "rval DLLCALL [L GetCurrentDirectoryA B260 workingDirectory L 260]
And on success, it would set the "workingDirectory variable to the buffer.
This breaks the functional programming model in that it requires DLLCALL to have side-effects (set variables). This can be made functional with a proper wrapper command that instructs DLLCALL to set a local variable and then returns is value.
Add a new "type specifier" for parameters that is a "B". The "value" is the number of bytes in the buffer. DLLCALL allocates the buffer of the requested size. The values are appened to the return list.
MAKE "rval DLLCALL [L GetCurrentDirectoryA B 260 L 260]
In this case, the returned list would be something like [92 C:\Program Files\FMSLogo]
This seems cleaner, but it becomes messy when callout function returns a PSTR in that the returned list would be a parsed form of the returned string (an arbitrary number of elements) followed by all of the buffer out parameters.
Both approaches suffer for the oddness of a "buffer", which does not exist in FMSLogo. These would be normal words, but they would end in "null bytes". It would be the caller's responsibility to remove the zero bytes if it wanted to treat it as a normal word.
Both approaches suffer from a vauge concern about backward-compatibility if FMSLogo supports Unicode in the future. In this case, converting the "byte buffer" to a Unicode word wouldn't be a simple matter of removing the null bytes. That is, the calling convention will break by moving to Unicode.
Diff:
I tried both approaches and decided on Approach #2, commited in [r4324]. Approach #2 made the implementation a little more complex, but architecturally cleaner, as it didn't couple the DLL subsystem to the workspace subsystem. For the Logo programmer, this approach allowed callers to use a purely functional paradigm (that is, it didn't compel the caller to create a variable to hold the buffer and rely on a side-effect have the variable be set.)
This feature will be available in FMSLogo 7.1.0.
Related
Commit: [r4324]