API functions. API: what it is, how to work and set up integration

It's time to talk about such a concept as API functions in Visual Basic language. Why are these functions important in Visual Basic? Let's figure it out, firstly, when you start programming in Visual Basic, you will immediately understand that using these functions you can write very serious programs, and secondly, you simply cannot do much without using API functions, for example, almost everything related using operating system Windows ( for example: find out the username, hard drive space, etc.).

But in order to start putting these functions into practice, you need to know what they are, let's talk about that first.

Theory on Visual Basic API functions

API is an abbreviation for Application Programming Interface ( application programming interface). In other words, an API is a set of functions that the operating system itself gives the programmer to use in their programs. Using the API, programmers can easily put their ideas into practice.

API functions can be called from Visual Basic to perform tasks for which standard Visual Basic code is not sufficient. For example, standard means Visual Basic does not allow you to shut down your computer or restart it. However, all this can be easily done by calling the appropriate API function.

Almost all functions that are located in Windows are located inside DLLs ( Dynamic Link Library). All dll files are located in the system Windows folder. There are over 1,000 API functions, which fall into four main categories.

  • Working with applications - launching and closing applications, processing menu commands, moving and resizing windows;
  • Graphics - creating images;
  • System information - identification of the current disk, memory size, current user name, etc.;
  • Working with the registry - manipulation of the Windows registry.

Using API functions in practice

Now let's move on to using these functions in practice. API functions called in Visual Basic must first be declared. The declaration specifies the name of the DLL and function, as well as information about the number and type of arguments.

DLL procedures are declared with the Declare command in the General Declarations section of a form module or a standard module:

Declare Function name Lib "library" [([ _ variable [,ByVal,] variable ]...])] As type

DLL procedures found in standard modules are public by default and can be called from anywhere in the application. Procedures declared in a form module are private and must be preceded by the keyword Private.

The Lib section tells you where to look DLL file containing the function. When referring to core Windows libraries (user32.dll, kernel32.dll, gdi.dll), the extension does not need to be included.

If the file path is not specified, then directory browsing begins in the following sequence

  1. The directory containing the program's EXE file;
  2. Current directory;
  3. Windows System Directory;
  4. Windows Directory;
  5. Path environment variable.

Here is a small list of standard Windows DLLs:

  • advapi.dll - NT protection, registry and other advanced services;
  • comdlg.dll - standard dialog boxes;
  • gdi.dll - graphics device interface;
  • kernel32.dll - memory, disks, processes, resources;
  • mpr.dll - networks;
  • netapi32.dll - network API library;
  • shell32.dll - Windows shell, drag-and-drop , icon selection;
  • user32.dll - user interface - windows, menus, lines, messages;
  • version.dll - version control;
  • winmm.dll - multimedia, sound, joysticks, timers;
  • winspoll.dll - print manager.

Most DLL procedures are documented using C and C++ programming language notation. To successfully convert an API function to a Declare command, you must understand the argument passing mechanism. Typically arguments are passed by value. In this case, the ByVal keyword is placed before the argument name. If the argument is passed by reference, then ByRef is set.

Here is the smallest list of functions that are used in Visual Basic:

  • BitBlt - copies an image from one hDC to another;
  • FindWindow - finds the Handle of a window with the specified Caption;
  • GetCursorPos - returns the current position of the mouse cursor (global);
  • GetDriveType - returns the drive type;
  • GetForegroundWindow - returns the Handle of the active window;
  • SetCursorPos - sets the new position of the mouse cursor;
  • SetVolumeLabel - changes the disk label;
  • SetWindowPos - sets the position of a window with a certain Handle (you can also use this function to make the window on TOP of all others);
  • ShellExecute - launches the application associated with the extension that has the specified file (it can also simply launch the specified application);
  • ShowCursor - hides or shows the mouse cursor on the screen.

Examples of working with the registry

Also, when programming in Visual Basic, and in other languages, a problem arises when you need to use Windows registry, but using API functions this is easy to do, for example:

To read a string parameter use the GetRegString function

Example:

Dim test As String test = GetRegString(HKEY_LOCAL_MACHINE, _ "Software\Microsoft\DirectX", "Version") Form1.Caption = test

To read a DWORD parameter GetRegDWord

Example:

Dim test As Long test = GetRegDWord(HKEY_LOCAL_MACHINE, _ "Software\Microsoft\Internet Explorer\AboutURLs", "Home") Form1.Caption = test

To write a string parameter, use SetRegString

Example:

SetRegString HKEY_LOCAL_MACHINE, _ "Software\test", "MyProgram", "Options"

If the key or parameter has not been created, then it will be created; if the key or parameter already exists, then the new values ​​will be written over the old ones.

To write a DWORD type parameter, use SetRegDWord

Example:

SetRegDWord HKEY_LOCAL_MACHINE, _ "Software\test", "MyProgram", "555"

To remove a key from the registry, use the DeleteRegKey function

Example:

DeleteRegKey HKEY_LOCAL_MACHINE, "Software", "test", True

Second parameter - Parent key
The third parameter is True - if confirmation for deletion is required, or False - if confirmation is not required.

To remove a value from the registry, use the DeleteRegValue function

Example:

DeleteRegValue HKEY_LOCAL_MACHINE,_ "Software\Microsoft\Internet Explorer\AboutURLs", "mozilla", False

In fact, the possibilities of API functions in the Windows operating system are almost limitless. Let's finish looking at this Visual Basic feature and finally write a small program using API functions.

This program simply displays a message on the screen, paste the following code:

Private Declare Function BeginPath Lib "gdi32" (ByVal hdc As Long) As Long Private Declare Function EndPath Lib "gdi32" (ByVal hdc As Long) As Long Private Declare Function PathToRegion Lib "gdi32" (ByVal hdc As Long) As Long Private Declare Function SetWindowRgn Lib "user32" (ByVal hWnd As Long, ByVal hRgn As Long, ByVal bRedraw As Boolean) As Long Private Sub Form_Load() Const TEXT = "You used the API" Dim hRgn As Long Font.Name = "Times New Roman" Font.Bold = True Font.Size = 60 Width = TextWidth(TEXT) Height = TextHeight(TEXT) BeginPath hdc Print TEXT EndPath hdc hRgn = PathToRegion(hdc) SetWindowRgn hWnd, hRgn, False Move (Screen.Width - Width) / 2 , (Screen.Height - Height) / 2 End Sub

