J/Direct

No matter how large MS Visual J Plus Plus's libraries are, there will always come a time when you can't find the exact function you want in either the Windows Foundation Classes for Java (WFC) or the Abstract Windowing Toolkit (AWT) library. When you are faced with this situation, you might discover that the function you need is a native function residing in an existing Dynamic-Link Library (DLL), such as the Win32 API.

NOTE
A native function is a function that is written in the machine language of the host machine. These functions are almost invariably written in C.

Prior to Visual J Plus Plus v6, you had to use Sun Microsystem's Java Native Interface (JNI) or Microsoft's Raw Native Interface (RNI) to access a native function from Java. Of these two interfaces, RNI is better optimized for accessing Windows functions, but it is not supported by Sun Microsystem's Java. JNI is more standard across the Java landscape, but is not supported by Visual J Plus Plus or Microsoft Internet Explorer.

Both JNI and RNI have serious drawbacks. Both require you to convert the Java data types to and from the corresponding C or C++ data types, which takes considerable effort. In addition, RNI limits you to calling functions that fit certain naming conventions. Further, with both JNI and RNI you must be careful to explicitly disable and enable garbage collection at the appropriate times. The net effect of these drawbacks is that to use RNI or JNI to invoke existing DLL functions (including Windows API functions), you must write a shell to perform the necessary conversions.

To address the problem of calling native functions from Java, Visual J Plus Plus v6 includes a new mechanism called J/Direct. (J/Direct was introduced as part of the Microsoft Software Development Kit (SDK) for Java version 2.01.) J/Direct provides you with convenient access to native functions. J/Direct performs any data conversions that might be necessary and deals with details concerning memory pointers and garbage collection. With J/Direct, you can use native functions in the same way that you use normal Java methods. Visual J Plus Plus v6 pounds the final nail into the RNI/JNI coffin by including a tool, named the J/Direct Call Builder, that builds the necessary J/Direct commands for the functions that make up the Win32 API.

In this chapter, you'll learn how to use J/Direct and the J/Direct Call Builder. This chapter starts out with a simple app called Beep, which attaches itself to a Win32 API function to generate a short beep on the PC. The chapter then moves up to a slightly more complicated example that involves passing structures to and from a Win32 API call. In addition, I'll show you how to access functions from DLLs that you might write yourself. Finally, you'll learn how to use J/Direct to generate a new and better solution to the idle event problem that we worked on in Chapter 10. (The code for all the examples in this chapter is on the companion CD in the Windows apps subfolder.)

Limitations to the use of J/Direct


Before we start working with J/Direct, I'll present a few caveats. First, any app written using J/Direct is by definition specific to the Win32 API, and is probably also specific to Intel processors. This implies that it would be unconscionable to use JNI, RNI, or J/Direct to write an applet that is designed to run on the Internet.

Second, although this chapter refers specifically to C structures, J/Direct also supports C++ structures. However, J/Direct doesn't support C++ classes.

Third, J/Direct and RNI can be used in the same program, but you should not intermix J/Direct and RNI calls. You shouldn't pass to a J/Direct call a reference to an object returned from RNI, and you shouldn't pass to an RNI call a reference to an object returned from J/Direct. Because of J/Direct's ease of use, I recommend that you simply not use RNI.

Fourth, because of the security checks, stack checking, and automatic data conversions that J/Direct performs for you, J/Direct calls are slightly slower than RNI calls. This speed difference should almost never be an issue. The time it takes for a program to make a function call is almost always insignificant, compared with the time it takes to execute the function. I doubt that the performance penalty would be noticeable, unless your program sits in a tight loop repeatedly calling small native functions.

Comments