Implementing a Type Field copy with Reflection?

BlitzMax Forums/BlitzMax Programming/Implementing a Type Field copy with Reflection?

DavidDC(Posted 2007) [#1]
In my Type I have a Method which copies all the fields of the type from the argument's same-type object

i.e.

Type MyType

  Field Field_a:Int
  Field Field_b:String

  Method Copy(_source:MyType)
    
    Field_a = _source.Field_a
    Field_b = _source.Field_b

  End Method
End Type

I'd like to use reflection here instead. My feeble start is below, but I'm a bit lost re Sets Gets and navigating Fields generally.

		Local self_id:TTypeId		=TTypeId.ForObject( Self)
		Local source_id:TTypeId 		= TTypeId.ForObject(_source)
		Local source_field_list:TList 	= source_id.Fields()
		Local source_field:TField 		= TField(source_field_list.First())
		
		For Local self_field:TField=EachIn self_id.EnumFields()
			self_field.Set Self, source_field.Get()
			source_field = OK, Now I admit I'm lost! These Sets and Gets confuse me...
		
		Next

Any help greatly appreciated!

Thanks.

-David


Who was John Galt?(Posted 2007) [#2]
I can't help you with the reflection, but here's a handy general function for copying types which seems to work.

Type Tcake
	Field x,y
End Type

Function copytype(src:Object,dest:Object,thesize)
	MemCopy(Byte Ptr(dest),Byte Ptr(src),thesize)
End Function

my:Tcake=New Tcake
my.x=5
my.y=6

your:Tcake=New Tcake
copytype(my,your,SizeOf(Tcake))

DebugLog your.x
DebugLog your.y



Dreamora(Posted 2007) [#3]
nomen: congratulation to your active null reference creation.
Copy of memory does not change the reference count -> zack and bang if the original object ever goes out of scope



here is a function I wrote as proof of concept for the german boards:




Gabriel(Posted 2007) [#4]

Copy of memory does not change the reference count -> zack and bang if the original object ever goes out of scope


Why should anything go bang? What does reference count have to do with anything? Why would you want to affect the reference count when creating a completely new object? Wouldn't that just stop the old object from ever being deleted? Why should an object going out of scope have any effect on the content of data you copied from it and is now residing in a completely different object?


Dreamora(Posted 2007) [#5]
Yeah but there is the little but massive problems that objects can hold references to other objects! And by memcopying them instead of assigning them, you totally break the GC (or in other terms: you would create weak references and therefor let the cloned object hold potential NULL references if the original object goes out of scope)
So everything you clone must be cloned by using this function hierarchically on all object references -> would need to be implemented in the bbObject class itself

Noel did that a few versions ago.
The GC dies with similar messages you get when you try to do callbacks to external libraries that are out of blitz for longer than the minimal timeslice of GC check.
Most likely because the clone can block the periodical GC checks


Gabriel(Posted 2007) [#6]
Ah, gotcha. I wasn't really thinking of objects holding other objects, since you can't really use that data for loading, saving etc anyway. You could clone it for immediate use though, so I see your point.


Azathoth(Posted 2007) [#7]
I've written a Clone function which may do what you want.




Who was John Galt?(Posted 2007) [#8]
nomen: congratulation to your active null reference creation
Hey, I never said it did a deep copy. Damn that infernal garbage collector!


DavidDC(Posted 2007) [#9]
Much thanks go to both Dreamora and Azathoth. Dreamora, I really liked the demonstrate-the-concept simplicity of your example. Helped me get my brain around it. Azathoth - talk about the swiss-army knife of clone functions! Amazing! Is this in the code archives? If not it probably should be : )

-David


Azathoth(Posted 2007) [#10]
I was going to put it in the archives but I was having problems getting arrays copied and thought I did something wrong, however it turns out its a bug and Mark says its fixed in the next release.


Chroma(Posted 2007) [#11]
I'm interested in this too. Consider this.

Type TEmitter
   Field vPos:TVec3 = Vec3()
End Type

Type TVec3
   Field x:Float, y:Float, z:Float
End Type

Function Vec3:TVec3()
   Return New TVec3
End Function

Now if I wanted to create a fast copy of an Emitter which included all its fields that are types (TVec3), but I didn't want to go through each field vector and have to copy that too...what's the fastest way?

I know that doing a EmitterA = EmitterB is wrong because then EmitterA just becomes a pointer to EmitterB and isn't it's own Emitter per say. Maybe if there was a fast way to copy an entire type to another.But so you don't have to blah blah blah.

When I say fast, I mean something that could possibly be called each cycle with minimal tasking.


Dreamora(Posted 2007) [#12]
The fastest way is to hardcode the clone method simply.

the slower way is to use the above cloning method but as it is done through reflection, it will be slower.