Here we used 4 functions (BeginPath, EndPath, PathToRegion, SetWindowRgn), which are located in two dll libraries(gdi32, user32).

That's all for now!

An API is an external interface for programming an application, accessing sites using a specific protocol to obtain information and simplified development of programs associated with internal services.

What does API mean?

The simplest analogy for using an API would be to use a calculator to perform complex calculations. Let's say you have a task, you can understand its essence, build equations and graphs, but you do not know how to perform arithmetic operations with numbers. There is a calculator next to you that can do these operations with ease. You don't know what's going on inside the computer, and you don't need to know. You give information in one form, and receive it in another, necessary for your purposes.

Any API works on this principle. You don’t care how the program gets the answer, what path the request takes inside it, how the calculations are performed. You are sure of only one thing - in response, standardized information will be given about the success of the operation or its error.

The API interface allows you not to waste your time, money and effort on buying a “new bike”. You get a working information port that receives and sends the necessary amounts of data for the purposes of your development.

Pros:

  • Saving on developing your own interface.
  • There is no need to understand the nuances of the issue.
  • APIs are developed by professionals and take into account all the factors of internal processes that you may not be aware of when creating your solution.
  • Allows you to communicate with services that are closed through other protocols.

Minuses:

  • If the target service is updated, the API does not always immediately receive full functionality.
  • You can't catch errors and don't know how the process works in someone else's code.
  • The API does not always give the most optimized result in terms of time, since it is designed to handle general cases, not specific ones.

API Examples

API integration is the process of connecting an application to an external data interface. Working with the API begins with studying the documentation and protocols used, and then directly integrating your program into the interface. Let's look at the most popular services that have their own API.

VKAPI

External interface for interaction of the popular social network VKontakte with clients, as well as with browser and server applications. Allows you to manage community messages, group covers, user pages if you have the appropriate access keys.

All requests are made to the address https://api.vk.com/method/

After the slash comes the name of the API method used and the GET parameters of the request are transmitted. The response also comes via HTTPS in JSON format.

TELEGRAM BOT API

One of the most popular APIs. It is used to control bots in the Telegram messenger. After creating a bot via @botfather and obtaining the necessary access keys, you can begin interacting with the backend.

Requests can be made to: https://api.telegram.org/bot0000000:token/

Where bot0000000 is replaced by the unique identifier of your bot, and token expresses the secret key.

Requests are sent via HTTPS connections, the method name is indicated with a slash to the main address. The response comes in JSON format.

OPEN WEATHER MAP API

It is often necessary to obtain weather information without using third-party widgets and paid applications. The OpenWeatherMap service comes to the rescue with an open and free API. After registering and receiving identification data, you can send weather requests from server scripts around the world. In response to the city ID, the resource returns the maximum detailed information about the current weather and gives a forecast for the near future.

Format: HTTP transmission via api.openweathermap.org/data/2.5/weather?id= indicating the identification number of the desired city. Server response: JSON.

GOOGLE MAPS API

What could be nicer than an interactive world map on a website? Especially if this is not a template insert from Google Maps, but your personal edition of a popular map with personal clusters of markers. The map will interact with other scripts on the site, sending information about clicks and coordinates.

Offers similar opportunities JavaScript API Google Maps. The module is completely scripted and works on the browser side, so we don’t need HTTP requests from PHP and the formation of headers on the server side, as was the case in other APIs.

For example, placing a marker on a map will look like this:

var mark = new google.maps.Marker((
position: myPOS,
map: map,
title:"Hello!"
});

What is the need and benefits of using the API?

There are quite a lot of useful functions.

First aspect

You can establish interactive user interaction with social networks and messengers, use the capabilities of third-party computing systems to display exchange rates, weather and other important information.

Using the API, you can instantly connect other resources and software solutions to servers, which would normally take weeks of development. The API simplifies life where a unique implementation is not needed, and reliability and security are a priority.

Second aspect

If you are the owner of complex computing power, a popular service or data warehouse for public or semi-private access, then a good move would be to raise your own API. What will it give:

  • Large flow of clients.
  • Simplified access to your services for partners.
  • Convenience of statistical analysis of service use.

Third aspect

Almost the same as the second one. But without having to implement an open access API. If you have a portal and you want to create a mobile application for it on Android/IOS, then rewrite the system under a single API - The best decision. The entire data structure is systematized. The site and application will operate through single data channels.

Let's start with the basics: what is an API? The abbreviation stands for Application Programming Interface, or interface for application programming. The name seems to speak for itself, but it’s better to consider a more detailed explanation.

As already mentioned, an API is, first of all, an interface. An interface that allows developers to use ready-made blocks to build an application. In the case of developing mobile applications, a library for working with a smart home can act as an API - all the nuances are implemented in the library and you only access this API in your code.

In the case of web applications, the API can return data in a format other than standard HTML, making it convenient to use when writing your own applications. Third-party public APIs most often serve data in one of two formats: XML or JSON. In case you decide to make an API for your application, remember that JSON is much more concise and easier to read than XML, and services that provide access to data in XML format are gradually abandoning the latter.

API in web applications with examples

An application - for example, Github - has its own API that other developers can use. How they will use it depends on the capabilities that the API provides and on how well the developers’ imagination works. The GitHub API allows, for example, to obtain information about the user, his avatar, readers, repositories and many other useful and interesting information.

In a similar way, you can send a request in any language, including Ruby. The response to the request will be approximately the following information:

( "login" : "Freika" , "id" : 3738638, "avatar_url" : "https://avatars.githubusercontent.com/u/3738638?v=3", "gravatar_id" : "" , "url" : "https://api.github.com/users/Freika", "html_url" : "https://github.com/Freika" , "followers_url" : "https://api.github.com/users/Freika/followers", "following_url" : "https://api.github.com/users/Freika/following(/other_user)", "gists_url" : "https://api.github.com/users/Freika/gists(/gist_id)", "starred_url" : "https://api.github.com/users/Freika/starred(/owner)(/repo)", "subscriptions_url" : "https://api.github.com/users/Freika/subscriptions", "organizations_url" : "https://api.github.com/users/Freika/orgs", "repos_url" : "https://api.github.com/users/Freika/repos", "events_url" : "https://api.github.com/users/Freika/events(/privacy)", "received_events_url" : "https://api.github.com/users/Freika/received_events", "type" : "User" , "site_admin" : false , "name" : "Evgeniy" , "company" : "" , "blog" : "http://frey.su/" , "location" : " Barnaul" , "email" : "" , "hireable" : true , "bio" : null, "public_repos" : 39, "public_gists" : 13, "followers" : 15, "following" : 21, "created_at" : "2013-03-01T13:48:52Z" , "updated_at" : "2014-12-15T13:55:03Z" )

As can be seen from the block above, the response contains the login, avatar, link to the profile on the site and in the API, user status, number of public repositories and other useful and interesting information.

API alone is not enough

Creating a full-fledged API for your application is only half the battle. How are you supposed to access the API? How will your users access it?

The first thing that comes to mind is the usual series of HTTP requests in order to receive necessary information, and this is the wrong answer. The most obvious method in this case is not the most convenient and simple. It would be much more reasonable to create a special library for working with the interface, which will describe everything necessary methods receiving and sending information using the API.

Let’s use Github once again to give an example: to work with the API of this excellent service (and its interface provides extensive capabilities), several libraries have been created in various languages, for example the Octokit gem. In the documentation for such libraries (and the gem given as an example), any interested developer will be able to find all the necessary ways to receive information from Github and send it back through the service API.

Thus, if you are creating your own API, consider perhaps creating libraries to work with it in the most common languages. And be prepared that at a certain level of demand for your application, someone else may create their own library to work with your API. This is fine.

useful links

In subsequent articles we will talk about how to correctly create an API, ensure its security and limit access to some information.

You've probably seen the term "API". Operating system, web browser, and application updates frequently announce new APIs for developers. But what is an API?

Application Programming Interface

The term API is an acronym and it stands for Application Programming Interface.

An API is like a menu in a restaurant. The menu contains a list of dishes that you can order, as well as a description of each dish. When you specify which menu items you want, the restaurant kitchen does the job and provides you with the finished dishes. You don't know exactly how the restaurant prepares this food, and you don't need to.

Likewise, the API provides many operations that developers can use, as well as a description of what they do. The developer does not need to know how, for example, the operating system is created and the Save As dialog box is displayed. They just need to know that it is available for use in the application.

This isn't a perfect metaphor as developers may have to provide their own API data to get results, so perhaps it's more like a fancy restaurant where you can provide some of your own ingredients for the kitchen to work with.

APIs allow developers to save time by taking advantage of platform implementation to perform important work. This helps reduce the amount of code to develop and also helps create consistency between applications on the same platform. APIs can control access to hardware and software resources.

APIs make life easier for developers

Let's say you want to develop an iPhone application. operating system Apple iOS provides a large number of APIs are like any other operating system to make this easier for you.

For example, if you want to embed a web browser to display one or more web pages, you don't have to program your own web browser from scratch just for your application. You
You can use the WKWebView API to embed a WebKit (Safari) web browser into your application.

If you want to take photos or videos from iPhone cameras You don't need to write your own camera interface. You can use the Camera API to embed the iPhone camera into your app. If the API didn't exist, app developers would have to create their own camera software and interpret the inputs hardware cameras. But Apple's operating system developers have done all that hard work, so developers can simply use the camera API to embed the camera and then continue writing their app. And when Apple improves the camera API, all apps that use it will automatically take advantage of that improvement.

This applies to all platforms. For example, do you want to create a dialog box in Windows? There is an API for this. Want to support fingerprint authentication on Android? There's an API for this, so you don't have to test every fingerprint sensor from every Android manufacturer. Developers don't have to reinvent the wheel over and over again.

APIs control access to resources

APIs are also used to control access to hardware devices and software features that the application may not have permission to use. This is why APIs often play a big role in security.

For example, if you have ever visited a website and seen a message in your browser that the website is asking for your exact location, that website is attempting to use the geolocation API in your web browser. Web browsers provide APIs to make it easy for web developers to access your location - they can simply ask "where are you?" and the browser will do the hard work of accessing your GPS or nearby Wi-Fi networks to find your physical location.

However, browsers also expose this information through APIs because access to it can be controlled. When a website wants to access your exact location, the only way get it through the location API. And, when a website tries to use it, you—the user—can allow or deny the request. Hardware resources such as a GPS sensor can only be accessed through an API, so the browser can control access to the hardware and limit what apps can do.

The same principle is used for modern mobile operating systems such as iOS and Android, where mobile applications have permissions that can be enforced by controlling access to the API. For example, if a developer tries to access the camera through the camera API, you can deny the permission request and the app will not have access to your device's camera.

File systems that use permissions, like Windows, Mac, and Linux, have those rights that are enforced by the file system API. A typical application does not have direct access to a raw physical hard drive. Instead, the application must access the files through the API.

APIs are used for communication between services

APIs are also used for other reasons. For example, if you have ever seen a Google Maps object embedded on a website, that website uses the Google Maps API to embed that map. Google provides APIs like these for web developers, who can then use the APIs to assemble complex objects directly on their website. If no such APIs exist, developers may have to create their own maps and provide their own map data in order to host a small interactive map on a website.

And since it's an API, Google can control access to Google Maps on third party websites, ensuring that they use it in a consistent manner rather than trying to randomly implement a frame that the Google Maps website shows, for example.

This applies to many different online services. There are APIs for requesting a translation of text from Google Translate or displaying Facebook comments or Twitter tweets on a website.

The OAuth standard also defines a number of APIs that allow you to log into a site through another service, such as using your login credentials. Facebook posts, Google or Twitter to log into a new website without creating a new one account user only for this site. APIs are standard contracts that define how developers interact with a service and the type of output that developers should expect to receive.

