Illegal specification

General FreeBASIC programming questions.
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Illegal specification

Post by deltarho[1859] »

Code: Select all

Function Jack( ByVal Jill As ZString*20 ) As Long
Print Jill
Return 1  
End Function

Dim x As ZString*20 = "0123456"

Jack( x )

Sleep
Why is parameter 1 an illegal specification?
badidea
Posts: 2586
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Illegal specification

Post by badidea »

Don't know, but this works:

Code: Select all

Function Jack( ByVal Jill As ZString ptr ) As Long
	Print *Jill
	Return 1 
End Function

Dim x As ZString*20 = "0123456"

Jack( x )

Sleep
Edit: Apparently putting ZString*20 'on the stack' is not allowed. Only pointers to it. ptr or byref (as below).
Last edited by badidea on Feb 17, 2018 20:15, edited 3 times in total.
fxm
Moderator
Posts: 12082
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Illegal specification

Post by fxm »

Or:

Code: Select all

Function Jack( ByRef Jill As ZString ) As Long
Print Jill
Return 1 
End Function

Dim x As ZString*20 = "0123456"

Jack( x )

Sleep
fxm
Moderator
Posts: 12082
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Illegal specification

Post by fxm »

The allocated size of a zstring cannot be passed to a procedure because a zstring has no descriptor, and only a string character data address is passed to a procedure.
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: Illegal specification

Post by deltarho[1859] »

Thanks guys.

I fell foul of being a PowerBASIC refugee. PB has StringZ which is the same as FB's ZString but PB will not allow StringZ being used as a parameter without declaring it's length and I, naturally, assumed that the same would apply with FB.
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: Illegal specification

Post by deltarho[1859] »

It is worth mentioning what is behind this query. I have a PowerBASIC dll which accepts dynamic strings ByValue. Passing the same from FreeBASIC did not work. It is probably because FB's dynamic strings are not the same as PB's dynamic strings. One string was a filename and having been passed incorrectly, from PB's perspective, my dll was reporting 'file not found'. Whatever else I did gave me a GPF and I tried quite a few ideas.

I then remembered that PB's StringZ and FB's ZString are formatted in the same way so reckoned their 'handshaking' should work. I then came a cropper when FB would not accept a string length with a ZString parameter as PB does, and insists upon.

I changed the dll to accept 'szInfile As StringZ * 260'. With PB I don't need to use ByRef as that is the default; unlike FB which is ByVal. The dll code uses dynamic strings so I declared 'sInFile As String' and then reassigned the input with sInFile = szInFile. That is all I had to with the dll.

From FB's perspective I simply pass 'ByRef as ZString'.

The PB dll is for AES encryption and is now working fine. I don't have any AES code in FB but will eventually port my PB stuff over. In the meantime I can continue with a project requiring AES by using the dll.
caseih
Posts: 2157
Joined: Feb 26, 2007 5:32

Re: Illegal specification

Post by caseih »

So Powerbasic passes the actual ZString on the stack? Like if you have a parameter defined as StringZ *20, it would always pass 20 bytes on the stack? Or is PB simply asking you to bound the length of the string so it knows how far it can safely go when deferencing the char * pointer? I suspect the latter...

Glad you figured out a way to get them talking. I'm unsure as to what passing a Zstring variable byref actually does. I wouldn't think it necessary to use byref at all. Passing a pointer by value is the same thing as passing something by reference.

I'm not at all surprised that PB dynamic strings and FB dynamic strings are not compatible. I would definitely never use either language's dynamic strings in a DLL that is intended for use by other languages.
Josep Roca
Posts: 564
Joined: Sep 27, 2016 18:20
Location: Valencia, Spain

Re: Illegal specification

Post by Josep Roca »

> So Powerbasic passes the actual ZString on the stack? Like if you have a parameter defined as StringZ *20, it would always pass 20 bytes on the stack? Or is PB simply asking you to bound the length of the string so it knows how far it can safely go when deferencing the char * pointer? I suspect the latter...

With PB, you can pass the actual ZString on the stack, but of course it is not recommended, since it is terribly inefficient and also subject to a 64 Kb limit (less the space used by other parameters, if any). You can shoot at your foot with a gun, but it is not recommended...

PowerBasic strings are standard BSTR, so they can be used with any language that can deal with BSTRings. However, FB strings are properietary and, therefore, incompatible with other languages. If you want to use them in a DLL that will be used with another language you will have to convert them to BSTR or ZString.
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Illegal specification

Post by dodicat »

You could probably produce a BSTR via "SysAllocString".
according to :
https://msdn.microsoft.com/en-us/librar ... s.85).aspx
i tried it out here(Win 10)

Code: Select all


extern "Windows"
declare function LoadLibraryEx alias "LoadLibraryExA"(byval as zstring ptr, byval as any ptr,byval as long) as any ptr
end extern


var L=loadlibraryex("C:\Windows\System32\oleaut32.dll",0,0)

dim allocstring as function( as any ptr) as any ptr
allocstring=dylibsymbol(L,"SysAllocString")

dim freestring as sub(as any ptr) 
freestring=dylibsymbol(L,"SysFreeString")

  dim as string chars="ABCDEFGHIJKLMNOPQRSTUVWXYZ":chars+=lcase(chars)

 if L andalso allocstring andalso freestring then

 dim as any ptr s=allocstring(strptr(chars))
 
 print *cast(zstring ptr,s) 's is a BSTR ?
 freestring(s)

else
  print "Error somewhere!"  
print L
print allocstring
print freestring
end if
print "press a key to end"
sleep

 
Maybe I am wrong though!
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Illegal specification

Post by jj2007 »

If, as caseih writes, you are dealing with 20 bytes on the stack, then SysAllocStringByteLen is probably the right function.
srvaldez
Posts: 3373
Joined: Sep 25, 2005 21:54

Re: Illegal specification

Post by srvaldez »

I put this together long time ago by scrounging the web, am sure there are better ways.

Code: Select all

#include once "win/wtypes.bi"
#include once "win/unknwn.bi"
#include once "win/oleauto.bi"
'
sub StringToBSTR( byref sb as BSTR, byref cnv_string As ZString )
    Dim As integer length
    length = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, @cnv_string, -1, NULL, 0)
    sb=SysAllocStringLen(sb,length)
    MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, @cnv_string, -1, sb, length)
End sub

function BstrToString(Strng as bstr ptr) as string' By Fr34k
  dim as string result
  dim as integer length
  dim as zstring ptr buffer
  Result = ""  
  If Strng then
    length = WideCharToMultiByte(CP_ACP, 0, *Strng, -1, NULL, 0, NULL, NULL) 
    Buffer = Allocate(length) 
    If Buffer then
      WideCharToMultiByte(CP_ACP, 0, *Strng, -1, Buffer, length, NULL, NULL) 
      Result = *Buffer 
      deallocate(Buffer) 
    EndIf 
  EndIf 
  Return Result 
End function
example use

Code: Select all

dim as bstr st
StringToBStr (st,"3.14159265358979323846264338328")
Print BstrToString(@st)
SysFreeString(st)                   'free the memory taken by st
Josep Roca
Posts: 564
Joined: Sep 27, 2016 18:20
Location: Valencia, Spain

Re: Illegal specification

Post by Josep Roca »

You don't need to call these functions dynamically, they're already supported by the FB headers for Windows. If you want to return an unicode BSTR you have to use SysAllocString and if you want to return an ansi BSTR, you have to call SysAllocStringByteLen.
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Illegal specification

Post by dodicat »

I like calling routines from their dll's.
It is more fun than loading them en masse.
But of course for large projects, the Windows headers are there.
caseih
Posts: 2157
Joined: Feb 26, 2007 5:32

Re: Illegal specification

Post by caseih »

So if I'm understanding correctly, deltarho[1859] should just leave his PB dll using dynamic strings, and then communicate with that dll using the BSTR functions the windows API provides, correct?
Josep Roca
Posts: 564
Joined: Sep 27, 2016 18:20
Location: Valencia, Spain

Re: Illegal specification

Post by Josep Roca »

It is a way to do it.
Post Reply