Discussion:
ByVal/ByRef confusion with strings
(too old to reply)
Mike McWhinney
2004-01-23 05:23:54 UTC
Permalink
Hello,

I am converting some VB code into Delphi 5.0. I have
come across a construct such as:

Public Declare Function USBm_DeviceVID Lib "USBm.dll"
(ByVal device As Byte) As Integer

This would translate to the following equivalent in Delphi:

Function USBm_DeviceVID(device:Byte):smallInt; stdcall; external
'USBm.dll'



However when I get to the following:

Function USBm_RecentError Lib "USBm.dll"
(ByVal errorstring As String) As Integer


I would tend to write this as:

Function USBm_RecentError(errorstring:widestring):smallint; stdcall;
external 'USBm.dll'

However, in the function description it says that 'errorstring' is
returned
with the value of the error. Shouldn't ByVal be ByRef instead in the
previous function? Or should the Delphi function have a var
parameter.

I understand that string parameters are passed as pointers in VB.

Could someone please clear this up for me?

Thanks.

Mike McWhinney
Rob Kennedy
2004-01-23 06:12:20 UTC
Permalink
Post by Mike McWhinney
Function USBm_RecentError Lib "USBm.dll"
(ByVal errorstring As String) As Integer
Function USBm_RecentError(errorstring:widestring):smallint; stdcall;
external 'USBm.dll'
However, in the function description it says that 'errorstring' is
returned
with the value of the error.
In the function description, does it give you a C declaration for the
function? Or do you have a C header file handy? I'd trust that more than
a VB declaration because of all the type changes VB does behind the scenes.
Post by Mike McWhinney
Shouldn't ByVal be ByRef instead in the previous function?
No. In VB, strings must *always* be passed ByVal to DLLs. No exceptions.
Ever.
Post by Mike McWhinney
Or should the Delphi function have a var parameter.
In my experience, the VB side is a ByVal String and the Delphi side is a
PChar, and VB will do the wide-to-narrow conversion automatically.
Sometimes the Delphi side is a PWideChar, so VB won't do the conversion.
I have no idea how it knows what to do.

Unless the documentation specifically states that the string argument is
a BSTR, I'd use PWideChar instead of WideString. If you test that, and
it crashes, then try WideString. If either one doesn't crash, but you
get giberish, then try PChar.
Post by Mike McWhinney
I understand that string parameters are passed as pointers in VB.
By default, everything is passed as pointers in VB -- ByRef is the
default argument-passing mode. When you specify ByVal, then is becomes
more like the way Delphi passes parameters by value. When a string is
passed by value in Delphi, it's still just a four-byte value on the
stack, which refers to the actual character data. I suspect VB works the
same way, so passing a string ByVal just passes a pointer to the first
character instead of a reference to a pointer to the first character,
which is what ByRef probably does.
--
Rob
J French
2004-01-23 15:06:17 UTC
Permalink
On Fri, 23 Jan 2004 00:12:20 -0600, Rob Kennedy <***@privacy.net>
wrote:

<snip>
Post by Rob Kennedy
No. In VB, strings must *always* be passed ByVal to DLLs. No exceptions.
Ever.
Totally untrue

The VB/Delphi passing of strings is (AFAIK) an undocumented area

However using StdCall :-

VB ByRef equals Delphi Var (Stack has pointer to pointer)

VB ByVal equals Delphi Const (Stack has pointer to string contents)

Interestingly in both cases a Unicode to ANSI conversion takes place
on the outbound trip, and an ANSI -> Unicrud is performed on the
return

This stuff is extremely dangerous, because of Delphi Reference
Counting.
VBDis
2004-01-25 08:31:12 UTC
Permalink
Post by J French
The VB/Delphi passing of strings is (AFAIK) an undocumented area
However using StdCall :-
VB ByRef equals Delphi Var (Stack has pointer to pointer)
VB ByVal equals Delphi Const (Stack has pointer to string contents)
Interestingly in both cases a Unicode to ANSI conversion takes place
on the outbound trip, and an ANSI -> Unicrud is performed on the
return
AFAIR the ByRef/ByVal keywords are used differently for VB strings and other
types. Strings always are passed by reference, ByVal only indicates that the
Unicode conversion should be performed, a reference to the ANSI string (PChar)
is passed to the subroutine, and the result is converted back into Unicode
after return. Using ByRef means to pass the VB (OLE, WideString) string
reference as it is.

So when the DLL expects an ByVal string, the Delphi equivalent would be a
PChar.

DoDi
J French
2004-01-25 10:12:42 UTC
Permalink
Post by VBDis
Post by J French
The VB/Delphi passing of strings is (AFAIK) an undocumented area
However using StdCall :-
VB ByRef equals Delphi Var (Stack has pointer to pointer)
VB ByVal equals Delphi Const (Stack has pointer to string contents)
Interestingly in both cases a Unicode to ANSI conversion takes place
on the outbound trip, and an ANSI -> Unicrud is performed on the
return
AFAIR the ByRef/ByVal keywords are used differently for VB strings and other
types. Strings always are passed by reference, ByVal only indicates that the
Unicode conversion should be performed, a reference to the ANSI string (PChar)
is passed to the subroutine, and the result is converted back into Unicode
after return. Using ByRef means to pass the VB (OLE, WideString) string
reference as it is.
No, if you want to pass a WideString you need to use the undocumented
StrPtr() or VarPtr()

Definitely from VB5 on, ByRef performs the Unicrud -> ANSI conversion
- it is directly equivalent to Delphi's StdCall Var S :String
Post by VBDis
So when the DLL expects an ByVal string, the Delphi equivalent would be a
PChar.
Yes, Delphi can take a PChar
- but if you are /very/ careful
Delphi can also take a Const S :String

The thing is that the core structure of a VB string matches that of a
Delphi ANSI string (after the U -> A Conversion)
However the VB strings are not reference counted ...

This stuff is not really documented, I only found out about it through
experimentation
Post by VBDis
DoDi
VBDis
2004-01-27 03:35:38 UTC
Permalink
Post by J French
No, if you want to pass a WideString you need to use the undocumented
StrPtr() or VarPtr()
Sorry, that's wrong.
Post by J French
Definitely from VB5 on, ByRef performs the Unicrud -> ANSI conversion
It was VB4/32, where the VB String type changed to BSTR. A BSTR is an OLE
Unicode (UTF-16) string, which is known in Delphi as a WideString.
Post by J French
The thing is that the core structure of a VB string matches that of a
Delphi ANSI string (after the U -> A Conversion)
That's also wrong. A VB ByVal String is an LPSTR, known in Delphi as PChar.
Post by J French
However the VB strings are not reference counted ...
Delphi WideStrings also are not reference counted, just to reflect the BSTR
specification!
Post by J French
This stuff is not really documented, I only found out about it through
experimentation
Post by VBDis
AFAIR the ByRef/ByVal keywords are used differently for VB strings and other
types. Strings always are passed by reference, ByVal only indicates that the
Unicode conversion should be performed, a reference to the ANSI string
(PChar)
Post by VBDis
is passed to the subroutine, and the result is converted back into Unicode
after return. Using ByRef means to pass the VB (OLE, WideString) string
reference as it is.
Have a look at e.g. "Passing Strings to a DLL Procedure" in VB5 Books Online.

Agreed, the Unicode/ANSI conversion is not well documented. I came across the
second conversion, back from ANSI into Unicode, when I found some strings
garbled after I had passed them ByVal to a procedure. This behaviour stands in
contrast to "ByVal", where one would expect that the passed value never could
be changed by the called procedure. In fact it was not the procedure that
garbled the string, but it was the first Unicode to ANSI conversion, and the
string was changed in my program by the second ANSI to Unicode conversion,
after return from the procedure.


But don't forget that I wrote the one and only working VB decompiler ;-)
I only was not sure whether I confused ByRef and ByVal, not using VB any more
since many years...

DoDi
J French
2004-01-27 11:41:27 UTC
Permalink
Post by VBDis
Post by J French
No, if you want to pass a WideString you need to use the undocumented
StrPtr() or VarPtr()
Sorry, that's wrong.
We must be talking at cross purposes
- I was saying VB5 on performs a Unicode to ANSI conversion when
passing both ByVal and ByRef

Strings in Variants do /not/ get converted - but that is not the point
Post by VBDis
Post by J French
Definitely from VB5 on, ByRef performs the Unicrud -> ANSI conversion
It was VB4/32, where the VB String type changed to BSTR. A BSTR is an OLE
Unicode (UTF-16) string, which is known in Delphi as a WideString.
Yes - I appreciate that
However if you pass a VB string as a parameter to Delphi, VB converts
it to an ANSI string
Post by VBDis
Post by J French
The thing is that the core structure of a VB string matches that of a
Delphi ANSI string (after the U -> A Conversion)
That's also wrong. A VB ByVal String is an LPSTR, known in Delphi as PChar.
It passes a pointer to the first byte of a String's data
- Delphi can pick this up as a StdCall Const
- seriously, try it if you do not believe me
Post by VBDis
Post by J French
However the VB strings are not reference counted ...
Delphi WideStrings also are not reference counted, just to reflect the BSTR
specification!
Hmm, probably to comply with AX
Post by VBDis
Post by J French
This stuff is not really documented, I only found out about it through
experimentation
We are definitely talking at cross purposes
Post by VBDis
Post by J French
Post by VBDis
AFAIR the ByRef/ByVal keywords are used differently for VB strings and other
types. Strings always are passed by reference, ByVal only indicates that the
Unicode conversion should be performed, a reference to the ANSI string
(PChar)
Post by VBDis
is passed to the subroutine, and the result is converted back into Unicode
after return. Using ByRef means to pass the VB (OLE, WideString) string
reference as it is.
Have a look at e.g. "Passing Strings to a DLL Procedure" in VB5 Books Online.
Agreed, the Unicode/ANSI conversion is not well documented. I came across the
second conversion, back from ANSI into Unicode, when I found some strings
garbled after I had passed them ByVal to a procedure. This behaviour stands in
contrast to "ByVal", where one would expect that the passed value never could
be changed by the called procedure. In fact it was not the procedure that
garbled the string, but it was the first Unicode to ANSI conversion, and the
string was changed in my program by the second ANSI to Unicode conversion,
after return from the procedure.
But don't forget that I wrote the one and only working VB decompiler ;-)
Yes, DoDi, I am well aware of that, but things changed with VB4 or
maybe VB5
- I only called Delphi DLLs from VB4 16 bit
- and picked up the parameters using ASM

However I have thoroughly investigated the VB5 calling conventions
Post by VBDis
I only was not sure whether I confused ByRef and ByVal, not using VB any more
since many years...
A VB string is passed as ANSI and is in the format LLLLDDDDDDDDDD
ByVal puts the location of the first D on the stack
ByRef puts the location of a pointer containing the address of D on
the stack

These are /really/ just what Delphi expects (under StdCall) for Const
and Var

Not only does VB perform the Unicode ANSI conversion for both ByVal
and ByRef strings, but it /also/ performs the same conversion for
Strings within a UDT

I think the reason for this is to obtain compatibility with the
Windows APIs - and they are StdCall
VBDis
2004-01-28 23:45:24 UTC
Permalink
Post by J French
We must be talking at cross purposes
Obviously we have very different opinions about what we're talking about.
Post by J French
- I was saying VB5 on performs a Unicode to ANSI conversion when
passing both ByVal and ByRef
Wrong, the Unicode to ANSI conversion only occurs with ByVal, not with ByRef.
Post by J French
Strings in Variants do /not/ get converted - but that is not the point
Nobody was talking about Variants before. This data type is also supported by
Delphi, for OLE/COM/ActiveX compatibility (or however MS likes to call it
tomorrow).
Post by J French
It passes a pointer to the first byte of a String's data
Just as I said, as an LPSTR ;-)
Post by J French
- Delphi can pick this up as a StdCall Const
- seriously, try it if you do not believe me
I don't understand how a data/argument type is related to a calling
convention???

