Page 1 of 1
Prototypes, strings and DLL again
Posted: Fri Jun 11, 2010 12:31 am
by luis
Does this qualify as a bug ?
CLIENT
Code: Select all
EnableExplicit
#PROTO_WITH_STRING = 1
Define a$
CompilerIf #PROTO_WITH_STRING = 1
If OpenLibrary(0, "lib.dll")
Prototype.s p_Proc1 (a$, b$) ; this will not work
Global Proc1.p_Proc1 = GetFunction(0, "Proc1")
EndIf
a$ = Proc1 ("hello", "fred") ; no way
CompilerElse
If OpenLibrary(0, "lib.dll")
Prototype.i p_Proc1 (a$, b$) ; this will work using PeekS
Global Proc1.p_Proc1 = GetFunction(0, "Proc1")
EndIf
a$ = PeekS(Proc1 ("hello", "fred")) ; why can't the compiler do this looking at the Prototype ?
CompilerEndIf
Debug "a$ = " + a$
DLL (lib.dll)
Code: Select all
Global Ret$
ProcedureDLL.s Proc1 (a$, b$)
Ret$ = a$ + " " + b$
ProcedureReturn Ret$
EndProcedure
See also (similar but using Imports) ->
http://www.purebasic.fr/english/viewtop ... =3&t=40926
And this (DLL limitations and good practice to follow ?) ->
http://www.purebasic.fr/english/viewtop ... 13&t=42537
Re: Prototypes, strings and DLL again
Posted: Fri Jun 11, 2010 4:42 am
by GBeebe
Agreed, but I thought it was standard for the pointer to a string to be returned by a DLL instead of the whole string itself. It's common in all DLLs that return "strings" and languages, right?
[Edit]
Because of something like this:
Code: Select all
*Name = GetUserName(something)
If *Name = #NUL
;something went wrong
ElseIf PeekS(*Name) = ""
;the user didn't supply a name.
UserName.s = "Anonymous"
Else
UserName.s = PeekS(*Name)
EndIf
Re: Prototypes, strings and DLL again
Posted: Fri Jun 11, 2010 8:06 am
by blueznl
GBeebe wrote:Agreed, but I thought it was standard for the pointer to a string to be returned by a DLL instead of the whole string itself. It's common in all DLLs that return "strings" and languages, right?
Either return a pointer, or (perhaps even better) allocate some memory, then call the DLL function with a pointer to that memory. Many DLL's return the required size of the buffer if they are passed a 0 as buffer address.
Re: Prototypes, strings and DLL again
Posted: Fri Jun 11, 2010 11:10 am
by luis
GBeebe wrote:Agreed, but I thought it was standard for the pointer to a string to be returned by a DLL instead of the whole string itself. It's common in all DLLs that return "strings" and languages, right?
Yes, but read below...
blueznl wrote:
Either return a pointer, or (perhaps even better) allocate some memory, then call the DLL function with a pointer to that memory. Many DLL's return the required size of the buffer if they are passed a 0 as buffer address.
Yes, it's a common way to communicate used in many APIs and I've considered that.
But my points are:
1) I have specified using prototypes the return type is a string. And if I assign the returned value through PeekS() to a string all works well. So why the compiler don't do that by itself ? It just knows. This is the first question.
1a) Is this a bug (I would call it a bug or a level of unexpected missing functionality if you like!) ? Second question.
2) Since it seem the compiler could do that, why force me to write DIFFERENT code in the client depending on my calling a proc from dll or from the source code directly, for example ? This is a little annoying because I would like to be able to release something in DLL form initially, and maybe later in source form, and the user (programmer) could use the same client code without modifications.
I know I could probably ALWAYS return the address of the string (using DLL or included source), but if it can be avoided and uniformed to the usual way of returning strings it would be better...
Unless there is a reason behind for all this (but again see point 1).
Comments ? Suggestions ?
Re: Prototypes, strings and DLL again
Posted: Fri Aug 08, 2014 4:02 pm
by Foz
Just to raise this an issue again, but why doesn't Prototype.s work the same as Prototype.i + PeekS()?
Re: Prototypes, strings and DLL again
Posted: Fri Aug 08, 2014 4:55 pm
by Danilo
Returning .s works only PB-Internal, together with PB's internal string-buffer.
The external DLL/lib does not write to PB's internal string buffer.
Code: Select all
Prototype.s p_Proc1 (a$, b$)
Procedure.s test_proc(a$,b$)
ProcedureReturn a$+b$
EndProcedure
Define f.p_Proc1 = @test_proc()
x$ = f("Hello"," World!")
Debug x$
Of course it would be better if Prototype.s, Prototype.p-ascii, Prototype.p-utf8, and Prototype.p-unicode
would just work and do automatically PeekS(), except for 0-pointers.
PeekS(0,-1,#PB_Ascii) does currently not check for 0-pointers. In my opinion such functions should check
for 0-pointers and return an empty string, instead crashing. I mean in the final exe, without debugger.
Re: Prototypes, strings and DLL again
Posted: Sat Aug 09, 2014 2:19 am
by kenmo
Danilo wrote:Of course it would be better if Prototype.s, Prototype.p-ascii, Prototype.p-utf8, and Prototype.p-unicode
would just work and do automatically PeekS(), except for 0-pointers.
I agree with this! Time for a Feature Request?
In fact a Prototype with return type .s seems "dangerous" because PureBasic doesn't know what string format the DLL uses! Since you are defining the prototype and you know its input formats, you should know (and be able to specify) its output format too.
(That's why returning a pointer, and using PeekS() with the appropriate format, is currently the best method.)