Just starting out? Need help? Post your questions and find answers here.
Mijikai
Addict
Posts: 1360 Joined: Sun Sep 11, 2016 2:17 pm
Post
by Mijikai » Thu Jan 10, 2019 10:21 am
The example code shows how to get a 'string' from a dll.
Peeks() destroys the structure that is used to return a string (pointer).
Code (dll):
Code: Select all
EnableExplicit
Structure STRING_STRUCT
*Buffer
*Pointer
String.s
EndStructure
Global Dummy.s = "2. Hello World!"
Macro mAllocString(p)
p = AllocateStructure(STRING_STRUCT)
If p
p\String = #Null$
p\Buffer = @p\String
p\Pointer = @p\Buffer
EndIf
EndMacro
ProcedureDLL.i Test1()
Protected *Return.STRING_STRUCT
mAllocString(*Return)
If *Return
*Return\String = "1. Hello World!"
ProcedureReturn *Return\Pointer
EndIf
EndProcedure
ProcedureDLL.i Test2()
Protected *Return.STRING_STRUCT
mAllocString(*Return)
If *Return
*Return\String = PeekS(@Dummy);<- this will destroy the structure!
ProcedureReturn *Return\Pointer
EndIf
EndProcedure
Code (exe):
Code: Select all
EnableExplicit
Import "test.lib"
Test1.i()
Test2.i()
FreeString.i(*String)
EndImport
Global *Test1.String
Global *Test2.String
*Test1 = Test1()
*Test2 = Test2()
Debug *Test1\s;<- works!
Debug *Test2\s;<- fails!
End
fryquez
Enthusiast
Posts: 369 Joined: Mon Dec 21, 2015 8:12 pm
Post
by fryquez » Thu Jan 10, 2019 10:46 am
*Return\String = PeekS(@Dummy) - changes the address.
You need to update your structure elements.
\Buffer
\Pointer
are still pointing to the "old" string location.
Mijikai
Addict
Posts: 1360 Joined: Sun Sep 11, 2016 2:17 pm
Post
by Mijikai » Thu Jan 10, 2019 11:36 am
It should only reallocate a already initialized string and not destroy it.
Peeks() returns a string (see help) and should behave like other functions (ex. Left(), StringField()) but it doesnt.
Josh
Addict
Posts: 1183 Joined: Sat Feb 13, 2010 3:45 pm
Post
by Josh » Thu Jan 10, 2019 2:09 pm
Code: Select all
Debug *Test1\s;<- works!
Debug *Test2\s;<- fails!
And whats the difference? Both show nothing. At least a working example would be good.
Next I would write the whole thing without DLL and without macro, there are possibly own errors much easier to recognize.
Last edited by
Josh on Thu Jan 10, 2019 2:11 pm, edited 1 time in total.
sorry for my bad english
Mijikai
Addict
Posts: 1360 Joined: Sun Sep 11, 2016 2:17 pm
Post
by Mijikai » Thu Jan 10, 2019 2:11 pm
Josh wrote: Code: Select all
Debug *Test1\s;<- works!
Debug *Test2\s;<- fails!
And whats the difference? Both show nothing.
Nice, then we have a huge bug.
Mijikai
Addict
Posts: 1360 Joined: Sun Sep 11, 2016 2:17 pm
Post
by Mijikai » Thu Jan 10, 2019 2:26 pm
Josh wrote:
Next I would write the whole thing without DLL and without macro, there are possibly own errors much easier to recognize.
I noticed a possible bug/issue and posted it here to improve PB just so u know...
Nice comment really...
Josh
Addict
Posts: 1183 Joined: Sat Feb 13, 2010 3:45 pm
Post
by Josh » Thu Jan 10, 2019 2:28 pm
Mijikai wrote: Nice, then we have a huge bug.
I wouldn't say that. Your code is just crappy and meaningless and unnecessarily complicated that you don't understand it yourself.
This is again a typical example as we had it a few times in the last days. Don't understand the own code, but immediately post under bugs.
sorry for my bad english
kenmo
Addict
Posts: 1967 Joined: Tue Dec 23, 2003 3:54 am
Post
by kenmo » Thu Jan 10, 2019 4:28 pm
I don't think there's a bug.
fryquez is right, you're changing the string without updating the pointer to the old string.
PureBasic doesn't guarantee string pointers don't change. (What if PeekS was peeking a much larger string? Of course the pointer will have to change.)
Some other comments too:
Code: Select all
Structure STRING_STRUCT
*Buffer
;*Pointer ; not needed, just return @*Return\Buffer
String.s
EndStructure
Global Dummy.s = "2. Hello World!"
Macro mAllocString(p)
p = AllocateStructure(STRING_STRUCT)
If p
Debug @p\String
p\String = #Null$ ; this line doesn't change anything since p\String has never been set
Debug @p\String
Debug ""
Debug p\Buffer
p\Buffer = @p\String ; this line doesn't change anything since @p\String remains 0
Debug p\Buffer
Debug ""
EndIf
EndMacro
ProcedureDLL.i Test1()
Protected *Return.STRING_STRUCT
mAllocString(*Return)
If *Return
*Return\String = "1. Hello World!"
*Return\Buffer = @*Return\String ; update \Buffer to point to updated string
ProcedureReturn @*Return\Buffer
EndIf
EndProcedure
ProcedureDLL.i Test2()
Protected *Return.STRING_STRUCT
mAllocString(*Return)
If *Return
*Return\String = PeekS(@Dummy)
*Return\Buffer = @*Return\String ; update \Buffer to point to updated string
ProcedureReturn @*Return\Buffer
EndIf
EndProcedure
Global *Test1.String
Global *Test2.String
*Test1 = Test1()
*Test2 = Test2()
Debug *Test1\s ; <- works
Debug *Test2\s ; <- works
; don't forget to free allocated structures...
; which might be impossible because you don't return the structure's address (*Return)
End
mk-soft
Always Here
Posts: 5406 Joined: Fri May 12, 2006 6:51 pm
Location: Germany
Post
by mk-soft » Thu Jan 10, 2019 8:46 pm
I things is a better way to do it over memory
For all OS (Update 2 - UTF8)
Code: Select all
;-TOP
; -----------------------------------------------------------------------------
Procedure AllocateString(Text.s, Format = #PB_Unicode)
Protected *mem, len
len = StringByteLength(text, Format) + SizeOf(character)
*mem = malloc_(len)
If *mem
PokeS(*mem, text, -1, Format)
EndIf
ProcedureReturn *mem
EndProcedure
; -----------------------------------------------------------------------------
Procedure.s FreeString(*Text)
Protected result.s
If *Text
result = PeekS(*Text)
free_(*Text)
EndIf
ProcedureReturn result
EndProcedure
; -----------------------------------------------------------------------------
ProcedureDLL _Get()
Protected *result, text.s
text = "Hello World!"
*result = AllocateString(text)
ProcedureReturn *result
EndProcedure
; -----------------------------------------------------------------------------
ProcedureDLL _Get_UTF8()
Protected *result, text.s
text = "Hello World!"
*result = AllocateString(text, #PB_UTF8)
ProcedureReturn *result
EndProcedure
; -----------------------------------------------------------------------------
CompilerIf #PB_Compiler_IsMainFile
Prototype protoGet()
Define lib.s, *mem
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
lib = "mylib.dll"
CompilerCase #PB_OS_Linux
lib = "mylib.so"
CompilerCase #PB_OS_MacOS
lib = "mylib.dylib"
CompilerEndSelect
If OpenLibrary(0, lib)
Get.protoGet = GetFunction(0, "_Get")
Get_UTF8.protoGet = GetFunction(0, "_Get_UTF8")
*mem = get()
Debug "Adr: " + *mem + " - " + FreeString(*mem)
*mem = get()
Debug "Adr: " + *mem + " - " + FreeString(*mem)
*mem = get()
Debug "Adr: " + *mem + " - " + FreeString(*mem)
*mem = Get_UTF8()
Debug "UTF8 String / Adr: " + *mem + " - " + PeekS(*mem, -1, #PB_UTF8)
free_(*mem)
Else
Debug "Error open Library!"
EndIf
CompilerEndIf