Of course non-OLE procedures must be flagged in VB with StdCall, because the
default VB/32 calling convention is SafeCall, as is appropriate for dealing
with OLE objects. Don't forget that VB is an OLE wrapper! But Delphi also
supports the SafeCall convention...
Post by J French
- I only called Delphi DLLs from VB4 16 bit
- and picked up the parameters using ASM
VB4/16 still uses the old ANSI strings, not Unicode strings.
Post by J French
However I have thoroughly investigated the VB5 calling conventions
Maybe not thoroughly enough?
Post by J French
A VB string is passed as ANSI and is in the format LLLLDDDDDDDDDD
ByVal puts the location of the first D on the stack
ByRef puts the location of a pointer containing the address of D on
the stack
You shouldn't guess so much about the internals of VB. Just like Delphi dynamic
strings are compatible with LPSTR, when passed as PChars, VB strings and
argument types are designed to serve the same purpose. And for that purpose the
bytes before the given address are not for use by the called procedure.
Post by J French
Not only does VB perform the Unicode ANSI conversion for both ByVal
and ByRef strings,
I'm tired to refrain that this is simply wrong :-(
Post by J French
but it /also/ performs the same conversion for
Strings within a UDT
Just for the same reason: LPSTR compatibility.
Post by J French
I think the reason for this is to obtain compatibility with the
Windows APIs - and they are StdCall
This is correct in so far, as SafeCall is only used with OLE - and OLE is the
primary interface to which VB/32 is compatible, both in data types and calling
conventions.

DoDi
J French
2004-01-29 09:18:34 UTC
Permalink
Post by VBDis
Post by J French
We must be talking at cross purposes
Obviously we have very different opinions about what we're talking about.
Ok - here is a little demo

( Delphi4 P and VB5 SP3 )

===== Delphi DLL =====

library Project1;

uses
SysUtils,
Classes,
Dialogs;

Procedure Test(Const S1:String; Var S2:String );StdCall;
Begin
ShowMessage( S1 );
ShowMessage( S2 );
End;

Exports Test;

begin
end.

===== VB Form1 Code =====

Option Explicit

Private Declare Sub Test _
Lib "project1.dll" _
(ByVal S1 As String, _
ByRef S2 As String)

Private Sub Command1_Click()
Dim S1$, S2$
ChDir App.Path

S1$ = "This is ByVal"
S2$ = "And this is ByRef"
Call Test(S1$, S2$)
End Sub

=========================

You will see that the Delphi code picks up both strings perfectly

I would not use the code like this, because of reference counting
- I would copy the strings byte by byte
J French
2004-01-30 12:03:07 UTC
Permalink
Post by J French
Post by VBDis
Post by J French
We must be talking at cross purposes
Obviously we have very different opinions about what we're talking about.
Ok - here is a little demo
Just to prove a point
(which I consider /very/ important in this area
- since the whole thing is so poorly documented)

Here is an extended version of the Demo
- it demonstrates that UDTs are definitely converted
- also that Strings are /definitely/ converted
regardless whether they go ByVal or ByRef

====== Delphi DLL ======

library Project1;

uses
SysUtils,
Classes,
Dialogs;


Procedure Test(Const S1:String; Var S2:String );StdCall;
Begin
ShowMessage( S1 );
ShowMessage( S2 );
End;

Type TRec = Packed Record
S :Array [0 .. 19] Of Char;
End;

Procedure TestUDT( Var Rec:TRec );StdCall;
Begin
ShowMessage( Rec.S );
Rec.S[0] := 'A';
Rec.S[1] := 'B';
End;

Procedure TestShortStr(Const S1:ShortString;
Var S2:pShortString );StdCall;
Begin
ShowMessage( S1 );
ShowMessage( S2^ );
S2^ := 'Back from Delphi';
End;

Exports Test,
TestUDT,
TestShortStr;

begin
end.

====== VB Form1 Code ======

Option Explicit

Private Type TRec
S As String * 20
End Type

Private Declare Sub Test _
Lib "project1.dll" _
(ByVal S1 As String, _
ByRef S2 As String)

Private Declare Sub TestUDT _
Lib "project1.dll" _
(ByRef Rec As TRec)

Private Declare Sub TestUDT1 _
Lib "project1.dll" _
Alias "TestUDT" _
(ByRef B As Byte)

Private Declare Sub TestShortStr _
Lib "project1.dll" _
(ByVal S1 As String, _
ByRef S2 As String)


' Send Unicode Strings ByVal and ByRef
' Demonstrates that they become ANSI
Private Sub Command1_Click()
Dim S1$, S2$
ChDir App.Path

S1$ = "This is ByVal"
S2$ = "And this is ByRef"
Call Test(S1$, S2$)
End Sub

' Send and modify a Unicode String in a UDT
' Demonstrates that it becomes ANSI for Delphi
Private Sub Command2_Click()
Dim Rec As TRec
ChDir App.Path

