| PowerBASIC | ||
|
The SocketTools Library Edition provides a complete set of function declarations and constants in the Include folder named cstools6.inc which can be included with your projects. It is recommended that you use at least version 7.0 of the PowerBASIC compiler. The samples included with SocketTools were developed using version 8.0 of the compiler and version 1.51 of the form designer. String ArgumentsAn important consideration when using the SocketTools libraries in PowerBASIC is how string arguments are used by the function. In most cases, the string is provided as input to the function, such as the hostname or address of a server to establish a connection with. However, in some cases the string is passed to the function as an output buffer into which the function copies data. An example of this would be the GetErrorString function, which is used to obtain a description of a specific error. In C/C++ you would allocate a character array and pass it to the function, such as:
PowerBASIC has a string type called ASCIIZ which is null terminated, fixed-length string and is compatible with how strings are passed to the functions in the SocketTools API. The equivalent code would be:
It is important to note that you should generally not use STRING types, since those represent variable length strings. Byte Array ArgumentsA number of SocketTools functions use byte arrays, either as an input argument to the function, or as an output argument which will contain data when the function returns. An example of this is the HttpGetData function, which will access a resource on the server and return the contents of that resource in a byte array passed to the function. For example, the following code in C++ would return the first 1024 bytes of the index page on a webserver:
If the function is successful, the byteBuffer array will contain the first 1024 bytes of the index page. In PowerBASIC, the equivalent code would look like this:
In this example, you will notice that the byteBuffer array is passed by reference, specifying the first element. The function will fill the byte array up to the number of bytes specified by the dwLength argument; when the function returns, dwLength will be updated with the actual number of bytes copied into the buffer. If you wanted to convert the data in the byte array to a string type, you can terminate the data with a null character. However, this means that you should reserve a byte in the array. For example:
Note that you should only do this if the data returned by the function is actually text. In this example, it is acceptable to do because the byte array contains the HTML text for the index page. Global Memory HandlesIn addition to using byte arrays, some SocketTools functions can use global memory handles (HGLOBALs) to exchange large amounts of data. Using the Windows API, global memory handles are allocated by the GlobalAlloc function, dereferenced by the GlobalLock function and released by the GlobalFree function. These functions are defined in the WIN32API.INC module that is included with the language. An application may choose to use a global memory handle instead of a pre-allocated buffer if the amount of data is very large, or the total amount of data that will be returned is unknown at the time the function is being called. Consider the call to the HttpGetData function used in the previous example. A pre-allocated buffer of 1024 bytes was passed to the function, and it copied up to that amount of data into the buffer. However, what if you wanted the complete page and did not know how large it was? You could attempt to determine the size of the page that was being requested using the HttpGetFileSize function, and then use that value to allocate a buffer. However, this incurs additional overhead and it is not always possible to get the size of a resource on a web server. Another alternative would be to simply allocate a very large buffer, but this could result in the application allocating large amounts of memory that it doesn't use and you would still run the risk that it wouldn't be large enough. The solution for this problem is to use a global memory handle rather than a pre-allocated buffer. Instead of copying the data into a buffer, the function allocates a global memory handle and stores the contents in the memory referenced by that handle. When the function returns, it passes the handle back to the caller. The caller then dereferences the handle to access the memory, and releases the handle when it is no longer needed. Here is an example of how it would be used in C/C++:
Note that the global memory handle is initialized to NULL and the length argument is initialized to zero. This is important to do because this is how the function knows that it should be returning a global memory handle instead of copying data into a buffer. If you forget to initialize those arguments, the function will fail and may cause the application to terminate with a general protection fault. The equivalent code in PowerBASIC would look like this:
It is important to remember to unlock and release the global memory handle when you are no longer using it. If you forget to release them, the application will have a memory leak. Event HandlersSocketTools uses events to notify the application when some change in status occurs, such as when data is available to be read or progress notifications during a file transfer. An event handler is simply a callback function which has a specific set of arguments, and the address of that function is passed to the RegisterEvent function in the library. The first step to creating an event handler is to create a function which matches the signature of the callback function defined by the SocketTools event notification function. When the event handler is called, SocketTools will pass the handle to the client session, an event identifier to specify which event occurred, an error code value if an error occurred, and the user-defined value that was specified by the caller when the event was registered. In C++, the callback function would be declared as:
In PowerBASIC, the equivalent function would be defined as:
Note that the STDCALL has been specified for the function. This is important, because the SocketTools libraries require this calling convention, as do any Windows API functions which use callback functions. Failure to specify the correct calling convention can prevent the callback function from being invoked or can cause the application to terminate abnormally. Let's create an event handler that updates a progress bar as a file is being downloaded from an HTTP server. To do this, we'll create a subroutine called HttpEventHandler:
This event handler checks to see if the event ID indicates that it is a progress event, and if it is, calls HttpGetTransferStatus to determine the number of bytes that have been copied so far. This is used to calculate a percentage and a progress bar control is updated with that value. Now that the event handler has been written, the next step is to register the event with the library so that it is called during the transfer. To do this, the HttpRegisterEvent function is called to enable notification for the progress event:
The first argument to HttpRegisterEvent is the handle to the client session. The second argument is the event ID for which you want to enable notification, the third argument is the address of the callback function, and the fourth argument is a user-defined value. That same value is passed to the event handler as the dwParam argument. To update a progress bar control or any other user interface object, the dwParam argument would typically be the handle to a dialog. Your event handler is now registered, and SocketTools will call your event handler during the process of downloading or uploading a file to notify you of the progress of the transfer. |
||
|
Copyright © 2008 Catalyst Development Corporation. All rights reserved. |
||