PowerBuilder and C++

Download Report

Transcript PowerBuilder and C++

PowerBuilder and
C++
or
How to optimize excessive
string operations
Arnd Schmidt
system analyst
[email protected]
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt
1
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
2
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
3
PowerBuilder Strings –
Memory Usage (ANSI)
string ls_test = ”PowerBuilder”
Variable ls_test holds the address of the strings first character.
Representation in Memory:
H e u t e :
P o w e r B u i
l d e r
M o r g e n :
Representation in Memory (Hexadecimal):
50 6F
77 65 72 42 75 69 6C 64 55 72 00
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt
4
PowerBuilder Strings – ASCII Table
ASCII Table (00-7F):
0
1
2
3
NUL
SOH
STX
EXT
EOT
ENQ
ACK
DLE
DC1
DC2
DC3
DC4
NAK
SYN
SP
!
"
#
$ % & '
3 0
4 @
1
A
2
B
3
C
5 P
6 `
7 p
Q
a
q
R
b
r
S
c
s
0
1
2
4 5 6 7
8
9 A B C D E
F
BEL
BS
HT
LF
VT
FF
CR
SO
SI
ETB
CAN
EM
SUB
ESC
FS
GS
RS
US
(
) * + , - .
/
4 5 6 7
D E F G
8
H
9 : ; < = >
I J K L M N
?
O
T U V W
d e f g
t u v w
X
h
x
Y Z [ \ ] ^
i j k l m n
y z { | } ~
_
o
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt
5
DEL
PowerBuilder Strings – Unicode
• UTF-8
– variable-width encoding of Unicode (1-3 byte)
• UTF-16 (UCS-2)
–
–
–
–
fixed-width encoding (2 byte)
UTF-16LE (Little Endian)
Example:
UTF-16BE (Big Endian)
Character ’P’ (0x50)
Offset
0
1
Default: UTF-16LE
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt
UTF-16LE
50
00
UTF-16BE
00
50
6
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
7
PowerBuilder Strings – Memory Usage
(Unicode)
string ls_test = ”PowerBuilder”
Variable ls_test holds the address of the strings first
character.
Representation in Memory:
P
l
o
d
w
e
e
r
r
b
u
i
Representation in Memory (Hexadecimal):
50 00
00 6C 00
6F 00 77 00 65 00 72 00 42 00 75 00 69
64 00 55 00 72 00 00 00
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt
8
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 support
Since PB10: Functions for 1-byte character support like LenA ()
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt
9
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_test
ls_test = &
of_ReplaceAll (”ABAABAABAAABA”,”ABA”,’A”)
Value of ls_test should be: ”AAAAA”
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt
10
PowerBuilder Strings – Example Code
for a simple of_ReplaceAll ()
Possible Implementation:
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 string
Return as_source
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt
11
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
12
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_test
ls_test = &
of_ReplaceAll (”ABaabAaBaaABa”,”aBA”,”a”, True)
Value of ls_test should be: ”aaaaa”
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt
13
PowerBuilder Strings – Example Code
for a case insensitive of_ReplaceAll ()
Possible implementation (1/3):
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_source
Long
ll_oldLen
// Length of as_old
Long
ll_newLen
// Length of as_new
Long
ll_delta
// Difference of ll_newLen and ll_oldLen
Long
ll_deltaSum = 0 // Increased sum for ll_delta
String ls_lowerSource
// ToLower converted as_source
// Check precondition
If IsNull(as_source) Or IsNull(as_old) &
Or IsNull(as_new)
Or IsNull(ab_ignoreCase) Then
SetNull(as_source)
Return as_source
End If
...
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt
14
PowerBuilder Strings – Example Code
for a case insensitive of_ReplaceAll ()
Possible implementation (2/3):
...
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
Loop
Else
...
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt
15
PowerBuilder Strings – Example Code
for a case insensitive of_ReplaceAll ()
Possible implementation (3/3):
..
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
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt
16
PowerBuilder Strings – Example Code
for a case insensitive of_ReplaceAll ()
But performance
and
memory consumption
is not satisfying!
Ideas?
PFC’s pfc_n_cst_string.of_global_replace () is a real good example!
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt
17
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
18
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
19
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
20
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 installation
directory, like: c:\watcom)
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt
21
PowerBuilder and C++
OpenWatcom – Program Menu
OpenWatcom provides a set of tools.
Short Demo now!
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt
22
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
23
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 Functions
extern "C" {
long PB_EXPORT StringReverse ( char *as_input, char *as_output ) ;
}
// Function Implementation
long 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
24
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
25
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
26
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
27
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
28
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
29
PowerBuilder and C++
Solution for of_ReplaceAll () – (2/2)
StringX.DLL
nv_stringx
Class cppstringx
+ HandleThis
External functions
Exported functions
Instance vars
cppstringx_create ()
cppstringx_create ()
constructor
cppstringx_destroy ()
cppstringx_destroy ()
~destructor
cppstringx_replaceall ()
cppstringx_replaceall ()
replaceall ()
cppstringx_getoutput ()
cppstringx_getoutput ()
getoutput ()
+ constructor ()
+ destructor ()
+ of_replaceall ()
Break here for a demonstration of speed!
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt
30
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 Implementation
long PB_EXPORT StringReverse ( TCHAR *as_input, TCHAR *as_output)
..
TCHAR a;
..
• To compile the code to support Unicode you have to set the
macro definition ‘_UNICODE ‘ on page 3 of the C++ Compiler
Switches.
• 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!
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt
31
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
32
PowerBuilder and C++ - Thank you
Thank you!
dwox.com
PBUGG Meeting, May 2006 - Copyright by Arnd Schmidt
33