Return a string from PB to VB

Just starting out? Need help? Post your questions and find answers here.
User avatar
mk-soft
Always Here
Always Here
Posts: 6204
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Post by mk-soft »

However, i am not going further discussion this specific code.
But read, what is a object by vb.net or variant by vb6.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Edwin Knoppert
Addict
Addict
Posts: 1073
Joined: Fri Apr 25, 2003 11:13 pm
Location: Netherlands
Contact:

Post by Edwin Knoppert »

That's a point for you yes.
If you want to make a compatible function you may indeed want to go the variant way.
But to make it compatible i suspect you *need* to create an unicode BSTR all the time.
In VB you simply use a variant to obtain the string and move it to a string variable.
But VB may not like it as return value and maybe you'll need to pass a variant byref to be set (maybe you did already).
User avatar
mk-soft
Always Here
Always Here
Posts: 6204
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Post by mk-soft »

Ok,

for varianttype vt_bstr using allways "SysAllocString_(...). If successful, returns a BSTR containing the string.

If I give the string directly back, I use the structure vbString. The text memory is then statically in the DLL and that vb the compiler reads and converts this then depending upon declaration. Functioned also perfectly. Is not however because of static text threadsafe.

With vb.net object good method is also array out to exchange. then one must be occupied however still with safearray.

(Sorry, some translated with babelfish)

Modify code now with mutex

Code: Select all


; This procedure is called once, when the program loads the library
; for the first time. All init stuffs can be done here (but not DirectX init)
;

Global mutex

ProcedureDLL AttachProcess(Instance)
  mutex = CreateMutex()
EndProcedure


; Called when the program release (free) the DLL
;
ProcedureDLL DetachProcess(Instance)
  FreeMutex(mutex)
EndProcedure


; Both are called when a thread in a program call or release (free) the DLL
;
ProcedureDLL AttachThread(Instance)
EndProcedure

ProcedureDLL DetachThread(Instance)
EndProcedure

; Compilermode ansi

;-T_BSTR
Procedure helpSysAllocString(*Value)
  ProcedureReturn SysAllocString_(*Value)
EndProcedure
Prototype.l ProtoSysAllocString(Value.p-unicode)

Global T_BSTR.ProtoSysAllocString = @helpSysAllocString()

ProcedureDLL GetString(*var.variant)

  Protected temp.s, hr
  
  LockMutex(mutex)
  temp = "Hello World"
  hr = VariantClear_(*var)
  If hr = #S_OK
    *var\vt = #VT_BSTR
    *var\bstrVal = T_BSTR(temp)
  EndIf
  UnlockMutex(mutex)
  ProcedureReturn hr
  
EndProcedure

ProcedureDLL GetFloat(*var.variant)

  Protected hr
  
  LockMutex(mutex)
  hr = VariantClear_(*var)
  If hr = #S_OK
    *var\vt = #VT_R4
    *var\fltVal = 99.8
  EndIf
  UnlockMutex(mutex)
  ProcedureReturn hr
  
EndProcedure

; direct
Structure vbString
  len.l
  text.s
EndStructure

ProcedureDLL GetDirectString()

  Static result.vbString
  
  Protected temp.s
  
  LockMutex(mutex)
  temp = "Hello World"
  result\text = temp
  result\len = Len(temp)
  UnlockMutex(mutex)
  ProcedureReturn @result\text

EndProcedure
P.S. Example for object with safearray
http://www.purebasic.fr/english/viewtop ... s&start=15
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Edwin Knoppert
Addict
Addict
Posts: 1073
Joined: Fri Apr 25, 2003 11:13 pm
Location: Netherlands
Contact:

Post by Edwin Knoppert »

I have little understanding of pb but i am a programmer.

VB.NET likes unicode
VB6 strings obtained via an external dll seems to be ansi.
Variants like to use unicode strings, it's not a must but preferred by me.

The directstring function is a poor situation.
You better avoid that an prepare one situation.

There are two ways, obtain a BSTR or obtain a Variant pointing to a BSTR.
A variant pointing to a BSTR is NOT a safearray, a safarray is not required for this.

A BSTR is simply a handle, obtain it and copy it's data to a local thing and free it.
User avatar
mk-soft
Always Here
Always Here
Posts: 6204
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Post by mk-soft »

That is correct.
If I write with purebasic dll´s also with NET Framework to be used am, one must use the WinAPI automation. Thus ensured that is it to memory leakages does not come. Thus VB.NET can release also duly in the DLL strings and also array put on again.

Property straight once again the example with arrays in the forum updates.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Ollivier
Enthusiast
Enthusiast
Posts: 281
Joined: Mon Jul 23, 2007 8:30 pm
Location: FR

Post by Ollivier »

I thank you for this interesting discussion. However, I didn't see you (Edwin Knoppert and mk-soft) continued it.

And I start to build a DLL with the method of Edwin Knoppert. It's a DLL used by VB6. Visibly, there is different methods for every compiler (VB6, VB2008 et VB.NET, etc...)

What do you think about this couple of code? Is this exact? Or do I do a mistakes if VB6 clears automatically the returned string, for example?

VB6:

Code: Select all

Declare Function InitLib Lib "MaLib.DLL" () As Integer
Declare Function TestLib Lib "MaLib.DLL" () As String
Declare Function CloseLib Lib "MaLib.DLL" () As Integer

Sub Main()

    InitLib()
        MsgBox TestLib()
    CloseLib()

End Sub
DLL PB

Code: Select all