If you have read this article, you will have a better idea of ​​what an API is. Ultimately, you don't need to know what an API is unless you're a developer. But, if you see that the software platform or service has added new APIs for different hardware or services, it should be easier for developers to use such features.

Windows API - a set of operating system functions

The abbreviation API seems very mysterious and even scary to many novice programmers. In fact, an Application Programming Interface (API) is just some ready-made set of functions that application developers can use. IN general case This concept is equivalent to what used to be more often called a subroutine library. However, API usually refers to a special category of such libraries.

During the development of almost any fairly complex application (MyApplication) for the end user, a set of specific internal functions is formed that are used to implement this particular program, which is called the MyApplication API. However, it often turns out that these functions can be effectively used to create other applications, including by other programmers. In this case, the authors, based on the strategy for promoting their product, must decide the question: do they open access to this set for external users or not? If the answer is yes, the phrase “The package includes an open set of API functions” appears in the description of the software package as a positive characteristic (but sometimes for additional money).

Thus, most often an API refers to a set of functions that are part of one application, but are also available for use in other programs. For example, Excel, in addition to its end-user interface, has a set of Excel API functions that can be used, in particular, when creating applications using VB.

Accordingly, the Windows API is a set of functions that is part of the operating system itself and at the same time accessible to any other application, including those written using VB. In this regard, the analogy with the BIOS/DOS system interrupt set, which is actually a DOS API, is quite justified.

The difference is that the range of Windows API functions, on the one hand, is much broader compared to DOS, and on the other hand, it does not include many of the tools for directly managing computer resources that were available to programmers in the previous OS. In addition, calls to the Windows API are performed using ordinary procedural calls, and calls to DOS functions are performed through a special processor instruction called Interrupt.

Why do we need Win API for VB programmers?

Despite the fact that VB has a huge variety of functions, in the process of more or less serious development it is discovered that their capabilities are often not enough to solve the necessary problems. At the same time, newbie programmers often begin to complain about the shortcomings of VB and think about changing tools, not suspecting that their computer has a huge set of tools and they just need to know how to use them.

When getting acquainted with the Win API, it is discovered that many built-in VB functions are nothing more than calls to the corresponding system procedures, but only implemented in the form of the syntax of a given language. Taking this into account, the need to use the API is determined by the following options:

  1. API functions that are fully implemented as built-in VB functions. Nevertheless, sometimes in this case it is useful to switch to using the API, since this can sometimes significantly improve performance (in particular, due to the absence of unnecessary transformations of passed parameters).
  2. Built-in VB functions implement only a special case of the corresponding API function. This is a fairly common option. For example, the CreateDirectory API function has more capabilities than the built-in VB MkDir operator.
  3. A huge number of API functions have no analogues at all in the current version of the VB language. For example, you cannot delete a directory using VB - to do this you need to use the DeleteDirectory function.

It should also be emphasized that some API functions (their share in the Win API is very small) cannot be called from VB programs due to a number of language limitations, for example, due to the inability to work with memory addresses. But in some cases, non-trivial programming techniques can help (in particular, in the case of the same addresses).

The author's personal point of view is that instead of expanding the built-in functions from version to version, VB should have been given good description the most popular API functions. At the same time, I would like to advise developers not to wait for the appearance new version tools with advanced functions, and take a closer look at the composition of the existing Win API - it is likely that the capabilities you need could have been implemented already in version VB 1.0, released in 1991.

How to learn Win API

This is not such a simple question, considering that the number of Win32 API functions is estimated at about 10 thousand (no one knows the exact figure, not even Microsoft).

VB (versions 4-6) includes a file describing Win API declarations - WIN32API.TXT (we will tell you more about its use later). But, firstly, with its help you can obtain information about the purpose of a particular function and its parameters only by the mnemonic names used, and secondly, the list of functions in this file is far from complete. At one time (seven years ago), VB 3.0 had special help files describing the functions of the Win16 API. However, already in v.4.0 this useful information with a convenient interface disappeared.

Comprehensive information about the Win32 API can be found in the Platform Software Development Kit help, which is included in the MSDN Library CDs included with VB 5.0 and 6.0 Enterprise Edition and Office 2000 Developer Edition. However, finding the necessary information there and understanding it is not at all easy. Not to mention that all the descriptions there are given in relation to the C language.

The books of the famous American expert Daniel Appleman are generally recognized in the world for learning API programming in the VB environment. His Dan Appleman's Visual Basic Programmer's Guide to the Windows API series (for Win16, Win32, and various versions of VB) has been one of the best-selling books for VB programmers since 1993. The book Dan Appleman’s VB 5.0 Programmer’s Guide to the Win32 API, released in 1997, was brought to the author from the USA by a friend who found it in the first bookstore of a small provincial town.

This book is over 1,500 pages long, covering general API programming techniques in VB, as well as over 900 functions. The accompanying CD contains the full text of the book and all program examples, and in addition, several additional chapters that were not included in the printed version. In 1999, Dan Appleman released a new book, Dan Appleman's Win32 API Puzzle Book and Tutorial for Visual Basic Programmers, which includes information on another 7,600 functions (though not as extensive).

Win API and Dynamic Link Library (DLL)

The Win API set is implemented in the form of dynamic DLLs. Next, we will actually talk about the technology of using DLLs in the VB environment using the example of libraries included in the Win API. However, when talking about DLLs, there are a few important points to make.

