|
Comments
Did you read today's front page stories & breaking news?
SYS-CON.TV
|
Product Review PowerBuilder Native Interface (PBNI) Part 1
PowerBuilder Native Interface (PBNI) Part 1
By: Roy Kiesler
Nov. 12, 2003 11:00 AM
The PowerBuilder Native Interface (PBNI) is a standard C++ programming interface that allows developers to extend the PowerScript language with C++ classes and to call PowerScript functions from C++ applications. Modeled after the Java Native Interface (JNI), PBNI provides a native vehicle that extends the functionality of PowerBuilder to that of the C++ programming language. Since its inception, PBNI has gained remarkable popularity within Sybase. PowerBuilder 9.0 ships with many new features, three of which - EJB client, Web services client, and the PBDOM XML parser - are PBNI implementations. Those, however, are merely the tip of an iceberg; the promise of PBNI can lead PowerBuilder programmers to new frontiers such as Microsoft .NET and has the potential to establish PowerBuilder as a new component model, alongside Microsoft's COM and Borland's VCL. It's not the intent of these articles to serve as a PBNI SDK reference, as PowerBuilder 9.0 already includes one; rather, it's a practical guide to writing PBNI extension modules (PBXs), outlining best practices to follow, as well as common programming errors to avoid. That being said, a certain amount of "dry" SDK review is occasionally necessary in order to maintain clarity and context. In places where such a review was necessary, the PBNI reference manual has been paraphrased. Note: This article assumes that the reader is an experienced C++ programmer familiar with Windows programming concepts, particularly DLLs, the Windows API, and advanced C++ concepts like templates and traits.
What Is PBNI?
The IPB_Session interface serves as the main conduit between native code and the PowerBuilder virtual machine. It exposes methods for accessing PowerScript data variables, creating and destroying PowerBuilder objects, invoking PowerScript functions, as well as catching and throwing PowerScript exceptions. The IPB_Session interface also exposes a method for setting a marshaler object, used to convert PowerBuilder data types and formats to other languages or component models. Marshaler extensions are covered later.
IPB_VALUE
IPB_ARGUMENTS
IPB_VM
The PBNI SDK
Building PBNI Extensions Steps 1 and 2 will not be discussed herein because they're simple tasks for most PowerBuilder developers. The PBX2PBD90 tool mentioned in step 6 is discussed in the "PBNI Utilities" in a later article. Steps 3, 4, and 5 are discussed later.
IMPLEMENTING PBNI CLASSES
virtual PBXRESULT Invoke The Invoke method must be implemented by every PBNI class. A typical implementation of this method resembles Listing 1. (Listings 1 and 2 can be downloaded from www.sys-con.com/pbdj/sourcec.cfm.) The third parameter of this method (pbmethodID) holds the ordinal of the method that was invoked on the PowerBuilder wrapper object. The value of this ordinal is declared in the C++ class definition. The fourth parameter is a pointer to a PBCallInfo struct that holds any parameters passed to the current method call. The Destroy method is called by the PBVM to remove an object instance that was previously created by either the PBX_CreateNonVisualObject() or the PBX_CreateVisualObject() functions. Consider the following PowerScript: IF IsValid( cpp_obj ) THEN DESTROY cpp_obj When the DESTROY statement is executed, PowerBuilder invokes the Destroy method on the PBX class. The code in the Destroy method will typically call the C++ delete statement, which in turn will invoke the class destructor of the PBNI module. For example:
void CMyClass::Destroy()
PBNI REQUIRED FUNCTIONS
PBX_GETDESCRIPTION
static const TCHAR classDesc[] = { The signature for this function is as follows: PBXEXPORT LPCTSTR PBXCALL PBX_GetDescription(); A PBNI class must inherit from one of two system classes:
The description can contain more than one class definition. An example is shown in Listing 2. A class definition can reference any class definition that appears before it in the description. The description returned from PBX_GetDescription is used by the PBX2PBD90 tool to generate a PBD wrapper for the PBNI class.
PBX_CREATENONVISUALOBJECT The signature for this function is as follows:
PBXEXPORT PBXRESULT PBXCALL Consider the following bit of PowerScript: n_cpp_base64 base64 base64 = CREATE n_cpp_base64 When the CREATE statement is executed, PowerBuilder invokes the PBX_CreateNonVisualObject method in the PBNI module, passing the bitwise object as the second parameter and "n_cpp_base64" (all lowercase) as the third parameter. The fourth parameter is a pointer to the C++ abstract class that will be used to create the new instance of the PBNI class. For example:
if ( strcmp( xtraName, "n_cpp_base64" ) == 0 )
PBX_CREATEVISUALOBJECT
PBXEXPORT PBXRESULT PBXCALL Consider the following bit of PowerScript: u_cpp_xpbutton xpbutton OpenUserObject( xpbutton, "u_cpp_xpbutton", 10, 10 ) When the OpenUserObject PowerScript function is called, PowerBuilder invokes the PBX_CreateVisualObject method in the PBNI module, passing the xpbutton object as the second parameter and "u_cpp_xpbutton" (all lowercase) as the third parameter. The fourth parameter is a pointer to the C++ abstract class that will be used to create the new instance of the PBNI class. For example:
if ( strcmp( xtraName, "u_cpp_xpbutton" ) == 0 ) The constructor of the PBXV_XPButton class (inherited from IPBX_VisualObject) calls the IPBX_ VisualObject GetWindowClassName() method, followed by the CreateControl() method. The latter is responsible for the creation, initialization, and display of the visual control.
PBX_INVOKEGLOBALFUNCTION
PBXEXPORT PBXRESULT PBXCALL
BUILDING A PBNI EXTENSION DLL Most C++ compilers and linkers have specific command switches that specify the aforementioned file locations. Depending on your choice of a C++ development environment, a convenient user interface might exist to modify these settings. Figures 1 and 2 illustrate such a user interface provided by Microsoft Visual C++ 7.0, an integral part of the Microsoft VisualStudio.NET development environment.
Note: All code examples in this article were compiled using both Microsoft Visual C++ .NET and Borland C++ Builder 6.0. Versions 5.0 and 6.0 of Visual C++ can also be used. At the time of writing, the latest beta of the open-source Watcom C++ 11.0c failed to compile the pbtraits.h file because it uses template specialization syntax that is not yet supported. Other compilers, such as CodeWarrior and GNU C++, might work, but they were not tested.
Reader Feedback: Page 1 of 1
Latest Cloud Developer Stories
Subscribe to the World's Most Powerful Newsletters
Subscribe to Our Rss Feeds & Get Your SYS-CON News Live!
|
SYS-CON Featured Whitepapers
Most Read This Week
Breaking Cloud Computing News |
||||||||||||||||||||||||||||||||||||||||||||||||||||