Rec.S = "12345678901234567890"
Call TestUDT(Rec)
MsgBox Rec.S
End Sub

' Send a Simple Byte Array to Delphi
' - when Delphi expects a TRec
' Demonstrate that Delphi is getting ANSI data
Private Sub Command3_Click()
Dim B(1 To 20) As Byte
Dim L9&
ChDir App.Path

For L9 = 1 To 20
B(L9) = Asc("A") + L9 - 1
Next

Call TestUDT1(B(1))

End Sub

' Send Spoofed ShortStrings ByVal And ByRef
' Demonstrate that Delphi receives Bytes not Unicode
' Also that ByRef Strings get ANSI -> Unicode on return
Private Sub Command4_Click()
Dim S1$, S2$, L%
ChDir App.Path

S1$ = Chr$(10) + "ByVal xxxxxxxxxxxx"
S2$ = Chr$(10) + "ByRef xxxxxxxxxxxx"
Call TestShortStr(ByVal S1$, S2$)

L = Asc(S2$)
MsgBox "Len:" + Str$(L) + ":" + S2$ + Chr$(13) _
+ "[" + Mid$(S2$, 2, L) + "]"


End Sub
VBDis
2004-01-31 20:34:56 UTC
Permalink
Post by J French
You will see that the Delphi code picks up both strings perfectly
Okay, you convinced me. Thanks for this update :-)

There has been a dramatic change between VB4 and VB5, and the VB5 docs still
describe the VB4 behaviour.

In VB4/32 strings are passed as I have described.

In VB5, and presumably later versions, strings are always converted to ANSI
prior to a call to an external procedure, and are converted back into Unicode
after return from the procedure, regardless of ByRef or ByVal.

Now I'm even more happy that I stopped using VB after version 3 ;-)

DoDi
J French
2004-02-01 18:01:19 UTC
Permalink
Post by VBDis
Post by J French
You will see that the Delphi code picks up both strings perfectly
Okay, you convinced me. Thanks for this update :-)
I should have posted an example earlier
- it just that I had had a few bevvies and was not really up to coding
- IMO one should post examples - not rhetoric

This whole area seems either undocumented, or impossible for me to
find documentation on it.

The stuff I found out was by playing with code, and largely by
accident.
Post by VBDis
There has been a dramatic change between VB4 and VB5, and the VB5 docs still
describe the VB4 behaviour.
Yes, I think that is right

I only really probed into VB4 16bit
- and ironically got into Delphi because I needed a way to add ASM to
VB - I had two weeks to get a product out, and needed fast string
searching.
Delphi1 was pretty cruddy, but I got Delphi2 for the licence
- and got hooked
Post by VBDis
In VB4/32 strings are passed as I have described.
In VB5, and presumably later versions, strings are always converted to ANSI
prior to a call to an external procedure, and are converted back into Unicode
after return from the procedure, regardless of ByRef or ByVal.
And even when they are part of a UDT - which is fascinating

This whole Unicode mess is quite incredible, MS built it into VB, yet
not into the operating system (95/98).
Post by VBDis
Now I'm even more happy that I stopped using VB after version 3 ;-)
There are one or two rather good things about VB5/6
- UserControls are useful - really useful
- and there is rudimentary polymorphism via 'Implements'
- Byte Arrays are amazingly fast - actually as fast as Delphi

However, Delphi is infinitely more flexible, since it deliberately
exposes things rather than trying to keep one away from them.

Curiously, I learnt more of what VB is really all about from Delphi

I still think that Borland should produce a version of VB ...
VBDis
2004-02-03 00:44:20 UTC
Permalink
Post by J French
Post by VBDis
In VB5, and presumably later versions, strings are always converted to ANSI
prior to a call to an external procedure, and are converted back into
Unicode
Post by VBDis
after return from the procedure, regardless of ByRef or ByVal.
And even when they are part of a UDT - which is fascinating
VB has some nice features, which I really miss in Delphi. Like Get and Put for
simple binary record I/O, including dynamic strings and arrays!
Post by J French
This whole Unicode mess is quite incredible, MS built it into VB, yet
not into the operating system (95/98).
MS offers both ANSI and Unicode version of almost all API's, and now also a
third .NET version. But in the systems only one set is implemented (ANSI for
9x, Unicode for all other Windows), the other set are wrappers which do the
same ANSI/Unicode conversion as does VB.
Post by J French
I still think that Borland should produce a version of VB ...
Heaven, NO, please! ;-)

