| By Jim O'Neil | Article Rating: |
|
| August 1, 2002 12:00 AM EDT | Reads: |
9,264 |
Have you ever thought of adding new features to PowerBuilder? Or wanted to call Java or .NET from PowerScript? Or imagined that you can call PowerScript from C++ or Java? With PBNI, you can do them all and more. PowerBuilder Native Interface (PBNI) is a standard interface for third parties to extend the functionality of PowerBuilder.
PBNI is a valuable new addition to the PowerBuilder programmer's toolbox that allows developers to reach beyond the already feature-rich constructs of PowerScript and custom class user objects (commonly referred to as nonvisual objects or NVOs). The following are a few of the things you can do with PBNI.
Creating PowerBuilder Extensions
Suppose you want to use a COM component in PowerBuilder. Unfortunately, one of the COM functions takes a pointer to a user-defined COM interface as a parameter, so you can't map the interface into any of PowerBuilder's datatypes. What should you do? With PowerBuilder 9, you can create a PowerBuilder extension using PBNI.
Now you want to create a SAX XML parser to complement the DOM parser provided in PowerBuilder 9. It's not trivial to implement the parser in PowerScript and you're concerned about the performance. You can write a PowerBuilder extension to do the job.
What if you want to invoke part of the Adaptive Server Anywhere API to provide a PowerBuilder interface for database backups and maintenance? Some of that functionality requires callback functions, which we all know aren't supported in PowerScript. The solution? Write a PowerBuilder extension using PBNI.
A PowerBuilder extension is a DLL written in C++ that exposes one or more native classes to be used in PowerScript as NVOs. A native class is a PowerScript class implemented in C++. The DLL is loaded by the PowerBuilder Virtual Machine (PBVM) dynamically at runtime when the native classes are used for the first time by a PowerBuilder application. When the functions of the native classes are called in PowerScript, the PBVM automatically delegates the function calls to the corresponding C++ classes.
To develop a PowerBuilder extension, first determine what native classes the extension will support. Next, for each native class, declare and implement a C++ class that inherits from IPBX_NonVisualObject and implement the standard functions required by PBNI using the ANSI C++ tool of your choice. Once the DLL has been built, generate a PBD file for the extension with the pbx2pbd tool shipped with PowerBuilder 9. With the DLL and PBD file in hand, the extension is ready to use. Simply add the PBD file to the library list of your PowerScript target and put the DLL in a directory on the PATH, and you can use the native classes as easily as the NVOs you're accustomed to building and using in PowerBuilder.
Each extension can include one or more native classes. When the pbx2pbd tool generates a PBD file for an extension, it calls the PBX_GetDescription() function to get a description of all the native classes supported by the DLL. Each class description basically follows PowerScript syntax:
static const TCHAR desc[] =This extension supplies two native classes, xmlevent and xmlparser, both inheriting from the NonVisualObject PowerBuilder system class. xmlevent defines four events and xmlparser defines one function.
{
"class xmlevent from nonvisualobject\n"
"event boolean startdocument(string docname)\n"
"event boolean enddocument(string docname)\n"
"event boolean startelement(string elementName)\n"
"event boolean endelement(string elementName)\n"
"end class\n"
"class xmlparser from nonvisualobject\n"
"function boolean parse(xmlevent handler, string xmlFileName)\n"
"end class\n"
}
In PowerBuilder, create a new NVO, e.g., myXmlEventHandler, that inherits from xmlevent and implements the four events. Then you can use the extension as follows:
myXmlEventHandler eventHandlerHere's what happens behind the scenes when the script is executed. To create XmlParser, the PBVM calls the PBX_CreateNonVisualObject() function exposed by the extension. This function creates the corresponding C++ object and returns it to the PBVM. When the parse() function of XmlParser is called, the PBVM calls the Invoke() function on the corresponding C++ object, then the function can parse the XML file and trigger events accordingly. This way, the event handlers of myXmlEventHandler are called to do whatever you want.
XmlParser parser
eventHandler = create myXmlEventHandler
parser = create XmlParser
parser.parse(eventHandler, "xyz.xml")
This means you can actually call a PowerScript function and trigger a PowerScript event from a PowerBuilder extension, because the PBVM and PowerBuilder extensions work together seamlessly. If you're familiar with the Java Native Interface (JNI), you'll see there are several similarities between JNI and PBNI.
To recap, you can write PowerBuilder extensions in C++ to provide one or more native classes that you can use in PowerScript as NVOs. PowerBuilder extensions can create PowerBuilder objects, call PowerScript functions, and trigger PowerScript events, making these constructs easily available from other environments such as Java.
Creating PowerBuilder Marshaler Extensions
PBNI also enables you to write marshaler extensions. Marshaler extensions can act as bridges between PowerBuilder and other components, such as CORBA components, Java classes, and Web services, as long as those components can be called from C++.
Let's say you want to call Java classes from PowerScript. Without PBNI, it's almost impossible to do that, but there is a way with PBNI.
Developing a Tool for Generating PowerBuilder Proxies for Java Classes
First develop PowerBuilder proxies for the Java classes you wish to invoke from PowerBuilder. You might do this using Java reflection, from Java source code directly, or using the javap tool.
For this Java class:
public class Converterthe PowerBuilder proxy would be something like this:
{
public double dollarToYen(double dollar);
public double yenToEuro(double yen);
}
$PBExportHeader$ConverterNotice that both PowerBuilder proxy functions have an alias that contains the Java function name and function signature. This is necessary since Java is case sensitive, but PowerBuilder is not. The alias information is used by the extension to find the corresponding Java functions.
$PBExportComments$Proxy for Java class.
global type Converter from NonVisualObject
end type
global Converter Converter
forward prototypes
public:
function dollarToYen(double ad_1) alias for "dollarToYen,(D)D"
function yenToEuro(double ad_1) alias for "yenToEuro,(D)D"
Developing a PowerBuilder Extension
Develop a PowerBuilder extension that provides a native class, called JavaProxy. The JavaProxy class has a function that looks something like this:
function long createJavaObject(ref PowerObject javaObject,string className)
You need to write another C++ class, e.g., JavaMarshaler, that implements the IPBX_Marshaler interface. This interface is responsible for marshaling requests to a Java object and unmarshaling the result returned from the Java object.
Once the code has been written, build the extension (containing the JavaProxy and the JavaMarshaler classes) and put it in a directory on the PATH. Then generate a PBD file for the extension with the pbx2pbd tool, add the PBD file to the library list of your PowerScript target, and import the proxy for the Converter Java class into your PowerScript target. Now you can call the Converter class:
JavaProxy l_jpWhen the createJavaObject() function of JavaProxy is called in PowerScript, the PBVM calls the corresponding C++ function in the extension. The C++ function creates a Java Converter object through JNI. If successful, the function creates an instance of the PowerBuilder Converter proxy and a JavaMarshaler object, and associates the JavaMarshaler object with the PowerBuilder proxy. Later, when conv.dollarToYen(100.0) is reached, the PBVM calls the InvokeRemoteMethod() function on the JavaMarshaler object. This function then delegates the call to the Java Converter object though JNI and returns the result to PowerBuilder. Now you can call Java from PowerBuilder.
Converter l_conv
double l_yen
l_jp = create JavaProxy
l_jp.createJavaObject(l_conv, "com.sybase.pbni.Converter")
l_yen = l_conv.dollarToYen(100.0)
Invoking PowerScript from Other Languages
Let's say you're writing a C++ (or even a Java) application and some part of it includes some intensive database operations. You already have many PowerBuilder NVOs doing the same thing. Can you reuse those PowerBuilder NVOs in the C++ application? Yes, using PBNI.
In the C++ application, load the PBVM DLL and call the PB_GetVM() function to get a pointer to the IPB_VM interface. From there call the CreateSession() function of the IPB_VM interface to create a session and get a pointer to the IPB_Session interface. Next create the NVO you want to use and invoke its functions through the IPB_Session interface.
C++ code in Listing 1 shows how to call the function int foo(string) of mynvo, which lives in mypbl.pbl (error-handling code has been removed for the sake of simplicity).
The last parameter to the GetMethodID() function is the signature of the PowerScript function. PBNI provides a utility, pbsig, to help you get the signatures of PowerBuilder functions.
Conclusion
PowerBuilder is wide open to the outside world. With PBNI, anything that can be called from C++ can be called from PowerScript; anything that can call C++ can also call PowerScript. The flexibility and interoperability provided by this technology is being put to use in the PowerBuilder product - features such as the PowerBuilder Document Object Model (PBDOM) and SOAP support are being implemented using PBNI. PBNI's potential is only limited by your imagination.
Published August 1, 2002 Reads 9,264
Copyright © 2002 SYS-CON Media, Inc. — All Rights Reserved.
Syndicated stories and blog feeds, all rights reserved by the author.
More Stories By Jim O'Neil
Jim O'Neil is a Microsoft Developer Evangelist for the Northeast U.S. where he concentrates on the developer communities using Visual Studio .NET and the various .NET technologies. Prior to joining Microsoft, he was a Principal Systems Consultant and Principal Technical Support Engineer for Sybase, Inc., where he specialized in the PowerBuilder family of tools, EAServer, and Appeon for PowerBuilder.
![]() |
Eduardo Fernandez Oliver 09/11/02 05:35:00 AM EDT | |||
- Why SOA Needs Cloud Computing - Part 1
- Cloud Expo and The End of Tech Recession
- The Transition to Cloud Computing: What Does It Mean For You?
- A Rules Engine Built in PowerBuilder
- Sybase Named “Silver Sponsor” of iPhone Developer Summit
- How PowerBuilder Got Its Groove Back
- The Cloud Has Cross-Border Ambitions
- Ulitzer Names The World's 30 Most Influential Virtualization Bloggers
- Ulitzer Named "New Media" Partner of Greatly Anticipated iStrategy Event in Berlin
- Risks and Enterprise Mobility?
- Steps for Success in Enterprise Mobility?
- Are Mobile Luddites Resisting Mobility?
- The Difference Between Web Hosting and Cloud Computing
- Sybase CTO to Speak at 4th International Cloud Computing Expo
- Why SOA Needs Cloud Computing - Part 1
- Cloud Expo and The End of Tech Recession
- The Transition to Cloud Computing: What Does It Mean For You?
- Five Reasons to Choose a Private Cloud
- Seeding The Cloud: The Future of Data Management
- The Threat Behind the Firewall
- Economy Drives Adoption of Virtual Lab Technology
- Tips for Efficient PaaS Application Design
- A Rules Engine Built in PowerBuilder
- Sybase Named “Silver Sponsor” of iPhone Developer Summit
- Where Are RIA Technologies Headed in 2008?
- PowerBuilder History - How Did It Evolve?
- The Top 250 Players in the Cloud Computing Ecosystem
- Custom Common Dialogs Using SetWindowsHookEx
- DDDW Tips and Tricks
- OLE - Extending the Capabilities of PowerBuilder
- DataWindow.NET How To: Data Entry Form
- Book Excerpt: Sybase Adaptive Server Anywhere
- Sybase ASE 12.5 Performance and Tuning
- Working with SOA & Web Services in PowerBuilder
- Office 2003 Toolbar: A New Look For Your Old PowerBuilder App
- Dynamically Creating DataWindow Objects

