In this case, by DLL we mean the traditional version of binary dynamic libraries, which provide applications with direct access to the necessary procedures - subroutines or functions (in much the same way as what happens when calling procedures inside a VB project). Such libraries can be created using different tools: VC++, Delphi, Fortran, except VB (let's see what appears in version 7.0) - the latter can only create ActiveX DLLs, accessed through the OLE Automation interface.

Typically dynamic library files have the extension .DLL, but this is not at all necessary (for Win16 the extension .EXE was often used); drivers external devices are indicated by .DRV.

As we have already noted, it is quite difficult to determine the exact number of Windows API functions and the files that contain them, but they are all located in the system directory. In this regard, it is better to highlight the composition of the libraries included in the operating system kernel and the main libraries with key additional functions.

And now some tips.

Tip 1. Make sure your DL ad is formatted correctly L-procedures

The very call to DLL procedures in a program looks exactly the same as to “regular” Visual Basic procedures, for example:

Call DllName([argument list])

However, to use external DLL functions (including Win API), they must be declared in the program using the Declare statement, which looks like this:

Declare Sub ProcedureName Lib _ “LibraryName” _ [([ArgumentList])]

Declare Function FunctionName _ Lib “LibraryName” _ [([ArgumentList])]

Here, optional elements of the operator are shown in square brackets, variable expressions are in italics, and the remaining words are key words. The help system gives a fairly good description of the syntax of the operator, so for now we will only note a few points.

Declarations of external functions should be placed in the General Declarations section of the module. If you place it in a form module, then you must specify the Private keyword (this declaration will only be available inside this module) - this is a limitation for all form module procedures.

The Win32 API set is implemented only in the form of functions (the Win16 API had many Sub routines). For the most part, these are functions of the Long type, which most often return the completion code of the operation.

The Declare operator appeared in MS Basic back in the days of DOS, and it was also used to declare internal project procedures. In Visual Basic this is not required, since the declaration of internal procedures is automatically their Sub or Function declaration. Compared to Basic/DOS, the new description must indicate the name of the library file where the required procedure is located. Wip API libraries are located in the Windows system directory, so it is enough to provide only the file name. If you are accessing a DLL that is located in a random location, you need to write down the full path to this file.

The description of the Declare statement usually takes up quite a lot of space and does not fit on one line in the code window. Therefore, we recommend that you adhere to a specific line-breaking scheme when writing applications, for example:

Declare Function GetTempPath _ Lib “kernel32” Alias ​​“GetTempPathA” _ (ByVal nBufferLength As Long, _ ByVal lpBuffer As String) As Long

In this case, all the main elements of the description are placed on different lines and are therefore easy to read.

Tip 2: Be especially careful when working with DLL functions

The use of the Win API and various DLL functions significantly expands the functionality of VB and often improves program performance. However, the price to pay for this is the risk of reducing the reliability of the application, especially during its debugging.

One of the most important advantages of the VB environment is the reliability of the program development process: operating under the control of an interpreter, program code theoretically cannot violate Windows operation and VB itself. The programmer may not be very careful about the correctness of passing parameters to called functions - such errors will be easily detected by the interpreter itself either during the process of translating the code or during its execution. In the most unpleasant case, the processing mode will simply be interrupted, with an indication of where and why the error occurred.

Using Windows API functions or other DLLs directly removes such control over the transfer of data and the process of code execution outside of the VB environment. Therefore, an error in accessing external functions can lead to inoperability of both VB and the operating system. This is especially true at the stage of program development, when the presence of errors is quite natural. Thus, by using the broader capabilities of the functions of the base layer of the system, the programmer takes responsibility for the correct use of them.

The problem is further aggravated by the fact that different programming languages ​​use different ways of passing parameters between procedures. (More precisely, different ways passing is the default, since many languages ​​can support multiple methods.) The Win APIs are implemented in C/C++ and use that system's parameter passing conventions, which differ from the usual VB version.

In this regard, it should be noted that the appearance of analogues of API functions built into VB is justified precisely by the adaptation of the latter to the VB syntax and the implementation of an appropriate data exchange control mechanism. Let us also note that at the stage of experimental debugging of the application when creating an executable module, it is better to use the P-code compilation option instead of Native Code (machine code). In the first case, the program will run under the control of an interpreter - slower compared to machine code, but more reliable from the point of view of possible erroneous impact on the operating system and providing a more convenient mode for identifying possible errors.

Tip 3: Dan Appleman's Ten Tips for Robust API Programming in VB

Using the API function requires more careful programming using some less familiar procedure call techniques (compared to VB). We will continue to address these issues in the following. And now we present a summary of the advice formulated by Dan Appleman on this topic (their first version appeared back in 1993) with some of our additions and comments.

1. Remember ByVal. The most common mistake made when accessing API and DLL functions is incorrect use keyword ByVal: people either forget to install it, or, conversely, install it when there is no need for it.

These examples show the impact of the ByVal operator on parameter passing

Parameter type With ByVal Without ByVal
Integer A 16-bit integer is pushed onto the stack The 32-bit address of a 16-bit integer is pushed onto the stack
Long A 32-bit integer is pushed onto the stack The 32-bit address of a 32-bit integer is pushed onto the stack
String The string is converted to the format used in C (data and a terminating null byte). The 32-bit address of the newline is pushed onto the stack The VB handle to the string is pushed onto the stack. (Such handles are never used by the Windows API itself and are only recognized in DLLs implemented specifically for VB.)

It should be recalled here that passing parameters to any programming system, including VB, is executed in two main ways: by reference (ByRef) or by value (ByVal). In the first case, the address of the variable is passed (this option is used by default in VB), in the second - its value. The fundamental difference is that using a reference, the changed value of the passed parameter is returned to the calling program.

To understand this, conduct an experiment using the following programs:

Dim v As Integer v = 2 Call MyProc(v) MsgBox “v = “ & v Sub MyProc (v As Integer) v = v + 1 End Sub

When you run this example, you will receive a message with variable value, equal to 3. The fact is that in this case the address of the variable v, physically created in the calling program, is passed to the MyProc subroutine. Now change the procedure description to

Sub MyProc (ByVal v As Integer)

As a result, when executing the test, you will get v = 2, because only the initial value of the variable is passed to the procedure - the result of operations performed with it is not returned to the calling program. The transfer mode by value can also be changed using the Call operator as follows:

Sub MyProc (v As Integer) ... Call MyProc((v)) ‘ (v) - parentheses indicate the transfer mode by value.

However, when accessing internal VB procedures, the use of the ByVal keyword in the Call statement is prohibited - parentheses are used instead. There is an explanation for this.

In the classical case (C, Fortran, Pascal), the difference between the ByRef and ByVal modes depends on what exactly is placed on the data exchange stack - the address of the variable or its value. Basic historically uses a variant of ByVal software emulation - there is always an address on the stack, but only when passing by value a temporary variable is created for this. To distinguish between these two options (Classic and Basic), different ways of describing the ByVal mode are used. Note that emulating the ByVal mode in VB provides higher program reliability: by mixing up the form of reference, the programmer risks only that the corrected value of the variable will be returned (or not returned) to the calling program. In the “classical” version, such confusion can lead to a fatal error when executing a procedure (for example, when a variable value equal to, say, zero, is used instead of a memory address).

DLL functions are implemented according to “classical” principles and therefore require a mandatory description of how data is exchanged with each of the arguments. Function declarations through the Declare description (more precisely, the list of passed arguments) serve this purpose. The most common way to pass parameters to a Windows API function or DLL is to use the ByVal keyword. Moreover, it can be specified both in the Declare operator and directly when calling the function.

The consequences of incorrect parameter passing are easy to predict. If you receive an obviously invalid address, you will receive a GPF (General Protection Fault) message. If the function receives a value that matches a valid address, then the API function will enter a foreign area (for example, the Windows kernel) with all the ensuing disastrous consequences.

2. Check the type of parameters being passed. The correct number and type of parameters passed are equally important. It is necessary that the arguments declared in Declare match the expected parameters in the API function. The most common case of error in parameter passing involves the difference between NULL and a zero-length string - remember that these are not the same thing.

3. Check the return type.

VB is fairly tolerant of return type mismatches function of values, since numeric values ​​are usually returned via registers rather than via the stack. The following rules will help determine the correct value returned by an API function:

  • A DLL function that does not return a value (analogous to void in 'C') must be declared as a VB Sub.
  • An API function that returns an integer value (Integer or Long) can be defined as either a Sub or a Function that returns a value of the appropriate type.
  • None of the API functions return floating point numbers, but some DLLs may well return this type of data.

4. Use the “As Any” construction with great care. Many Windows API functions have the ability to accept parameters of different types and use the As Any construct to do so (type interpretation is performed depending on the value of other parameters passed).

A good solution in this case may be to use several aliases (Alias) of a function by creating two or more declarations for the same function, with each declaration specifying parameters of a specific type.

5. Don't forget to initialize the strings. There are many functions in the Win API that return information by loading data into string buffers passed as a parameter. In your program, you can seemingly do everything correctly: don’t forget about ByVal, pass parameters to the function correctly. But Windows cannot check how large the size of the memory allocated for a row is. The row size must be large enough to accommodate all the data that can be placed in it. Responsibility for reserving a buffer of the required size lies with the VB programmer.

It should be noted that in 32-bit Windows, when using strings, conversion is carried out from Unicode (double-byte encoding) to ANSI (single-byte encoding) and back, taking into account the national system settings. Therefore, to reserve buffers, it is sometimes more convenient to use byte arrays instead of string variables. (More on this below.)

Most often, Win API functions allow you to define the maximum block size yourself. In particular, sometimes this requires calling another API function that will “tell” the block size. For example, GetWindowTextLength allows you to determine the length of the string needed to hold the window title returned by the GetWindowText function. In this case, Windows ensures that you don't go overboard.

6. Be sure to use Option Explicit.

7. Carefully check parameter values ​​and return values. VB has good type checking capabilities. This means that when you try to pass an invalid parameter to a VB function, the worst that can happen is that you get an error message from VB. But this mechanism, unfortunately, does not work when accessing Windows functions API.

Windows 9x has improved parameter checking for most API functions. Therefore, the presence of an error in the data usually does not cause a fatal error, but determining what caused it is not so easy.

Here we recommend using several ways to debug this type of error:

  • use step by step mode debugging or the Debug.Print command to check each suspicious API function call. Check the results of these calls to make sure everything is normal and the function completed correctly;
  • use a Windows debugger like CodeView and a debugger Windows version(available in Windows SDK). These tools can detect a parameter error and at least determine which API function is causing the error;
  • Use additional third-party tools to check parameter types and the validity of their values. Such tools can not only find parameter errors, but even point to the line of VB code where the error occurred.

In addition, it is necessary to check the result of executing the API function.

8. Remember that integers in VB and in Windows are not the same thing. First of all, you should keep in mind that the term “Integer” in VB means a 16-bit number, while in the Win 32 documentation it means a 32-bit number. Secondly, integers (Integer and Long) in VB are signed quantities (that is, one digit is used as the sign, the rest as the mantissa of the number), in Windows only non-negative numbers are used. This circumstance must be kept in mind when you form the passed parameter using arithmetic operations(for example, calculate the address by summing some base and offset). The standard VB arithmetic functions are not suitable for this. We will discuss what to do in this case separately.

9. Pay close attention to function names. Unlike Win16, the names of all Win32 API functions are sensitive to the exact use of lowercase and uppercase letters (this was not the case in Win16). If you somewhere use a lowercase letter instead of an uppercase one or vice versa, then required function will not be found. Also be careful to use the A or W suffix correctly in functions that use string parameters. (For more on this, see below.)

10. Save your work often. Errors associated with incorrect use of DLLs and Win APIs can lead to an emergency termination of the VB environment, and possibly the entire operating system. You should ensure that the code you write is saved before the test run. The simplest thing is to set the mode for automatic recording of project modules before starting the project in the VB environment.

After reading the previous advice, you may think that using Win API functions is risky. To some extent this is true, but only in comparison with the safe programming provided by VB itself. But with skillful use and knowledge of possible pitfalls, this risk is minimal. In addition, it is often simply impossible to completely abandon the use of Win API - they will still be required for any serious development.

In addition, we previously mentioned the pitfalls for a wide class of DLLs. In the case of the Win API, everything is much simpler, since the form for accessing these functions is clearly unified. The following main points should be kept in mind:

  1. Win32 API functions are just that: functions, that is, procedures of the Function type (there were many Sub routines in the Win16 API). All these are functions of the Long type, so their descriptions are written in the following form: Declare Function name ... As Long ‘function type _ is defined explicitly

    Declare Function name& ‘ function type _ is determined using the suffix

    The call to the API function looks like this:

Result& = ApiName& ([ ArgumentList]
  1. Most often, the return value of a function is the completion code of the operation. Moreover, a non-zero value in this case means normal completion, zero means an error. Usually (but not always) you can clarify the nature of the error by calling the GetLastError function. The description of this function looks like this: Declare Function GetLastError& Lib “kernel32” ()

    ATTENTION! When working in VB, it is better to use the LastDLLError property of the Err object to get the value of the qualified error code, since VB sometimes resets the GetLastError function between calling the API and continuing to execute the program.

    You can interpret the code returned by GelLastError using constants written in the API32.TXT file, with names starting with the ERROR_ suffix.

    The most common mistakes are following codes:

    • ERROR_INVALID_HANDLE = 6& - invalid handle
    • ERROR_CALL_NOT_IMPLEMENTED = 120& - calling a function in Windows 9x that is only available for Windows NT
    • ERROR_INVALID_PARAMETER = 87& - incorrect value parameter

    However, many functions return the value of some requested parameter (for example, OpenFile returns the value of the file handle). In such cases, the error is determined by some other special Return& value, most often 0 or –1.

  2. Win32 APIs use strictly fixed ways to transfer the simplest data types. a) ByVal...As Long

    By using type variables Long performs at least 80% of argument passing. Note that the argument Always is accompanied by the ByVal keyword, and this, among other things, means that a one-way data transfer is performed - from the VB program to the API function.

    B) ByVal...As String

    This type of data transfer also occurs quite often, and with the argument also Always ByVal applies. When an API function is called, the address of the string is written to the stack, so in this case two-way data exchange is possible. There are several dangers to be aware of when working with strings.

    The first is that memory reservation for a string is made in the calling program, so if the API function will fill strings, then you need to create a string of the required size before calling it. For example, the GetWindowsDirectory function returns the path to Windows directory, which by definition should not take more than 144 characters. Accordingly, calling this function should look something like this:

    WinPath$ = Space$(144) ‘ reserve a string of _ 144 characters Result& = GetWindowsDirectory& (WinTath$, 144) _ ‘ fill the buffer ‘ Result& - the actual number of characters in the _ directory name WinPath$ = Left$(WinPath, Result&)

    The second problem is that when calling an API function, the source string is converted to some internal representation, and when exiting the function, vice versa. If in the days of Win16 this operation consisted only of adding a zero byte at the end of the line, then with the advent of Win32 this was added to the transformation of the double-byte Unicode encoding to ANSI and vice versa. (This was discussed in detail in the article “Features of working with string variables in VB”, ComputerPress 10’99 and 01’2000). For now, let's just note that using the ByVal ... As String construct, you can exchange strings with only character data.

    B) ...As Any

    This means that some memory buffer address will be pushed onto the stack, the contents of which will be interpreted by the API function, for example, depending on the value of other arguments. However, As Any can only be used in the Declare statement - when a specific function is called, a specific variable must be defined as an argument.

    D) ... As UserDefinedType

    This design is also often used when it is necessary to exchange data (generally in both directions) using some structure. In fact, this construction is a kind of concrete implementation of the As Any transmission form, it’s just that in this case the function is configured to a fixed structure.

    The form of the data structure is determined by the specific API function, and it is the programmer's responsibility to properly describe and reserve it in the calling program. This design Always used without words ByVal, that is, in this case, transfer by reference is performed - the address of the variable is written to the stack.