DoDi
J French
2004-02-03 11:43:55 UTC
Permalink
Post by VBDis
Post by J French
Post by VBDis
In VB5, and presumably later versions, strings are always converted to ANSI
prior to a call to an external procedure, and are converted back into
Unicode
Post by VBDis
after return from the procedure, regardless of ByRef or ByVal.
And even when they are part of a UDT - which is fascinating
VB has some nice features, which I really miss in Delphi. Like Get and Put for
simple binary record I/O, including dynamic strings and arrays!
Yes, in Delphi one has to do a bit more fiddling for this
Post by VBDis
Post by J French
This whole Unicode mess is quite incredible, MS built it into VB, yet
not into the operating system (95/98).
MS offers both ANSI and Unicode version of almost all API's, and now also a
third .NET version. But in the systems only one set is implemented (ANSI for
9x, Unicode for all other Windows), the other set are wrappers which do the
same ANSI/Unicode conversion as does VB.
Ah, of course :-

VB holds Unicode Data
VB converts Unicode to ANSI
XP ApiA converts ANSI to Unicode and calls ApiW
ApiW returns Unicode to ApiA
ApiA converts Unicode to ANSI then returns ANSI to VB
VB converts ANSI to Unicode

Clever people those designers at Microsoft
Post by VBDis
Post by J French
I still think that Borland should produce a version of VB ...
Heaven, NO, please! ;-)
But you would have such fun un-picking it ...
Post by VBDis
DoDi
VBDis
2004-02-07 03:38:27 UTC
Permalink
Post by J French
Ah, of course :-
VB holds Unicode Data
VB converts Unicode to ANSI
XP ApiA converts ANSI to Unicode and calls ApiW
ApiW returns Unicode to ApiA
ApiA converts Unicode to ANSI then returns ANSI to VB
VB converts ANSI to Unicode
Clever people those designers at Microsoft
This is why VB should be used for what it was designed for: OLE (ActiveX...).
Then the VB data types are "native" OLE types, which deserve no conversion at
all.

All programs and languages have problems with API functions, because regardless
of your choice of the A or W versions, your clients will use just the system
that requires additional conversions :-(

DoDi
J French
2004-02-07 07:32:21 UTC
Permalink
On 07 Feb 2004 03:38:27 GMT, ***@aol.com (VBDis) wrote:

<snip>
Post by VBDis
Post by J French
Clever people those designers at Microsoft
This is why VB should be used for what it was designed for: OLE (ActiveX...).
Then the VB data types are "native" OLE types, which deserve no conversion at
all.
That is not really practical when it comes to calling APIs
- and anyway like most languages under Windows, VB is largely a front
for calling APIs
Post by VBDis
All programs and languages have problems with API functions, because regardless
of your choice of the A or W versions, your clients will use just the system
that requires additional conversions :-(
I'm slightly at a loss as to what the MS designers were smoking when
they designed VB5 and VB6

They knew perfectly well that Win95 and Win98 were the prevalent
operating systems that it would be run on
- and both of those were very much ANSI

And as soon as they get reasonable distribution of a Unicode OS (XP)
they decide to trash VB and replace it with something totally
different

Actually I have a fair idea of what was going on, prior to the IBM PC,
occidental machines had very little market penetration in Far Eastern
locales (at that time mainly Japan)
- as a reaction, MS have devoted a disproportional amount of effort
into trying to 'localize' their software
- for them localization is aknee jerk reaction, rather than a decision
based on practical considerations (AKA reality)
VBDis
2004-02-10 07:19:43 UTC
Permalink
Post by J French
I'm slightly at a loss as to what the MS designers were smoking when
they designed VB5 and VB6
The history of VB, as I see it:

VB was developed by Cooper Group, codename ThunderBasic. You'll find according
hints in the binaries of the early VB versions. The original version was a
text-based interpreter, most probably. At least the VB Setup programs of the
early VB versions were stored as text files, but both the text file and
interpreter were hidden from the user.

At that time it was quite easy to control crazy setup programs, because after
starting Setup.exe all the unpacked components have been available in the TEMP
folder, so that the user could step in the interpreter (unpacked setup.exe)
through the setup1.bas program. Starting with VB3 the setup1 programs became
compiled VB code, the setup wrapper unpacked the VBRUN300.DLL and the
setup1.exe, and then started setup1. This was the time when I started working
on a VB decompiler, because I was tired of finding my system damaged after
installing any VB3 application.

In the early VB versions (1..3) MS tried to extend the functionality of VB
itself, and to improve its Windows API interface, including DDE support. At the
same time the VB interpreter was incorporated into the Office applications
(Word, Access...), and the development of the Office API (from DDE to OLE to
COM to ActiveX...) was reflected in the following VB versions. The first few
Office versions lacked real interoperability, since every VBA interpreter had
its own syntax and RTS extensions, as well as its own storage format for the
binary p-code. VB, and not VBA, was the first development system that really
could "automate" (talk to) all the Office application. This was possible due to
the slowly evolving OLE standard, and the exposure of OLE classes by the Office
applications.

From that time on VB was the dedicated Office automation tool, and all the
changes from VB3 to VB4 and later versions are the natural consequences of the
evolution of the Office package and the MS automation object model. The
introduction of Unicode into VB corresponds to the according change in the
Office tools, when e.g. the version of Word jumped from 2.0 to 6.0. In my
decompilation attempts for VB4 I stumbled over an almost unknown fact, namely
that the 32 bit VB forms, controls, and classes, all are veritable OLE classes
- i.e. all newer VB versions are inseparable from OLE, ActiveX or however this
beast may be named in the future.

Some time ago MS started another unification attempt, with .NET. In that model
not only the automation interface was renewed for another time, but also the VB
runtime system was extended into a much more general runtime environment (CLI =
Common Language Infrastructure, CTS=Common Type System). In that move the
traditional VB syntax was broken, in favor of a C-ish programming model
(classes, exceptions...). This change was not so obvious in VC and other
languages, because MS didn't want to risk to frustrate VC and VJ coders in the
same way; instead they introduced C# and J# (etc.) as new languages, which may
or may not have been accepted by the coders by now; I dunno because I don't
watch the .NET activities attentively. I also don't know why MS decided to
rename VB into VB.NET, and not into B#, perhaps because they didn't want to
risk that the VB coders could become aware of the fact that they use an BASIC
dialect <shudder>, with a touch of being a primitive language, slow, unsafe and
whatever more unpleasant attributes are associated with BASIC.


I hope that now you finally understand why I, and other people, consider VB as
being an OLE wrapper.

DoDi
J French
2004-02-10 08:40:19 UTC
Permalink
On 10 Feb 2004 07:19:43 GMT, ***@aol.com (VBDis) wrote:

<snip>
Post by VBDis
I hope that now you finally understand why I, and other people, consider VB as
being an OLE wrapper.
DoDi
Thanks - that was very interesting

I had never considered VB as a byblow (by product) of the VBA used in
MS Office Automation

It makes perfect sense - in a strange Microsoftish way ...

Jeremy Collins
2004-01-23 08:29:29 UTC
Permalink
Post by Mike McWhinney
Function USBm_RecentError Lib "USBm.dll"
(ByVal errorstring As String) As Integer
Function USBm_RecentError(errorstring:widestring):smallint; stdcall;
external 'USBm.dll'
However, in the function description it says that 'errorstring' is
returned
with the value of the error. Shouldn't ByVal be ByRef instead in the
previous function? Or should the Delphi function have a var
parameter.
Assuming it's a C DLL, your safest bet is to pass a string buffer
to the function:

function USBm_RecentError(errorstring : PWideChar):smallint; stdcall;
external 'USBm.dll';

var
ErrBuffer : array[0..255] of WideChar;
iRes : integer;
begin
FillChar(ErrBuffer, SizeOf(ErrBuffer), 0);
iRes := USMm_RecentError(ErrBuffer);
:
end;

You can treat the buffer a string as far as Delphi is concerned,
e.g. you could pass it to ShowMessage etc.

A C program calling a function such as this will typically allocate
memory for a char array, and pass a pointer to the first array
element.

Make sure it really is a widechar array it is expecting - do you
have the .h file that accompanies the DLL?
--
jc

Remove the -not from email
Continue reading on narkive:
Loading...