Upload
lee-tyler
View
222
Download
0
Embed Size (px)
Citation preview
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 1
PowerBuilder and C++
or
How to optimize excessive string operations
Arnd Schmidt
system analyst
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 2
PowerBuilder and C++ - Abstract
• Abstract– PowerBuilder and Strings– A simple of_ReplaceAll ()– Setting up a test suite– Install OpenWatcom C++– Simple DLL Example for OpenWatcom– Install Visual Studio Express C++– Simple DLL Example for Visual C++– A faster of_ReplaceAll () in OpenWatcom– Accessing Functions and Classes– PowerBuilder Native Interface (PBNI)– Live demonstrations and Labs
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 3
PowerBuilder Strings – The String
Q: What is a string? A: A sequence of characters in memory,
delimited by a special character.What else should be a ”Zeichenkette”?
Q: What is that special character?A: That is the null byte (0x00).
Q: Are there any string length limitations? A: Yes, it is limited by the (available) memory.
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 4
Variable ls_test holds the address of the strings first character.Representation in Memory:
PowerBuilder Strings – Memory Usage (ANSI)string ls_test = ”PowerBuilder”
H e u t e :
P o w e r B u i l d e r
M o r g e n :
50 6F 77 65 72 42 75 69 6C 64 55 72 00
Representation in Memory (Hexadecimal):
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 5
PowerBuilder Strings – ASCII Table
ASCII Table (00-7F):
0 1 2 3 4 5 6 7 8 9 A B C D E F
0 NUL SOH STX EXT EOT ENQ ACK BEL BS HT LF VT FF CR SO SI
1 DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US
2 SP ! " # $ % & ' ( ) * + , - . /
3 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
4 @ A B C D E F G H I J K L M N O
5 P Q R S T U V W X Y Z [ \ ] ^ _
6 ` a b c d e f g h i j k l m n o
7 p q r s t u v w x y z { | } ~ DEL
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 6
• UTF-8– variable-width encoding of Unicode (1-3 byte)
• UTF-16 (UCS-2)– fixed-width encoding (2 byte)– UTF-16LE (Little Endian)– UTF-16BE (Big Endian)– Default: UTF-16LE
PowerBuilder Strings – Unicode
Example: Character ’P’ (0x50)
Offset 0 1
UTF-16LE 50 00
UTF-16BE 00 50
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 7
PowerBuilder Strings – UTF16 (UCS-2)
Examples of used ranges:
Range Name Examples
0020-007F Basic Latin 0-9,A-Z,a-Z,!,$,%,<,=,>, ...
00A0-00FF Latin 1 SupplementedÀ, Ä, Ë, Ö, Ü, ä,ö,ü,ß, ©, ..
0100-017F Latin Extended A Ą, ą, Ę, ę, Ģ, ģ
0180-024F Latin Extended B Ǎ, ǎ, Ǽ, ǽ, Ǿ, ǿ
0370-037F Greek and CopticΑ, Β, Γ, Δ, Ε, α, β, γ, δ, ε
0600-06FF Arabic ٤, ٣, ٢, ١, ٠, ل, ض, ص ,
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 8
Variable ls_test holds the address of the strings first character.Representation in Memory:
PowerBuilder Strings – Memory Usage (Unicode)string ls_test = ”PowerBuilder”
P o w e r b u i
l d e r
50 00 6F 00 77 00 65 00 72 00 42 00 75 0069
00 6C 00 64 00 55 00 72 00 00 00
Representation in Memory (Hexadecimal):
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 9
PowerBuilder Strings – Functions
• Built-in functions:– Char (), Fill (), Space ()– ASC (), Lower (), Upper (), Reverse () , Wordcap ()– Trim (), LeftTrim (), RightTrim ()– Len (), Pos (), LastPos()– Mid (), Left (), Right (), – Replace () – Match ()
Prior PB10: Functions like LenW() for Unicode supportSince PB10: Functions for 1-byte character support like LenA ()
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 10
PowerBuilder Strings – A simple of_ReplaceAll () Function• Lab 1 (5 min.)
Implement the function of_ReplaceAll () that will– Replace all occurrences of the string as_old in a given
string as_source by the string as_new.– Return the modified as_source.
Test the function by coding:string ls_testls_test = & of_ReplaceAll (”ABAABAABAAABA”,”ABA”,’A”)
Value of ls_test should be: ”AAAAA”
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 11
PowerBuilder Strings – Example Code for a simple of_ReplaceAll ()
Function String of_ReplaceAll( String as_source, String as_old, String as_new )long ll_Pos = 1// Find the first occurrence of as_old ...ll_Pos = Pos ( as_source, as_old, ll_Pos )
// Only enter the loop if you find as_old ...Do While ll_Pos > 0 // Replace old_str with ls_new_str ... as_source = Replace ( as_source, ll_Pos, Len(as_old), as_new)
// Find the next occurrence of ls_old_str ll_Pos = Pos ( as_source, as_old, ll_Pos + Len(as_new))Loop// Return stringReturn as_source
Possible Implementation:
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 12
PB Strings – Discussion
• What happens during execution for large strings with a lot of replacements?– Due to string assignments there will be a lot
of memory related operations (allocation and copying).
– The Len () function will be called to much, even though the strings (old/new) are usually not very long.
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 13
PowerBuilder Strings – Case sensitive/ insensitive of_ReplaceAll ()• Lab 2 (5 min.)
Expand the function of_ReplaceAll () to accept a boolean variable so that it works case sensitive or case insensitive.– Replace all occurrences of the string as_old in a given
string as_source by the string as_new.– If the functions boolean argument ab_ignorecase is set
to true, perform the search case insensitive.– Return the modified as_source.
Test the function by coding:string ls_testls_test = & of_ReplaceAll (”ABaabAaBaaABa”,”aBA”,”a”, True)
Value of ls_test should be: ”aaaaa”
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 14
PowerBuilder Strings – Example Code for a case insensitive of_ReplaceAll ()
Function String of_ReplaceAll( String as_source, String as_old, String as_new Boolean ab_ignorecase )Long ll_pos // Position of as_old in as_sourceLong ll_oldLen // Length of as_oldLong ll_newLen // Length of as_newLong ll_delta // Difference of ll_newLen and ll_oldLenLong ll_deltaSum = 0 // Increased sum for ll_deltaString ls_lowerSource // ToLower converted as_source
// Check preconditionIf IsNull(as_source) Or IsNull(as_old) & Or IsNull(as_new) Or IsNull(ab_ignoreCase) Then
SetNull(as_source)Return as_source
End If...
Possible implementation (1/3):
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 15
PowerBuilder Strings – Example Code for a case insensitive of_ReplaceAll ()
...ll_oldLen = Len ( as_old ) ll_newLen = Len ( as_new )
If ab_ignoreCase Then // Not Case sensitive as_old = Lower ( as_old ) ls_lowerSource = Lower ( as_source ) ll_delta = ll_newLen - ll_oldLen
ll_pos = Pos ( ls_lowerSource, as_old ) Do While ll_pos > 0 as_source = Replace ( as_source, ll_pos + ll_deltaSum, & ll_oldLen, as_new ) ll_pos = Pos ( ls_lowerSource, as_old, ll_pos + ll_oldLen ) ll_deltaSum += ll_delta LoopElse...
Possible implementation (2/3):
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 16
PowerBuilder Strings – Example Code for a case insensitive of_ReplaceAll ()
..Else // Case sensitive ll_pos = Pos ( as_source , as_old )
Do While ll_pos > 0 as_source = Replace ( as_source, ll_pos, ll_oldLen, as_new ) ll_pos = Pos ( as_source, as_old, ll_pos + ll_newLen ) Loop
End If
Return as_source
Possible implementation (3/3):
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 17
PowerBuilder Strings – Example Code for a case insensitive of_ReplaceAll ()
PFC’s pfc_n_cst_string.of_global_replace () is a real good example!
But performance and
memory consumption
is not satisfying!
Ideas?
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 18
PowerBuilder and DLLs (I)
Q: What is a DLL?
A: DLL = Dynamic Link Library!
Q: What is a Dynamic Link Library?
A: Something like a DLL?!
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 19
PowerBuilder and DLLs (II)
Dynamic-Link Library:• Microsoft’s implementation of shared libraries.• Library is organized into sections.• Library can hold code and data (like resources).• Library is loaded when needed during runtime.• Only a single instance will be loaded when used by
multiple applications.• Reference to the DLL’s code is dynamic - not static.• Library usage can be shared – not only the code,
but also the data.
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 20
PowerBuilder and C++ - OpenWatcom
• History – Initially 1965 students at the university of Waterloo in
Canada developed a Fortran compiler (WATFOR)– 1985: PC Version of WATFOR-77– 80’s: Rewriting the code in C– 1988: First PC Version Watcom C 6.0
– Code generator supported C and FORTRAN– Portable across multiple platforms ( DOS, Windows,
OS/2, and Windows NT – Popular in the mid-1990s
– Some important games were developed with Watcom C ( DOOM, Descent or Duke Nukem 3D )
– Since 2000 Open Source– License from Sybase allows free commercial use
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 21
PowerBuilder and C++ - OpenWatcom Installation
• Download and run setup.– Download the file
open-watcom-c-win32-1.5.exe (59 MB)
from http://www.openwatcom.org/ftp/
or ftp://ftp.openwatcom.org/watcom/
– Execute the file and follow instructions. (Tip: Use a short name for the installationdirectory, like: c:\watcom)
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 22
PowerBuilder and C++ OpenWatcom – Program Menu
OpenWatcom provides a set of tools.
Short Demo now!
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 23
PowerBuilder and C++ OpenWatcom – Building a DLL
Lab3: PB9 and OpenWatcom Lab:• Filesystem Operations
– Create a new directory– Copy file easydll.cpp to the directory
• Start OpenWatcom IDE – Create a new project (easydll) and save it– Create a new target (easydll.dll)– Add new source (easydll.cpp) to the target – Save project– Make target
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 24
PowerBuilder and C++ OpenWatcom – easydll.cpp
// This is the key (copied from pbdll.h)#pragma aux __fortran "*" parm [] modify [ eax ecx edx ];#define PB_EXPORT __export __fortran
// Export Functionsextern "C" { long PB_EXPORT StringReverse ( char *as_input, char *as_output ) ;}// Function Implementationlong PB_EXPORT StringReverse ( char *as_input, char *as_output ) { long l, i;
for (l=0 ; as_input[l]!='\0‚ ; ++l);
for (i=0 ; i<l ; i++) { as_output[l - i - 1] = as_input[i]; } return l;}
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 25
PowerBuilder and C++ - Visual C++ 2005 Express Installation• Visit Visual C++ Express Homepage at
msdn.microsoft.com/vstudio/express/visualc• Download
Visual C++ 2005 Express
• Install and run it at least once!
• Download Platform SDK Server 2003 R2
• Install– Tip: You do not need to install the 64-Bit features
• Follow instructions from– msdn.microsoft.com/vstudio/express/visualc/usingpsdk
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 26
PowerBuilder and C++ Visual C++ 2005 Exp. – Building a DLL
Lab4: PB9 and Visual C++ Lab:• Filesystem Operations
– Create a new directory – Copy easydll.c, easydll.def and the makefile to
the directory
• Command line– Start „Visual Studio 2005 Command Prompt“– Change current directory – Execute „nmake“
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 27
PowerBuilder and C++ Visual C++ 2005 Exp. – easydll.c
__declspec(dllexport) long __stdcall StringReverse ( char *as_input, char *as_output ) { long l, i;
for (l=0 ; as_input[l]!='\0‚ ; ++l);
for (i=0 ; i<l ; i++) { as_output[l - i - 1] = as_input[i]; } return l;}
easydll.def:
LIBRARY "EasyDLL"
EXPORTS StringReverse
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 28
PowerBuilder and C++ Back to the of_ReplaceAll ()• Goals
- Avoid to much memory allocation • Minimize usage of Memory space• Minimize Memory actions, like allocation and
freeing of memory- Use an efficient Search Algorithm
• Something like Boyer-Moore algorithm- Support PB9 or PB 10
• ANSI vs. Unicode
• For long strings and a lot of replace operations the best strategy in conjunction with PowerBuilder seems to be a 2-pass strategy.
1. Analyze the string and determine desired memory space
2. Allocate the memory and copy only what you need.
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 29
PowerBuilder and C++ Solution for of_ReplaceAll () – (1/2)• C++ Class that supports the 2-pass strategy
- Class uses member variables to store specific information.- Source can be compiled for 8-bit (ANSI) or 16-bit
(Unicode) character usage (TCHAR).
• PowerBuilder nonvisualobject class (Wrapper)- A new instance of the C++-Class will be created for each
PowerBuilder object instance (constructor). - The handle of the C++-Class instance will be stored in an
instance variable of type ’long’.- Local external function calls are declared to invoke the
exported DLL functions.- PowerBuilder code (PBVM) is responsible for the (big)
memory allocation (result string).
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 30
PowerBuilder and C++ Solution for of_ReplaceAll () – (2/2)
nv_stringx+ HandleThis
+ constructor ()
+ destructor ()
+ of_replaceall ()
Class cppstringxExternal functions
cppstringx_destroy ()
cppstringx_replaceall ()
cppstringx_getoutput ()
cppstringx_create ()
cppstringx_destroy ()
cppstringx_replaceall ()
cppstringx_getoutput ()
cppstringx_create ()
~destructor
replaceall ()
getoutput ()
constructor
Instance vars
StringX.DLL
Exported functions
Break here for a demonstration of speed!
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 31
PowerBuilder and C++ Supporting PB9 and PB10 (Unicode) • The Key to success is to use TCHAR instead of char for
character declarations / definitions.
#include <tchar.h>..// Function Implementationlong PB_EXPORT StringReverse ( TCHAR *as_input, TCHAR *as_output)..TCHAR a;..
• Lab 5. Copy and modify the OpenWatcom EasyDLL Example source code to work with PB10 / PB 10.5. You have to setup a new OpenWatcom Workspace and Target!
• To compile the code to support Unicode you have to set the macro definition ‘_UNICODE ‘ on page 3 of the C++ Compiler Switches.
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 32
PowerBuilder and C++ Short info about PBNI
• With PBNI you are able to develop a C++ Class without programming a PowerBuilder object like nv_stringx.
• You can implement a high performance string modifying class or other specialized classes that fit your special needs.
Or wait for others doing this job!
• Demonstration of some PBNI examples.
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt 33
PowerBuilder and C++ - Thank you
Thank you!
dwox.com