Example of calling an API function

Let's illustrate the above using the example of using two useful functions for working with files - lopen and lread, which are described as follows:

Declare Function lopen Lib “kernel32” _ Alias ​​“_lopen” (_ ByVal lpFileName As String, _ ByVal wReadWrite As Long) As Long Declare Function lread Lib “kernel32” _ Alias ​​“_lread” (_ ByVal hFile As Long, lpBuffer As Any, _ ByVal wBytes As Long) As Long

In VB, their analogues - in this case exact ones - are the Open and Get operators (for Binary mode). Let us immediately pay attention to the use of the Alias ​​keyword in a function declaration - this is exactly the case when you cannot do without it. Actual function names in the library begin with an underscore (typical C language style), which is not allowed in VB.

The file opening operation might look like this:

Const INVALID_HANDLE_VALUE = -1 ' incorrect _ descriptor value lpFileName$ = “D:\calc.bas” ' file name wReadWrite& = 2 ' read-write mode hFile& = lopen(lpFileName$, wReadWrite&) _ ' define the file descriptor If hFile& = INVALID_HANDLE_VALUE Then _ ' error opening the file ' specify the error code CodeError& = Err.LastDllError 'CodeError& = GetLastError _ ' this construction does not work End If

Here you need to pay attention to two points:

  • as the value of the function we get the value of the file descriptor. The error corresponds to a value of –1;
  • It is precisely in this case that calling the GetLastError function does not work - to obtain a refined error value, we turned to the Err object (we talked about the possibility of such a situation above).

