Michael
The address of what you call the string handle in BYVAL is the first character of the string, all other handle info is a negative of that pointer.
Lets consider just a local string if you do VARPTR on it you get an address (sa &H10000) if you then retrieve the contents of that address you will then get another address the (STRPTR say &H20000) and if you then retrieve the contents of that address you will get the first character of the string no exceptions
Thats why the very simple EXE and DLL I posted work as does the second simple pair I posted which reverses the types. To quote you try it.
John
Announcement
Collapse
No announcement yet.
PB DLL wants dynamic string BYVAL
Collapse
X
-
I don't think that is quite correct. In both cases the address on the stack will point to the first byte of the string
In the case of a PB function ...
Code:FUNCTION FOO (BYVAL X AS STRING)
A PB CALL FOO (BYVAL X [a STRING] ) will pass that.
Except I'm not sure what PB will do if Foo is declared "AS ASCIIZ"... it may "help" by silently converting this call to the address of the first byte of of a copy of the data. (I would much prefer a compile-time "parameter mismatch error" to "helping" without being asked in a case like this.)
A VB CALL (BYVAL X [A STRING]) will pass the address of first byte of copy of string DATA, AFIAK, always.
MCM
Leave a comment:
-
-
Michael
VB:
Code:
DECLARE Foo...( BYVAL X AS STRING
CALL Foo (stringvar)Passes address of first byte of copy of string data.
PB
Code:
#COMPILE DLL
FUNCTION Foo (BYVAL X AS STRING) EXPORT ....Expects the value of the string handle on the stack.
Call PB "FOO" using "VB", PB gets a non-zero value (the address of the copy), which it then tries to use in string functions, only to find out that the passed value is NOT a string handle and therefore any memory references inherent in that string hande are worthless. GPF is probably the best result you can hope for (silent corruption of data being worse).
This may be the problem as however SQlitening in the line following the one I quoted does an IIF based on LEN so depending where VB saved the BYREF ASCIIZ it creates that might cause a GPF.
I suspect the best solution given its goal is for SQlitening to change its BYVAL STRING functions to BYREF ASCIIZ which as I have already shown would not require any existing PB calls to be changed.
John
Leave a comment:
-
-
See post #1 which showed this at the end of the posting.
But I said it more succinctly and eloquently. I guess that means I get that job writing documentation instead of you!
MCM
Leave a comment:
-
-
Seems to me this is a real simple problem and you have found the solution:
GOAL
Starting from VB module, call a PB-created function which wants a 'BYVAL AS STRING' parameter.
SOLUTION
Create a PB "helper" function to accept call parameter "AS ASCIIZ"; this function simply copies the passed parameter to a dynamic string variable and calls the ultimate target function passing that temp var BYVAL.
Declare the helper function to use "BYVAL AS STRING" in the VB program, to result in the helper function receiving what PB will handle when told a parameter is AS ASCIIZ.
Too bad no one thought of this sooner, like maybe in about post # 13 on page one.
Leave a comment:
-
-
I will only call SQLitening from PB. Have had zero problems doing this.
If using VB6 a call to a PB/DLL that calls SQLitening.
This allows writing all code in PB which is what I wanted anyway.
VB'ers should not consider calling it directly from VB6 stable.
Leave a comment:
-
-
>GPF's compiled. Environment lasts a bit longer
Well, if both crash and burn sooner or later, you can pretty much exclude execution envirornment as a factor... for now.
However, I would find a way to do all testing using compiled EXE to eliminate that factor completely.
Leave a comment:
-
-
>This code GPF's immediately if the SQLitening.Dll is called directly from VB6
From VB-IDE? Or from VB6-compiled EXE?
IIRC VB-IDE does not handle externals the same in both; may be chasing down different problems!
Leave a comment:
-
-
(No POKE? Really? )
Not a fault of our own, but more the teachers before us.
Its up to the student to learn the mistakes of the past.
Leave a comment:
-
-
From a simple example or as simple as I can make it without confusing everyone (including myself, which is probably why I tried to allow for Asciiz vs string in my function)
I tried to comment as much as possible, and should be straight-forward the difference between VB6 and PB.
Also take special note that in VB6 whenever you declare an Alias that is capitalized the same as the internal function, it disappears in code, so you can NOT see it (Yet another thing that annoys me, that what I can not see, I can not troubleshoot)
Anyways, give it a shot and see if it makes more sense.Attached Files
Leave a comment:
-
-
VB:
Code:DECLARE Foo...( BYVAL X AS STRING CALL Foo (stringvar)
PB
Code:#COMPILE DLL FUNCTION Foo (BYVAL X AS STRING) EXPORT ....
Call PB "FOO" using "VB", PB gets a non-zero value (the address of the copy), which it then tries to use in string functions, only to find out that the passed value is NOT a string handle and therefore any memory references inherent in that string hande are worthless. GPF is probably the best result you can hope for (silent corruption of data being worse).
The reason it seems something is corrupt is, because something is corrupt!
Call the same Foo function from a PB program, using the correct PB DECLARE:
Code:DECLARE FUNCTION FOO ... (BYVAL X AS STRING)
I provided code to call PB function as written, except apparently there is no such thing as POKE in VB. (Copymemory should work, though).
(The whole way VB handes strings is, well, "strange," at least for refugees from GW-BASIC and QuickBASIC. I can see where using Unicode internally makes sense for a product which must support multiple languages and character sets, though)
What's really hard to believe is the Microsoft did not offer a null-terminated string datatype (the PB "ASCIIZ") in the VB product - a product DESIGNED for use in the Windows environment. I hope whatever the designer was smoking at the time was worth it.
MCM
(No POKE? Really? )
Leave a comment:
-
-
I am not sending any empty strings. I'm always passing all 3 values.
This code GPF's immediately if the SQLitening.Dll is called directly from VB6. It works all the time when called from mConnect/mDisconnect in
the connect.dll written in PB9.
Also, the SQLitening.log is not updated if called from VB6 which indicates there is something getting lost or corrupted like a file handle.
If mConnect is used then mDisconnect should also be used.
Code:Option Explicit 'These 2 are used to directly call from VB6. Do not work correctly. Private Declare Function slConnect Lib "SQLitening.DLL" (Optional ByVal rsServer As String, Optional ByVal rlPort As Long, Optional ByVal rsModChars As String) As Long Private Declare Sub slDisconnect Lib "SQLitening.DLL" () 'These 2 work by calling a dll that calls SQLitening.Dll Private Declare Function mConnect Lib "connect.dll" Alias "MCONNECT" (Optional ByVal rsServer As String, Optional ByVal rlPort As Long, Optional ByVal rsModChars As String) As Long Private Declare Sub mDisconnect Lib "connect.dll" Alias "MDISCONNECT" () Private Sub Form_Load() Dim x As Long Dim sIP As String Dim PortNumber As Long Dim rsModChars As String Dim result As Long ChDir "c:\sql6\bin" For x = 1 To 1 sIP = "68.13.44.154" PortNumber = 51234 rsModChars = "E0" result = slConnect(sIP, PortNumber, rsModChars) 'GPF 'result = mConnect(sIP, PortNumber, rsModChars) 'works Next MsgBox "Click to end" slDisconnect 'does NOT write to SQLitening.log 'mDisconnect 'writes to SQLitening.log Unload Me End End Sub 'PB CODE 'DECLARE FUNCTION mConnect LIB "connect.dll" (OPT sServer AS ASCIIZ, _ OPT BYVAL PortNumber AS LONG, OPT rsModChars AS ASCIIZ) AS LONG 'DECLARE FUNCTION mOpen LIB "connect.dll" (OPT rsFileName AS ASCIIZ, OPT rsModChars AS ASCIIZ) AS LONG 'Declare Sub mDisconnect Lib "connect.dll" () 'FUNCTION mConnect(OPT rsServer AS ASCIIZ, OPT BYVAL PortNumber AS LONG, OPT rsModChars AS ASCIIZ) EXPORT AS LONG ' LOCAL result AS LONG ' result = slConnect(ByVal rsServer, ByVal PortNumber, ByVal rsModChars) ' FUNCTION = result 'End Function 'SUB mDisconnect EXPORT ' slDisconnect 'End Sub
Last edited by Mike Doty; 23 Oct 2008, 04:50 PM.
Leave a comment:
-
-
Mike
I will start again, here is a very simple DLL using BYVAL as string
Code:#COMPILE DLL #DIM ALL SUB test(BYVAL t AS STRING) EXPORT ? t END SUB
Code:DECLARE SUB test LIB "test.dll" ALIAS "TEST" ( t AS ASCIIZ)
Code:DECLARE SUB test LIB "test.dll" ALIAS "TEST" (BYVAL t AS STRING)
Code:PUBLIC DECLARE SUB test LIB "test.dll" ALIAS "TEST" (BYVAL t AS STRING)
As you now say the calls succeed the first two times so the concept of the pass is obviously correct.
From your “fix” intermediate DLL and looking at the code of Sqlitening it looks like you passed an empty string (different in PB and VB), if not its far more complicated.
John
Leave a comment:
-
-
Originally posted by Michael Mattias View Post>IF rsServer = $NUL THEN EXIT FUNCTION
Assuming this is written in PowerBASIC, that will work but only because PB treats NULL string handles as NUL. (or maybe it's the OLE functions which do).
Actually VB being forgiving of us amateur programmers handles optionals very well.
May I explain to a guru how I understand PB handles optional strings. You seem to understand that for strings there is VARPTR and an STRPTR, so I assume you understand that any string function like the line of code quoted first gets the equivalent of VARPTR to find the string details so it can check for the NUL. But as it was optional and not passed the stack contains a VARPTR entry of 0 and thus a CERTAIN GPF. Gee PB 101.
Leave a comment:
-
-
quote:
It is also important to note that a string BYVAL in PowerBASIC is not the same thing as a string BYVAL in Visual Basic. That is, since PowerBASIC natively supports ASCIIZ strings, it does not convert a dynamic string into an ASCIIZ string, as does Visual Basic. PowerBASIC does exactly what you tell it: it makes a copy of the string, and passes the new string handle to the API or DLL. For example, if you have the following DECLARE statement in a Visual Basic module:
Declare Sub Hello Lib "HELLO.DLL" Alias "Hello" (Byval Greetings$)
…then in PowerBASIC, you would create an almost identical exported Sub, but with the BYVAL clause removed, and the string parameter changed to ASCIIZ. For example:
' PB code
#COMPILE DLL
DECLARE SUB Hello LIB "HELLO.DLL" ALIAS "Hello" (Greetings AS ASCIIZ)
SUB Hello ALIAS "Hello" (Greetings AS ASCIIZ) EXPORT
MSGBOX Greetings
END SUB
I pass all parameters from VB6 so that is not a problem.
Do you want me to write a program that GPF's if not done like PowerBASIC suggests?
John,
Please post the DECLARE statement used to compile the DLL.
The code uses BY VAL STRING not the declare statement in your posting.Last edited by Mike Doty; 23 Oct 2008, 02:41 PM.
Leave a comment:
-
-
>IF rsServer = $NUL THEN EXIT FUNCTION
Assuming this is written in PowerBASIC, that will work but only because PB treats NULL string handles as NUL. (or maybe it's the OLE functions which do).
If you made that function instead
Code:FUNCTION slConnect ALIAS "slConnect" (OPTIONAL rsServer AS ASCIIZ, _ OPTIONAL BYVAL rlPort AS LONG, _ OPTIONAL rsModChars AS ASCIIZ) EXPORT AS LONG
To check if optional ASCIIZ (or any other BYREF param) was or was not passed you test the address...
Code:IF VARPTR(rsServer) THEN ' param was passed IF rsServer = $NULL THEN ..... ELSE 'twas not passed END IF
MCM
Leave a comment:
-
-
I need sleep so a little more for you to consider. From the code
Code:FUNCTION slConnect ALIAS "slConnect" (OPTIONAL BYVAL rsServer AS STRING, _ OPTIONAL BYVAL rlPort AS LONG, _ OPTIONAL BYVAL rsModChars AS STRING) EXPORT AS LONG 'comments and other lines removed IF rsServer = $NUL THEN EXIT FUNCTION ' run local if passed as $NUL
I will read your comments tommorow.
Leave a comment:
-
-
Please read, yes the code shown is all PB but I posted this as well "Just did another VB6 test with it that called it 20 times with different text and no problems, so can't see how the problem is a DLL Wanting BYVAL as STRING from VB" Try it!!
So many other possibles in this particularly on slConnect where all variables are optional. VB has always seemed to handle not passing an optional string rather well, in PB its version dependant. So are you not passing any of the optional parameters on your third call, particularly the first as it is a string, then I wouldnt be surprised if it GPF'd.
Leave a comment:
-
Leave a comment: