Hi Bob:
Thanks for your very helpful explanation. I will be studying this entire thread over the next week or so. I see that I am still on the lower portion of the learning curve. May you have a blessed day.
Sincerely,
Michael D Fitzpatrick
Announcement
Collapse
No announcement yet.
Possible bug in PowerBASIC's implementation of Fixed-length strings
Collapse
X
-
Originally posted by Michael Fitzpatrick View PostHi Bob:
I am having some difficulty understanding your post.
1) When I tried compiling just this much in PowerBASIC:
DIM xx$(1 TO 4)
xx(1) = "xc"
xx(2) = "SR"
xx(3) = "DI"
xx(4) = "CO"
I got the compiler message: "Missing declaration: xx"
Michael Fitzpatrick
You don't show your actual code used (always preferred on this forum) so it's difficult to determine exactly what the problem is. I'd bet you have a "#Dim All" at the top of your code (Highly reccoed for all code). Try
Code:'... Local xx$() '<<<<Add this befire Dimming ************** Dim (xx$(1 to 4) '...
===============================================
"It is better to be feared than loved,
if you cannot be both."
Niccolo Machiavelli (1469-1527), "The Prince"
===============================================
Leave a comment:
-
Not that diversion is necessarily a bad thing, but I think we may have forgotten the 'conditions of contest' here...
The problem is NOT to "do something" in PowerBASIC to allow a PB-written function in a DLL to understand what has been passed to it; the problem is finding the best way to express and work with whatever VBA is passing to that DLL-based function.
When you control both sides (the passer and the passee, so to speak) many things are possible... but when you don't control one side or the other, the number of things which can be made to work tends to be somewhat more limited.
MCM
Leave a comment:
-
For more clarity, here is a compilable example:
Code:#COMPILE EXE #DIM ALL FUNCTION PBMAIN () AS LONG LOCAL msgString AS STRING msgString = STRING$(200, ".") '50 elements * 4 bytes per element = 200 bytes needed DIM IOfcArry(49) AS LONG AT STRPTR(msgString) 'overlay array onto msgString. (again, rather advanced technique) IOfcArry(0) = 25464 '"xc" = &h6378 = 25464. &h63 = "c" and &h78 = "x" but stored reversed (aka little endian). IOfcArry(1) = 5392708 '"DIR" IOfcArry(2) = 21075 '"SR" '. . . IOfcArry(49) = 5197635 '"COO" REPLACE ANY $NUL WITH $SPC IN msgString 'gets rid of $NUL characters so we can print full string ? msgString 'now you can see how your strings are stored properly END FUNCTION
Leave a comment:
-
For example, the string array whose elements are:
OfcArry(0) = "xc"
OfcArry(1) = "DIR"
OfcArry(2) = "SR"
. . .
OfcArry(49) = "COO"
can instead be represented by an array of integers whose elements are:
IOfcArry(0) = 4
IOfcArry(1) = 1
IOfcArry(2) = 2
. . .
IOfcArry(49) = 3
Code:IOfcArry(0) = 25464 '"xc" = &h6378 = 25464. &h63 = "c" and &h78 = "x" but stored reversed (aka little endian). IOfcArry(1) = 5392708 '"DIR" IOfcArry(2) = 21075 '"SR" . . . IOfcArry(49) = 5197635 '"COO"
Leave a comment:
-
I didn't create code which was intended to be used anywhere in particular. I just answered your question and gave you some example pseudo-code to demonstrate the principles.
DIM xx$(...) creates, allocates, and initializes a dynamic string array named xx$(). There is no exclusivity to the name, so you must reference it with the "$" type identifier to tell it apart from xx%() and xx#() and others.
DIM xx(...) AS STRING creates, allocates, and initializes a dynamic string array. Additionally, the AS STRING declares that the name xx is exclusive to this particular name and will not be used for another array in this scope and context. It can then be referenced without a type identifier as xx(). Now, xx() and xx$() may be used interchangeably. They refer to the same array data, bevause you told the compiler that any use of the ambiguous name xx() should be interpreted as the dynamic string array named by xx().
The variables x& and y& are long integers. VARPTR() and STRPTR() return a numeric value which tells you the location (address) of a variable and string data respectively. An address is a numeric value, not a string, so the address must be assigned to a numeric variable.
You asked me where in memory a particular set of data may be found. The concept of "where" requires a numeric answer because that is the way an address (location) is represented. The code I gave you showed a generic way to obtain the address of a variable or string data.
Bob Zale
PowerBASIC Inc.
Leave a comment:
-
Missing Declaration
Hi Bob:
I am having some difficulty understanding your post.
1) When I tried compiling just this much in PowerBASIC:
DIM xx$(1 TO 4)
xx(1) = "xc"
xx(2) = "SR"
xx(3) = "DI"
xx(4) = "CO"
I got the compiler message: "Missing declaration: xx"
Did you mean DIM xx(1 TO 4) As String?
And did you mean for this DIM to reside in a PowerBASIC source or in an Excel VBA procedure (as per my situation)?
2) If we are dealing with arrays of strings, why would you have:
x& = PEEK(LONG, VARPTR(xx$(1)))
y& = STRPTR(xx$(1))
Wouldn't x& and y& be of type LONG? (Perhaps I am missing something here.) How would those two statements (and any other relevant code) have to be modified to deal with strings instead of integers? Thanks for your kind help. May you have a blessed day.
Sincerely,
Michael Fitzpatrick
Leave a comment:
-
Hi Michael,
Assuming,,,
DIM xx$(1 TO 4)
This creates an array of four dynamic string variables. These four string variables are stored in contiguous memory locations. Each of these variables consists of of a 32-bit (4-byte) pointer to the actual string data. If the string is nul (zero-length) the pointer is zero (0).
VARPTR(xx$(1)) returns the address (location) of that string variable. The next 3 array members follow in memory.
STRPTR(xx$(1)) returns the address of the string data, or zero if nul.
STRPTR(xx$(1)) is equal to the pointer at VARPTR(xx$(1))
x& = PEEK(LONG, VARPTR(xx$(1)))
y& = STRPTR(xx$(1))
x& and y& are always equal.
Best regards,
Bob Zale
PowerBASIC Inc.
Leave a comment:
-
Hi Bob:
I was wondering: In your March 28th 5 PM post you state: "A 4 element array is four of those pointers which could point anywhere, because each could be any length, including nul, in which case the pointer would be zero. Effectively, you have string pointers with two levels of indirection." Is there any place in memory where those 4 pointers are in contiguous locations? Thanks! May you have a blessed day.
Sincerely,
Michael D Fitzpatrick
Leave a comment:
-
Originally posted by Michael Mattias View PostI guess you don't use the CVx/MKx$ functions as much as you did since UDTs replaced Ye Olde "FIELD" statements used in older BASIC to access numbers stored in disk files, but they can still be useful functions to have around.
MCM
Thanks the reminder, M. A year or so ago when John G and I were playing around with the Word Connection puzzle solver (Programming Forum), he was using packed strings for the data and this dummy didn't make the Mk/Cv connection then about packing strings. Now I see it clearly. Or maybe I don't. Close enough anyway.
==================================
"The difference between
'involvement' and 'commitment'
is like a ham-and-eggs breakfast:
the chicken was 'involved'
the pig was 'committed'."
unknown
==================================Last edited by Gösta H. Lovgren-2; 29 Mar 2009, 08:46 PM. Reason: "You have to set Rules *Boundries* and Leemitations." - Cesar Milan
Leave a comment:
-
It is for anyone who hasn't used it. Perhaps you would care to post an actual example demostrating how to use it.
CVL() allows you to assign the value of any four bytes to a long integer variable
Code:LOCAL pL AS LONG PTR, L AS LONG, S AS STRING LET L = 12345& LET S = MKL$(L) LET pl = STRPTR (S) ' point to the string MSGBOX @Pl
Code:UNION LongUnion L AS LONG S AS STRING * 4 END UNION LOCAL U AS LongUnion U.S = MKL$(12345&) MSGBOX FORMAT$(U.L)
MCM
Leave a comment:
-
Originally posted by Michael Mattias View PostIt is?
=========================================================
"Perfect love is rare indeed
for to be a lover will require that you continually have:
the subtlety of the very wise,
the flexibility of the child,
the sensitivity of the artist,
the understanding of the philosopher
the acceptance of the saint,
the tolerance of the scholar
and the fortitude of the certain."
Leo Buscaglia
=========================================================
Leave a comment:
-
Michael--
It would normally be something like:
LongVarArr(0) = CVL("xc" + CHR$(0,0))
However, if you have to go through a special group of assignment statements like this, I probably wouldn't waste the time here. I'd most likely put any extra code on the PowerBASIC side, as it will likely be much faster. I just tossed this out as a general idea which might help... never know about all the circumstances.
Best regards,
Bob
Leave a comment:
-
Bob was talking about packing strings into integers first (a fairly sophisticated programming process
For a two byte string, X% = CVI(string)
For any string up to four bytes, X& = CVL(LEFT$(string + SPACE$(4)), 4)
(SPACE$() can be $NUL or anything else, just make sure CVL() gets an argument of at least four characters).
To convert back to strings in called function, MKI$() or MKL$() can be used.
Leave a comment:
-
Michael, you are getting a type mismatch error because:
Originally posted by Michael Fitzpatrick View Post
Code:Dim LongVarArr(0 To 4) As Long [COLOR=red]'Array defined as Long Ingeger (a number)[/COLOR] LongVarArr(0) = "xc" [COLOR=red]'Assignig a string to an integer[/COLOR]
=================================
When your only tool is a hammer,
everything looks like a nail.
(FREDH - Salon's Table Talk)
=================================
Leave a comment:
-
Re Bob Zale's 8:12 PM suggestion
Hi Bob:
Thanks for the suggestion. I tried to implement it in the following Excel VBA code which will call the DLL to display the various values of the LongVarArr Array. Unfortunately when I tried to compile this Excel VBA code, the compiler gave me the message: "Type mismatch". I clicked the debug button of the message, and "LongVarArr(0) = "xc"" was highlighted. Apparently, Excel does not want to convert a text string to its value as a Long. How should I proceed with this code?
Code:Declare Function ProcTxtAsLngArry Lib "C:\PBWin90\MySamples\MySample1.dll" (ByRef x&) As String Sub TestPassTxtAsLngArrs() Dim LongVarArr(0 To 4) As Long LongVarArr(0) = "xc" LongVarArr(1) = "SR" LongVarArr(2) = "DIR" LongVarArr(3) = "COO" LongVarArr(4) = "xc" Dim AnswStr As String AnswStr = ProcTxtAsLngArry(LongVarArr(0)) MsgBox "AnswStr = " & AnswStr End Sub
Sincerely,
Michael Fitzpatrick
Leave a comment:
-
Your suggestion
Thanks for your suggestion. Since my motive here is speed, I will have to compare the execution time of packing the data (in Excel VBA which is interpreted, not compiled) and then unpacking it in my DLL with the time to pass an array of integers (already formed in Excel) to a DLL which then utilizes that array. Thanks again for your suggestion. May you have a blessed day.
Sincerely,
Michael Fitzpatrick
Leave a comment:
-
Could you not pass it as a delimiter'ed string? That is, join all the elements into one string with, say $TAB's between the elements and then just break it back apart when your DLL gets it?
Leave a comment:
-
If all of your string data is 4 bytes or less, don't use a numeric value which merely "represents" the string. Instead, use a Long Integer which is equal to the 4 bytes or less of string data. That totally eliminates the conversion step.
Leave a comment:
-
Passing string arrays from Excel to a PowerBASIC created DLL
Greetings! I thank everyone of you for your responses. My main purpose in creating the DLL was to take some slow-running interpreted code from an Excel VBA module and place it in a DLL which could run that code much faster, the code in a DLL being compiled rather than interpreted. Therefore my main objectives are speed, speed, and speed.
Now here is my bright idea for essentially transferring string information from Excel to a DLL which will process it. Since I have only 4 different types of strings: "xc", "COO", "SR" and "DIR", I will let these strings be represented by integers as follows:
Code:String Use this Integer Representation "xc" 4 "COO" 3 "SR" 2 "DIR" 1
OfcArry(0) = "xc"
OfcArry(1) = "DIR"
OfcArry(2) = "SR"
. . .
OfcArry(49) = "COO"
can instead be represented by an array of integers whose elements are:
IOfcArry(0) = 4
IOfcArry(1) = 1
IOfcArry(2) = 2
. . .
IOfcArry(49) = 3
and I believe that transferring this array of 50 integers from Excel to the PowerBASIC DLL is probably much faster than any of the schemes suggested or hinted at in this thread. Of course, if anyone has a faster and/or simpler scheme than this one, I will be happy to adopt it. May you have a blessed day.
Sincerely,
Michael Fitzpatrick
Leave a comment:
Leave a comment: