[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

microsoft.public.vb.general.discussion

byVal or byRef when getting string in passed param to dll function

Andrej Viktorovich

7/10/2012 11:25:00 AM

Trying to get string to Visual Basic compiled program from *.dll compiled vc++

I have function in dll:


extern "C" int _stdcall TstCharReturn(char* c)
{
long long l = 1234567890;
sprintf(c,"%010lld",l);
return true;
}

I have declaration in VB program:

Declare Function TstCharReturn Lib "myLib" Alias "TstCharReturn" (ByRef c As String) As Boolean

Function calling procedure:

Dim s As String
s = "0987654321"
r = TstCharReturn(s)
LogIt(s)

And my VB app crash with message

"Attempted to read or write protected memory. This is often an indication that other memory is corrupt"

In case when i declare function by changing return string to "ByVal" (..."TstCharReturn" (ByVal c As String)...) everything goes fine. But logic says that I must use ByRef.


What's a problem with ByRef?
3 Answers

ObiWan

7/10/2012 3:27:00 PM

0


> Declare Function TstCharReturn Lib "myLib" Alias
> "TstCharReturn" (ByRef c As String) As Boolean

If you use ByRef, VB will pass the "string descriptor"; this is fine as
long as the "receiving code" knows it and knows how to handle it; this
isn't your case, the C code is expecting a pointer to the string, so in
this case, you'll need to use the "ByVal" keyword which will instead
pass the pointer to the string (storage)

Schmidt

7/10/2012 4:12:00 PM

0

Am 10.07.2012 13:25, schrieb Andrej Viktorovich:

> What's a problem with ByRef?

With ByRef As String, VB is passing the VarPtr(strVariable)
(the descriptor, as ObiWan already said) ...
Whereas with ByVal As String in the Declare, VB is passing
the StrPtr(strVariable) ...the current "Pointer-to-strContent"
which the Descriptor holds.

So at the C-side of things, you will have to dereference
the incoming "Pointer-to-a-Pointer" first (in case of ByRef).

There's an additional thing which takes place under the hood:
VB-Strings are of type BSTR, which hold 16Bit-WChars...
so these strings pointers are not passed directly to the
C-Side of things - instead an implicite ANSI-conversion
takes place - and VB is then passing the appropriate
*temporary* Pointer to the ANSI-Content, or the Tmp-Variables
Pointer which holds the Pointer to the ANSI-Content directly
(depending on ByVal or ByRef) to the Dll-Function.

But that 8BitChar-conversion-mechanism works transparently,
so what's statet on top (with regards to either VarPtr
or StrPtr-passing in case of ByRef or ByVal) remains true
nonetheless.

So the mentioning of this ANSI-stuff was just for completeness...
In case you do declare ByVal - and then compare for example
the value of the incoming Char-Pointer at the C-Side, with
the Value VB spits out when you do:
Debug.Print StrPtr(strVariable).
Then the Value of the CharPtr on the C-side of things will
always differ from what Debug.Print StrPtr(strVariable)
will report at the VB-End... as said, this is due to the
"ANSI-automatics" VB performs under the hood, in case
you define a Param within a VB-DllFunc-Declare "As String"
(no matter, if ByRef or ByVal).

If you want to avoid this VB-ANSI-automatic (e.g. when
your C-Dlls understands "Unicode on Windows" and was set up,
to work with WChars), then just define the String-Params in
your VB-Declare "ByVal As Long" - and pass StrPtr(strVariable)
instead of just strVariable from the VB-end.

Olaf


Ralph

7/10/2012 6:02:00 PM

0

On Tue, 10 Jul 2012 18:11:50 +0200, Schmidt <sss@online.de> wrote:

>Am 10.07.2012 13:25, schrieb Andrej Viktorovich:
>
>> What's a problem with ByRef?
>
>With ByRef As String, VB is passing the VarPtr(strVariable)
>(the descriptor, as ObiWan already said) ...
>Whereas with ByVal As String in the Declare, VB is passing
>the StrPtr(strVariable) ...the current "Pointer-to-strContent"
>which the Descriptor holds.
>
>So at the C-side of things, you will have to dereference
>the incoming "Pointer-to-a-Pointer" first (in case of ByRef).
>
>There's an additional thing which takes place under the hood:
>VB-Strings are of type BSTR, which hold 16Bit-WChars...
>so these strings pointers are not passed directly to the
>C-Side of things - instead an implicite ANSI-conversion
>takes place - and VB is then passing the appropriate
>*temporary* Pointer to the ANSI-Content, or the Tmp-Variables
>Pointer which holds the Pointer to the ANSI-Content directly
>(depending on ByVal or ByRef) to the Dll-Function.
>
>But that 8BitChar-conversion-mechanism works transparently,
>so what's statet on top (with regards to either VarPtr
>or StrPtr-passing in case of ByRef or ByVal) remains true
>nonetheless.
>
>So the mentioning of this ANSI-stuff was just for completeness...
>In case you do declare ByVal - and then compare for example
>the value of the incoming Char-Pointer at the C-Side, with
>the Value VB spits out when you do:
> Debug.Print StrPtr(strVariable).
>Then the Value of the CharPtr on the C-side of things will
>always differ from what Debug.Print StrPtr(strVariable)
>will report at the VB-End... as said, this is due to the
>"ANSI-automatics" VB performs under the hood, in case
>you define a Param within a VB-DllFunc-Declare "As String"
>(no matter, if ByRef or ByVal).
>
>If you want to avoid this VB-ANSI-automatic (e.g. when
>your C-Dlls understands "Unicode on Windows" and was set up,
>to work with WChars), then just define the String-Params in
>your VB-Declare "ByVal As Long" - and pass StrPtr(strVariable)
>instead of just strVariable from the VB-end.
>
>Olaf
>

As Olaf has suggested there are ways to more or less insure a
'generic' passing of VB Strings to a C/C++ DLL, however if this
component is expected to be distributed to multiple developers, or to
just remove the possibility of Declare directives, creating a Type
Library for your component will help to make it practically seemless
to call your DLL from VB.

http://support.microsoft.com...
(This article is dated as It refers to VC++ 5 and ODL, but nothing
much has changed, and you can use IDL as well.)

-ralph