How to fix error 177 ???
Re: How to fix error 177 ???
Comparing the local object's address inside the function and the address of the object after the function's result assignment, they appear to be the same. From your remarks, I conclude that this is no guarantee and in order to guarantee it, the *new* keyword should be used in the function.
Re: How to fix error 177 ???
Yes.
For the bugged code, the compiler does not complain because a hacked expression is used to create first the null reference:
dim byref t as TT = *cptr(TT ptr, 0)
@t = @TT()
If you attempt to directly create a reference on a temporary object:
dim byref t as TT = TT()
"error 24: Invalid data types" is outputted by the compiler.
For the bugged code, the compiler does not complain because a hacked expression is used to create first the null reference:
dim byref t as TT = *cptr(TT ptr, 0)
@t = @TT()
If you attempt to directly create a reference on a temporary object:
dim byref t as TT = TT()
"error 24: Invalid data types" is outputted by the compiler.
Re: How to fix error 177 ???
I was under the impression that the "invalid data types" error is due to the byref clause, not because the object is temporary.fxm wrote:Yes.
For the bugged code, the compiler does not complain because a hacked expression is used to create first the null reference:
dim byref t as TT = *cptr(TT ptr, 0)
@t = @TT()
If you attempt to directly create a reference on a temporary object:
dim byref t as TT = TT()
"error 24: Invalid data types" is outputted by the compiler.
Re: How to fix error 177 ???
For example, I can setup a null reference object with and without *byref*:
But a direct call to the (default) constructor using *byref*, as you pointed out, is not allowed:
Code: Select all
dim t as TT = *cptr(TT ptr, 0)
' or
dim byref t as TT = *cptr(TT ptr, 0)
Code: Select all
dim byref t as TT = TT()
Re: How to fix error 177 ???
Not exactly.Munair wrote:I was under the impression that the "invalid data types" error is due to the byref clause, not because the object is temporary.
With a local instance, no compiler error but the program does not run as wanted:
Code: Select all
type TT extends object
s as string
declare constructor()
end type
constructor TT()
print "TT called"
end constructor
function SomeTT(byval b as boolean = false) byref as TT
dim t0 as TT
dim byref t as TT = t0
t.s = "Hello"
return t
end function
print (SomeTT(true)).s
sleep
Code: Select all
type TT extends object
s as string
declare constructor()
end type
constructor TT()
print "TT called"
end constructor
function SomeTT(byval b as boolean = false) byref as TT
static t0 as TT
dim byref t as TT = t0
t.s = "Hello"
return t
end function
print (SomeTT(true)).s
sleep
Re: How to fix error 177 ???
@mrminecrafttnt
There is another alternative that I like to use.
When there is a chance that a function may return an unusable result, set it up as a boolean return value and use either a pointer to the desired return type or a byref parameter.
Return true when the return value is valid and false when not.
Here is the byref param version:
and here is the pointer version:
There is another alternative that I like to use.
When there is a chance that a function may return an unusable result, set it up as a boolean return value and use either a pointer to the desired return type or a byref parameter.
Return true when the return value is valid and false when not.
Here is the byref param version:
Code: Select all
function Inventory.getObj(ObjName as string, Byref iod As InventoryObjectData) as Boolean
dim as integer id = search_id(ObjName)
if id = -1 then
print "Object not found"
Return False
Else
iod = ObjectData(id)
return true
end if
End Function
and here is the pointer version:
Code: Select all
function Inventory.getObj(ObjName as string, Byval pIOD As InventoryObjectData Ptr) as Boolean
dim as integer id = search_id(ObjName)
if id = -1 then
print "Object not found"
Return False
Else
pIOD = @ObjectData(id)
return true
end if
End Function
Re: How to fix error 177 ???
Or, if you really only want to have one function output, in the case of types/objects, add a boolean member as flag to indicate the object is valid/found.
Re: How to fix error 177 ???
In addition to what sancho3 and Munair propose, here's a simple scheme that I use often:
In other words, don't use references when working with objects unless you absolutely have to. Since in FreeBasic you can't do late binding of references, there's not much else you can do when/if you start working with interfaces.
Code: Select all
/'
The ID you'll use to identify objects throughout your
code base.
'/
type ObjectID as string
/'
The abstract interface for an inventory item
'/
type IInventory extends Object
public:
declare virtual destructor()
declare virtual property ID() as ObjectID
protected:
declare constructor()
declare constructor( _
byref as const ObjectID )
private:
m_ID as ObjectID
end type
constructor IInventory()
this.constructor( "<Unknown>" )
end constructor
constructor IInventory( _
byref anID as const ObjectID )
m_ID = anID
end constructor
destructor IInventory()
end destructor
property IInventory.ID() as ObjectID
return( m_ID )
end property
/'
A concrete implementation of an inventory item
'/
type Asset extends IInventory
public:
declare constructor( _
byref as const ObjectID )
declare destructor() override
static Null as Asset ptr
private:
declare constructor()
end type
'' The null asset
dim as Asset ptr _
Asset.Null = cptr( Asset ptr, 0 )
constructor Asset()
base()
end constructor
constructor Asset( _
byref anID as const ObjectID )
base( anID )
end constructor
destructor Asset()
end destructor
/'
Finds an asset on a given array. Returns Asset.Null if
it's not found.
'/
function findAsset( _
assets() as Asset, _
byref anID as const ObjectID ) as Asset ptr
for _
i as integer = lbound( assets ) to ubound( assets )
if( _
assets( i ).ID = anID ) then
return( @assets( i ) )
end if
next
return( Asset.Null )
end function
/'
Main code
'/
dim as Asset _
someAssets( ... ) = _
{ _
Asset( "Pears" ), _
Asset( "Apples" ), _
Asset( "Bananas" ) _
}
/'
See if we can find some asset
'/
var anAsset = findAsset( someAssets(), "Apples" )
if( _ '' Found it?
anAsset <> Asset.Null ) then
/'
Do some mighty interesting stuff
'/
? "Found it!"
else
'' Crap out
? "Couldn't find it!"
end if
sleep()
Re: How to fix error 177 ???
In FreeBASIC, anything that can be done with pointers can be done with references (because a reference is the dereferencing of an internal pointer, but accessible by user).paul doe wrote:Since in FreeBasic you can't do late binding of references, there's not much else you can do when/if you start working with interfaces.
Your example modified for using references:
Code: Select all
/'
The ID you'll use to identify objects throughout your
code base.
'/
type ObjectID as string
/'
The abstract interface for an inventory item
'/
type IInventory extends Object
public:
declare virtual destructor()
declare virtual property ID() as ObjectID
protected:
declare constructor()
declare constructor( _
byref as const ObjectID )
private:
m_ID as ObjectID
end type
constructor IInventory()
this.constructor( "<Unknown>" )
end constructor
constructor IInventory( _
byref anID as const ObjectID )
m_ID = anID
end constructor
destructor IInventory()
end destructor
property IInventory.ID() as ObjectID
return( m_ID )
end property
/'
A concrete implementation of an inventory item
'/
type Asset extends IInventory
public:
declare constructor( _
byref as const ObjectID )
declare destructor() override
static byref Null as Asset
private:
declare constructor()
end type
'' The null asset
dim byref as Asset _
Asset.Null = *cptr( Asset ptr, 0 )
constructor Asset()
base()
end constructor
constructor Asset( _
byref anID as const ObjectID )
base( anID )
end constructor
destructor Asset()
end destructor
/'
Finds an asset on a given array. Returns Asset.Null if
it's not found.
'/
function findAsset( _
assets() as Asset, _
byref anID as const ObjectID ) byref as Asset
for _
i as integer = lbound( assets ) to ubound( assets )
if( _
assets( i ).ID = anID ) then
return( assets( i ) )
end if
next
return( Asset.Null )
end function
/'
Main code
'/
dim as Asset _
someAssets( ... ) = _
{ _
Asset( "Pears" ), _
Asset( "Apples" ), _
Asset( "Bananas" ) _
}
/'
See if we can find some asset
'/
var anAsset = findAsset( someAssets(), "Apples" )
if( _ '' Found it?
@anAsset <> @Asset.Null ) then
/'
Do some mighty interesting stuff
'/
? "Found it!"
else
'' Crap out
? "Couldn't find it!"
end if
sleep()
Re: How to fix error 177 ???
Why would Null be part of the object?
Even better would be a built-in keyword Nil in the category New and Delete:
Code: Select all
#define nil(o) (varptr(o) = 0)
...
if not ( _ '' Found it?
Nil(anAsset) ) then
Code: Select all
if anAsset <> Nil then
Re: How to fix error 177 ???
Not true, because there's no orthogonality between references and pointers:fxm wrote:In FreeBASIC, anything that can be done with pointers can be done with references (because a reference is the dereferencing of an internal pointer, but accessible by user).
Code: Select all
type ISomething extends Object
declare virtual destructor()
declare abstract property foo() as integer
end type
destructor ISomething()
end destructor
type SomeObject
public:
declare constructor( _
byref as ISomething )
declare destructor()
private:
declare constructor()
m_something as ISomething
end type
constructor SomeObject()
end constructor
constructor SomeObject( _
byref aReference as ISomething )
m_something = aReference
end constructor
destructor SomeObject()
end destructor
Code: Select all
type ISomething extends Object
declare virtual destructor()
declare abstract property foo() as integer
end type
destructor ISomething()
end destructor
type SomeObject
public:
declare constructor( _
byref as ISomething )
declare destructor()
private:
declare constructor()
m_something as ISomething ptr '' Notice it's a pointer
end type
constructor SomeObject()
end constructor
constructor SomeObject( _
byref aReference as ISomething )
m_something = @aReference
end constructor
destructor SomeObject()
end destructor
Code: Select all
type ISomething extends Object
declare virtual destructor()
declare abstract property foo() as integer
end type
destructor ISomething()
end destructor
type SomeObject
public:
declare constructor( _
byref as ISomething )
declare destructor()
private:
declare constructor()
m_something as ISomething = any '' Equivalent to 'nothing' in other languages
end type
constructor SomeObject()
end constructor
constructor SomeObject( _
byref aReference as ISomething )
m_something = aReference
end constructor
destructor SomeObject()
end destructor
Re: How to fix error 177 ???
fxm
your example gives
Compiler output:
Aborting due to runtime error 12 ("segmentation violation" signal) in 32 bit gas and gcc
And compile failed with no reason shown in 64 bit gcc.
This also gives the same result
Win 10 fb , version 1.05, fbide.
your example gives
Compiler output:
Aborting due to runtime error 12 ("segmentation violation" signal) in 32 bit gas and gcc
And compile failed with no reason shown in 64 bit gcc.
This also gives the same result
Code: Select all
type udt
as integer n
static byref null as udt
end type
dim byref as udt udt.null=*cptr(udt ptr,0)
sleep
Re: How to fix error 177 ???
Because not every object can be nullable, and the null pointer has to be of the same type as the object to avoid casting. The right way (depending on circumstances) would be to implement the Null Pattern for each object that needs it.Munair wrote:Why would Null be part of the object?
I would define the Null pointer as:
Code: Select all
#define Null cptr( any ptr, 0 )
Re: How to fix error 177 ???
Sorry, I've written the code in a hurry. The Null reference should be part of the interface, not the derived classes themselves:Munair wrote:Why would Null be part of the object?
Code: Select all
/'
The ID you'll use to identify objects throughout your
code base.
'/
type ObjectID as string
/'
The abstract interface for an inventory item
'/
type IInventory extends Object
public:
declare virtual destructor()
declare virtual property ID() as ObjectID
static Null as IInventory ptr
protected:
declare constructor()
declare constructor( _
byref as const ObjectID )
private:
m_ID as ObjectID
end type
dim as IInventory ptr _
IInventory.Null = cptr( IInventory ptr, 0 )
constructor IInventory()
this.constructor( "<Unknown>" )
end constructor
constructor IInventory( _
byref anID as const ObjectID )
m_ID = anID
end constructor
destructor IInventory()
end destructor
property IInventory.ID() as ObjectID
return( m_ID )
end property
/'
A concrete implementation of an inventory item
'/
type Asset extends IInventory
public:
declare constructor( _
byref as const ObjectID )
declare destructor() override
private:
declare constructor()
end type
constructor Asset()
base()
end constructor
constructor Asset( _
byref anID as const ObjectID )
base( anID )
end constructor
destructor Asset()
end destructor
/'
Finds an asset on a given array. Returns Asset.Null if
it's not found.
'/
function findAsset( _
assets() as Asset, _
byref anID as const ObjectID ) as IInventory ptr
for _
i as integer = lbound( assets ) to ubound( assets )
if( _
assets( i ).ID = anID ) then
return( @assets( i ) )
end if
next
return( Asset.Null )
end function
/'
Main code
'/
dim as Asset _
someAssets( ... ) = _
{ _
Asset( "Pears" ), _
Asset( "Apples" ), _
Asset( "Bananas" ) _
}
/'
See if we can find some asset
'/
var anAsset = findAsset( someAssets(), "Apples" )
if( _ '' Found it?
anAsset <> IInventory.Null ) then
/'
Do some mighty interesting stuff
'/
? "Found it!"
else
'' Crap out
? "Couldn't find it!"
end if
sleep()
Re: How to fix error 177 ???
Another way would be a (global) constant (not only good for OO stuff, but procedural also):paul doe wrote:I would define the Null pointer as: #define Null cptr( any ptr, 0 )
Const As Any Ptr NULL = 0
More efficient than a #Define (a single line #Macro).