Macro ProcedureReturnSysStringGlobal(VarName)
! mov eax, [v_#VarName]
! mov [esp + 16], eax
ProcedureReturn
EndMacro

Global SPtr.I

ProcedureDLL.I InitLib()
    SPtr = SysAllocStringByteLen_(" ", 1)
    ProcedureReturn 1
EndProcedure

ProcedureDLL.I TestLib()
    SPtr = SysReAllocString_(SPtr, "Petit message ok")
    ProcedureReturnSysStringGlobal(SPtr)
EndProcedure

ProcedureDLL.I CloseLib()
    SysFreeString_(SPtr)
    ProcedureReturn 1
EndProcedure
Edwin Knoppert
Addict
Addict
Posts: 1073
Joined: Fri Apr 25, 2003 11:13 pm
Location: Netherlands
Contact:

Post by Edwin Knoppert »

The caller frees.
Thus.. wrong code here..

It's so simple, i showed you..
For VB.NET you'll need to adapt VB.NET
Edwin Knoppert
Addict
Addict
Posts: 1073
Joined: Fri Apr 25, 2003 11:13 pm
Location: Netherlands
Contact:

Post by Edwin Knoppert »

The test is easy.
Place a msgbox on each request right after the creation and show your self the value of the BSTR handle.
This should remain the same on multiple requests(as long no other BSTR requests where performed.)
User avatar
mk-soft
Always Here
Always Here
Posts: 6204
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Post by mk-soft »

Is better to use the variant method by my Example "GetString(*result.variant)"

VB6

Code: Select all

  Dim result as Variant
VB.NET

Code: Select all

  Dim result as Object
VB can then order in accordance with the memory of the variable result again release.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Ollivier
Enthusiast
Enthusiast
Posts: 281
Joined: Mon Jul 23, 2007 8:30 pm
Location: FR

Post by Ollivier »

@Edwin Knoppert

I understand your easy test. But I have an other test (which is harder) I can't try myself, because I haven't VB.

Is it possible to make a little PB DLL like you told me page 1 (with SysAllocStringByteLen_() ), and a little VB6 code which calls 1 million times (1 000 000 times). A priori, this test seems to crash... But I am not sure cause I give this exercice to another person: I didn't make it myself. He answered me it crashes. But I think he did a mistake in the test.

Could you publish the two little codes (DLL PB and VB6) here?
Edwin Knoppert
Addict
Addict
Posts: 1073
Joined: Fri Apr 25, 2003 11:13 pm
Location: Netherlands
Contact:

Post by Edwin Knoppert »

Depends on your needs, be clear on this:

1)
VB6 returns a 'string' (but is an ansi BSTR handle).

2)
You want the same behaviour in your pb dll as descibed in #1?

3)
What will you do with VB.NET?
Will you allow to receive an ansi string and convert it to a VB.NET string?
(One way, from the dll to VB.NET)
Ollivier
Enthusiast
Enthusiast
Posts: 281
Joined: Mon Jul 23, 2007 8:30 pm
Location: FR

Post by Ollivier »

@Edwin Knoppert

Only for VB6!

Ollivier
Ollivier
Enthusiast
Enthusiast
Posts: 281
Joined: Mon Jul 23, 2007 8:30 pm
Location: FR

Post by Ollivier »

A couple of codes like this...

VB6 code

Code: Select all

Declare Function Test Lib "C:\DOCUME~1\EDWINK~1\LOCALS~1\Temp\PB51A\unsaved.dll" () As String

Sub Main()

    MsgBox Test()

End Sub
PB DLL code

Code: Select all

ProcedureDll.I Test()
  ProcedureReturn SysAllocStringByteLen_("DLL MESSAGE IS OKAY!", 20)
EndProcedure
...But without MsgBox (cause it's impossible to click [ok] 1 000 000 times) and with a loop of 1 000 000 iterations in the VB6 code. No change in the PB DLL code. The goal is that VB6 must receive the most great possible quantity of strings without saturation.
Edwin Knoppert
Addict
Addict
Posts: 1073
Joined: Fri Apr 25, 2003 11:13 pm
Location: Netherlands
Contact:

Post by Edwin Knoppert »

Try this:

www.hellobasic.com/trials/BSTRVBTest.zip

project1 is the VB6 exe
Pass a value on the commandline for using the loop.

Code: Select all

Declare Function Test Lib "pbdlltest.dll" () As String
Declare Function Test2 Lib "pbdlltest.dll" (ByVal sText As String) As String

Sub Main()

    Dim x As Long
    
    x = Val(Command)
    'MsgBox Str$(x) & ", " & Test2(Time)
    
    For a = 0 To x
        Test
    Next

End Sub
pbcode:

Code: Select all

ProcedureDLL.I Test() 
  ProcedureReturn SysAllocStringByteLen_("DLL MESSAGE IS OKAY!", 20) 
EndProcedure

ProcedureDLL.I Test2(sText.s) 
  ProcedureReturn SysAllocStringByteLen_(@sText, Len(sText)) 
EndProcedure
Ollivier
Enthusiast
Enthusiast
Posts: 281
Joined: Mon Jul 23, 2007 8:30 pm
Location: FR

Post by Ollivier »

@Edwin Knoppert

I thank you to prepare all that for me. But what I want is less...

I downloaded it, extracted it and executed it. The program crashes whatever the value is, and with or without slash "/".

I an sorry. I just want to know if, on your computer and with VB6, these two codes work fine:

VB6

Code: Select all

Declare Function Test Lib "pbdlltest.dll" () As String

Sub Main()

    Dim x As Long
    Dim MyString As String

    x = 1000000
   
    For a = 0 To x
        MyString = Test
    Next

End Sub 
PB DLL

Code: Select all

ProcedureDLL.I Test()
  ProcedureReturn SysAllocStringByteLen_("DLL MESSAGE IS OKAY!", 20)
EndProcedure
(It's not a problem if MyString is overwritten every time)
(If there is an error in my VB6 code, you can correct it in order to get a good code)
Post Reply