The contents of the file can then be read, but this assumes that the programmer must have some understanding of its structure (just as is the case when working with arbitrary binary files). In this case, calling the lread function might look like this:

Dim MyVar As Single wBytes = lread (hFile&, MyVar, Len(MyVar) ' reading a real number, 4 bytes ' wBytes is the number of data actually read, ' -1 is an error... Type MyStruct x As Single i As Integer End Type Dim MyVar As MyStruct wBytes = lread (hFile&, MyVar, Len(MyVar)) ' read data structure, 6 bytes

Please note again: the second argument to the function is passed by reference, the rest are passed by value.

Dim MyVar As String MyVar = Space$(10) ‘reserve a variable for 10 characters wBytes = lread (hFile&, ByVal MyVar, Len(MyVar)) ‘ read character string, 10 characters

Here you can see an important difference from the previous example - the string variable is necessarily accompanied by the ByVal keyword.

Reading the contents of a file in an array (for simplicity, we will use a one-dimensional byte array) is done as follows:

Dim MyArray(1 To 10) As Byte wBytes = lread (hFile&, MyArray(1), _ Len(MyArray(1))* 10) ‘ read 10 array elements

By specifying the first element of the array as an argument, we are passing the address of the beginning of the memory area reserved for the array. Obviously, you can fill any fragment of an array in this way:

WBytes = lread (hFile&, MyArray(4), _ Len(MyArray(1))* 5) ‘ read array elements 4 to 8

Tip 5: Use Alias ​​for Gears and parameters As Any

Here, based on the previous example, we will reveal the essence of Dan Appleman's fourth tip.

When working with the lread function, you should remember that when accessing it using a string variable, you must use the ByVal keyword (otherwise you will receive messages about an illegal operation). To protect yourself, you can make an additional special description of the same function to work only with string variables:

Declare Function lreadString Lib “kernel32” _ Alias ​​“_lread” (_ ByVal hFile As Long, ByVal lpBuffer As String, _ ByVal wBytes As Long) As Long

When working with this description, you no longer need to specify ByVal when contacting:

WBytes = lreadString(hFile&, MyVarString, _ Len(MyVarString)) ‘

It would seem that the syntax of the Declare operator allows you to make a similar special description for an array:

Declare Function lreadString Lib “kernel32” Alias ​​“_lread” (_ ByVal hFile As Long, lpBuffer() As Byte, _ ByVal wBytes As Long) As Long

However, the appeal

WBytes = lreadArray(hFile&, MyArray(), 10)

inevitably leads to a fatal program error.

This is a continuation of the conversation about the peculiarities of processing string variables in Visual Basic: VB uses double-byte Unicode encoding, Win API uses single-byte ANSI (and with the format adopted in C - with a zero byte at the end). Accordingly, when using string variables as an argument, the conversion from Unicode to ANSI is always automatically performed when calling an API function (more precisely, a DLL function) and the reverse conversion when returning.

The takeaway from this is simple: String variables can be used to exchange character data, but they cannot be used to exchange arbitrary binary information (as was the case with 16-bit versions of VB). In the latter case, it is better to use a one-dimensional byte array.

As you know, the String type can be used to describe a custom structure. In this regard, you need to remember the following:

  • It is strictly forbidden to use the following construction to access the Win API: Type MyStruct x As Single s As String ‘variable-length string End Type

    In the case of a variable-length string, a string descriptor is passed as part of the structure with all the ensuing consequences in the form of a program execution error.

  • You can use a fixed-length string as a structure element: Type MyStruct x As Single s As String*8 ‘ fixed-length string End Type

In this case, the corresponding encoding conversion is performed.

And one last note: under no circumstances should you use an array of string variables (both fixed and variable length) when accessing an API function. Otherwise, the emergence of an “illegal operation” will be guaranteed.

It is likely that you will have a situation where you need to write your own DLL functions. The need for this will inevitably arise if you use mixed programming technology - using two or more programming languages ​​to implement one application.

In this regard, we note that mixed programming is quite common for implementing a fairly complex application. Indeed, each language (more precisely, a programming system based on a language) has its own strengths and weak sides, so it makes sense to take advantage of different tools to solve different problems. For example, VB - for creating a user interface, C - for efficient access to system resources, Fortran - for implementing numerical algorithms.

The author's opinion is this: any serious programming requires the developer to be proficient in at least two tools. Of course, in modern conditions of a clear division of labor it is very difficult to be an excellent expert even in two systems, so the “main and auxiliary languages” scheme is more logical. The idea here is that even a superficial knowledge of the “auxiliary” language (writing fairly simple procedures) can greatly improve the efficiency of using the “main” one. Note that knowledge of VB, at least as an auxiliary one, is today almost a mandatory requirement for a professional programmer. By the way, in the days of DOS, knowledge of the basics of Assembler was extremely desirable for any programmer, including Basic.

One way or another, even in group work, when each programmer is engaged in his own specific task, all project participants should have an idea of ​​the features of the procedural interface in different languages. And know that many programming systems (including VB), in addition to the default interface, allow you to use other, advanced methods of accessing procedures that make it possible to adapt the interface to another language.

When studying the interprocedural interface, you should pay attention to the following possible pitfalls:

  • Different languages ​​may use different conventions for writing identifiers. For example, it is common to use an underscore at the beginning of a procedure name, which is not allowed in VB. This problem is easily solved by using the Alias ​​keyword in the Declare statement (see example tip 2.3).
  • A different sequence of writing passed arguments onto the stack can be used. For example, in the days of DOS (I honestly admit, I don’t know what it looks like now in the Windows environment), C wrote arguments from the end of the list, other languages ​​(Fortran, Pascal, Basic) - from the beginning.
  • By default, different principles of passing parameters are used - by reference or by value.
  • Various principles storing string variables. For example, in C (as well as in Fortran and Pascal), the length of a string is determined by the null byte at the end of it, but in Basic the length is written explicitly in the string descriptor. Of course, you need to keep in mind the possibility of using different character encodings.
  • When transferring multidimensional arrays, you should remember that various options for converting multidimensional structures into one-dimensional ones are possible (starting from the first index or from the last, in relation to two-dimensional arrays - “by rows” or “by columns”).

Taking all this into account, the following recommendations can be formulated:

  • Use the simplest, proven methods for passing arguments to DLL functions. The standards adopted for the Win API are quite suitable as a model.
  • Never pass arrays of string variables.
  • Be very careful when passing simple string variables and multidimensional arrays.
  • Be sure to specially check the functionality of the mechanism for passing arguments to the called procedure and back. Write a special test to check data transfer. Separately check that each argument is passed correctly. For example, if you have a procedure with several arguments, first check that each parameter is passed correctly for the one-argument option, and only then for the entire list.

But what if the DLL function is already written, for example, in Fortran, but its input interface does not fit very well into the above VB standards? There are two pieces of advice here. First: write a test DLL function and use it to try to find the desired call from the VB program using trial and error. Second: write an adapter procedure in the same Fortran that would provide a simple interface between VB and a DLL function with the conversion of simple data structures into complex ones (for example, convert a multidimensional byte array into a string array).

So: use DLL functions. But remain vigilant...

ComputerPress 9"2000

Internet