Microsoft KB Archive/188541

= INFO: Visual Basic Requirements for Using Exported DLLs =

Article ID: 188541

Article Last Modified on 5/13/2003

-

APPLIES TO


 * Microsoft Visual Basic 5.0 Learning Edition
 * Microsoft Visual Basic 6.0 Learning Edition
 * Microsoft Visual Basic 5.0 Professional Edition
 * Microsoft Visual Basic 6.0 Professional Edition
 * Microsoft Visual Basic 5.0 Enterprise Edition
 * Microsoft Visual Basic 6.0 Enterprise Edition

-



This article was previously published under Q188541



SUMMARY
Certain requirements must be met for Visual Basic to successfully use a function exported from a DLL. These requirements include rules for declaring and calling exported functions, as well as rules for creating exported functions in a DLL. This article summarizes these requirements.



MORE INFORMATION
An important feature of a Visual Basic program is its ability to use dynamically-linked libraries (DLLs) of functions and resources. Because these exported functions are frequently written in other programming languages, care must be taken that both syntax and data types are in the form needed by Visual Basic.

Visual Basic Syntax Requirements
To declare a DLL procedure, add a Declare statement to the Declarations section of the code window. Visual Basic assumes that exported DLL functions have the same attributes as a Windows API function. The correct syntax for a Declare statement is shown below, followed by a list of Visual Basic syntax rules.

Declare Function publicname Lib "libname" [Alias "alias"] _ [(ByVal] var [As type] [,[ByVal] var [As type...])] As Type


 * Public or private: DLL procedures declared in standard modules (.bas) are public by default and can be called from anywhere in your application. DLL procedures declared in any other type of module are private to that module, and must be identified by preceding the declaration with the Private keyword.
 * Sub or function: DLL procedures may be defined as either a Function or Sub. If a procedure does not return a value, write the declare as a Sub. If the procedure returns a value, write the declare as a Function.
 * Using an alias: It is sometimes necessary to define a substitute name for an exported procedure in a Declare statement. Examples of where this can occur are:


 * Where an exported procedure uses strings. This is usually due to the DLL containing both ANSI and UNICODE versions of the procedures.
 * Where an exported function has a name that is not a valid Visual Basic identifier, such as a name that matches a Visual Basic keyword or that begins with an underscore.
 * Case sensitivity: Procedure names are case-sensitive in 32-bit versions of Visual Basic. In 16-bit versions, procedure names are not case-sensitive.
 * Passing arguments by value or by reference: By default, Visual Basic passes all arguments by reference. Many DLL procedures expect an argument to be passed by value. To pass an argument by value, place the ByVal keyword in front of the argument declaration in the Declare statement.
 * Empty argument list: Empty parentheses indicate that the Sub or Function procedure has no arguments and that Visual Basic should ensure that none are passed.

For additional syntax information, see the following topics in Visual Basic Help:


 * Declaring a DLL Procedure
 * Declare Statement
 * Call Statement
 * Function Statement

Visual Basic Data-Type Requirements
Data type definitions vary between programming languages, and some parameters used in other languages are not supported in Visual Basic. To ensure that your exported procedures behave in the way you expect, you may need to append Visual Basic keywords to procedure parameters or convert parameters to those data types supported by Visual Basic.

Common Visual Basic keywords are listed below:


 * Passing a parameter by value or by reference: As discussed above, Visual Basic passes all arguments by reference. To pass a parameter by value, place the ByVal keyword in front of the argument declaration.
 * Passing a function pointer as a parameter: To pass the address of a user-defined procedure as an argument to an exported procedure, precede the name of the user-defined procedure with the AddressOf keyword. For important additional information on this, see the "Passing Function Pointers to DLL Procedures and Type Libraries" Visual Basic Help topic.
 * Modifying data types: Use an As clause following the argument list to specify the return type of the procedure. Use an As clause within the argument list to specify the data type of any of the arguments passed to the procedure. In addition to specifying any of the standard data types, you can specify As Any to inhibit type checking and allow any data type to be passed to the procedure.

Common conversions to Visual Basic data types are listed below:


 * 8- to 16-bit numeric parameters: Pass 8- to 16-bit numeric parameters (int, short, unsigned int, unsigned short, BOOL, and WORD) as Integer.
 * 32-bit numeric parameters: Pass 32-bit numeric parameters (long, unsigned long, and DWORD) as LONG.
 * Object handles: All handles are unique 32-bit integer values associated with a Window and are passed by value, so pass these parameters as Long.
 * Strings: Strings include the LPSTR and LPBYTE data types (pointer to characters or pointer to unsigned characters). Pass these parameters as (ByVal param As String) because Visual Basic passes a pointer to the beginning of the string.
 * Pointers to numeric values: Pass pointers to numeric values by not using the ByVal keyword.
 * Structures: If the Visual Basic user-defined type matches the structure expected by the DLL, the structure can be passed by reference. NOTE: Structures cannot be passed by value.
 * Pointers to arrays: Pass the first element of the array by reference.
 * Null pointers: If a DLL expects a Null pointer, pass it as (ByVal paramname As Any) or (ByVal paramname as Long). You can use 0& as the value of paramname when calling the DLL.

Visual Basic Requirements for Creating Exported DLL Functions
This section provides some information for creating an exported DLL that meets the Visual Basic requirements using Microsoft Visual C++. Other C++ compilers may or may not support the keywords used in this section.

  Maintain the Stack: Visual Basic requires that the function receiving the arguments also maintain the stack. The Visual C++ keyword that can perform the correct stack maintenance is _stdcall. The _stdcall keyword decorates the function name with a preceding underscore and appends "@n" where n is the number of bytes required to contain the function's arguments and the return value. For example, if you create a function called GetWindowSize and use the _stdcall keyword to provide stack maintenance, the function is defined as follows: int GetWindowSize (int nIndex)

The following is the exported name result: _GetWindowSize@4

Note the preceding underscore that is added by the _stdcall keyword.   Export the file: To export the file, you must use a .def file with an EXPORTS section. The _declspec(dllexport) keyword exports the function but maintains the name decoration.

A .def file also exports the function names while removing the name decoration. The following example shows how the EXPORTS section of a .def file is implemented for a function called DisplayMessage:      EXPORTS DisplayMessage          @1



