www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Accessing Private Fields from Outside

reply Mehrdad <wfunction hotmail.com> writes:
Is there any (hacky) way of accessing a private field from outside a 
data type? (The equivalent of reflection in managed languages.)

I'm trying to write a piece of marshaling code that needs access to a 
data type's fields, but can't access them because it's not allowed to. :(
May 17 2011
next sibling parent reply "Robert Jacques" <sandford jhu.edu> writes:
On Tue, 17 May 2011 19:47:29 -0400, Mehrdad <wfunction hotmail.com> wrote:

 Is there any (hacky) way of accessing a private field from outside a  
 data type? (The equivalent of reflection in managed languages.)

 I'm trying to write a piece of marshaling code that needs access to a  
 data type's fields, but can't access them because it's not allowed to. :(

The short answer: T.tupleof works for anything that you have the source to, but doesn't support polymorphism out of the box. The long answer (from my json library): static Value from(T)(T value) { static if(is(T == class) ) if( value is null ) return Value(Null.init); //... static if(is(T == struct) || is(T == class)) { Value[string] result; foreach(i,v;value.tupleof) { result[value.tupleof[i].stringof["value.".length..$]] = from(v); } return Value( result ); } //.. } P.S. Are you marshaling to/from an open format or something proprietary?
May 17 2011
parent reply Mehrdad <wfunction hotmail.com> writes:
On 5/17/2011 5:13 PM, Robert Jacques wrote:
 On Tue, 17 May 2011 19:47:29 -0400, Mehrdad <wfunction hotmail.com> 
 wrote:

 Is there any (hacky) way of accessing a private field from outside a 
 data type? (The equivalent of reflection in managed languages.)

 I'm trying to write a piece of marshaling code that needs access to a 
 data type's fields, but can't access them because it's not allowed 
 to. :(

The short answer: T.tupleof works for anything that you have the source to, but doesn't support polymorphism out of the box. The long answer (from my json library): static Value from(T)(T value) { static if(is(T == class) ) if( value is null ) return Value(Null.init); //... static if(is(T == struct) || is(T == class)) { Value[string] result; foreach(i,v;value.tupleof) { result[value.tupleof[i].stringof["value.".length..$]] = from(v); } return Value( result ); } //.. } P.S. Are you marshaling to/from an open format or something proprietary?

access the value; it just give me a tuple I can't do anything with. Your example only gets the name of the field, but you never actually seem to access it. (P.S.: I'm trying to marshal from/to Windows data structures, so I guess it's kinda both?)
May 17 2011
parent Mehrdad <wfunction hotmail.com> writes:
On 5/17/2011 5:52 PM, Robert Jacques wrote:
 On Tue, 17 May 2011 20:44:24 -0400, Mehrdad <wfunction hotmail.com> 
 wrote:

 On 5/17/2011 5:13 PM, Robert Jacques wrote:
 T.tupleof has a problem though: It doesn't seem to let me actually 
 access the value; it just give me a tuple I can't do anything with. 
 Your example only gets the name of the field, but you never actually 
 seem to access it.

 (P.S.: I'm trying to marshal from/to Windows data structures, so I 
 guess it's kinda both?)

I actually do both (name and value) in the above example. Name: value.tupleof[i].stringof["value.".length..$] Value: v You can also use value.tupleof[i] if all you want is to set a field.

Hm, my bad. Seems like the newest version of DMD allows this, though I could swear I couldn't do that before (it would say the member is inaccessible). :-) (And yeah, I already noticed that thing about foreach(ref), thanks.) On 5/17/2011 5:56 PM, Adam D. Ruppe wrote:
 Thanks, but traits doesn't really let me read or write to the
 variable though. :(

foreach(member; __traits(allMembers, TYPE)) __traits(getMember, instance_of_type, member) = something; tupleof is probably better for this though, since it only includes actual data members; it excludes methods. You can write to tupleof by using an index.

Nope, getMember doesn't work, it gives me an inaccessible field error.
May 17 2011
prev sibling next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
Check out the __traits(allMembers, TYPE) system:

http://dpldocs.info/traits
May 17 2011
parent reply Mehrdad <wfunction hotmail.com> writes:
On 5/17/2011 5:18 PM, Adam D. Ruppe wrote:
 Check out the __traits(allMembers, TYPE) system:

 http://dpldocs.info/traits

though. :(
May 17 2011
parent Adam D. Ruppe <destructionator gmail.com> writes:
 Thanks, but traits doesn't really let me read or write to the
 variable though. :(

Use getMember there. foreach(member; __traits(allMembers, TYPE)) __traits(getMember, instance_of_type, member) = something; tupleof is probably better for this though, since it only includes actual data members; it excludes methods. You can write to tupleof by using an index.
May 17 2011
prev sibling next sibling parent "Robert Jacques" <sandford jhu.edu> writes:
On Tue, 17 May 2011 20:44:24 -0400, Mehrdad <wfunction hotmail.com> wrote:

 On 5/17/2011 5:13 PM, Robert Jacques wrote:
 On Tue, 17 May 2011 19:47:29 -0400, Mehrdad <wfunction hotmail.com>  
 wrote:

 Is there any (hacky) way of accessing a private field from outside a  
 data type? (The equivalent of reflection in managed languages.)

 I'm trying to write a piece of marshaling code that needs access to a  
 data type's fields, but can't access them because it's not allowed to.  
 :(

The short answer: T.tupleof works for anything that you have the source to, but doesn't support polymorphism out of the box. The long answer (from my json library): static Value from(T)(T value) { static if(is(T == class) ) if( value is null ) return Value(Null.init); //... static if(is(T == struct) || is(T == class)) { Value[string] result; foreach(i,v;value.tupleof) { result[value.tupleof[i].stringof["value.".length..$]] = from(v); } return Value( result ); } //.. } P.S. Are you marshaling to/from an open format or something proprietary?

access the value; it just give me a tuple I can't do anything with. Your example only gets the name of the field, but you never actually seem to access it. (P.S.: I'm trying to marshal from/to Windows data structures, so I guess it's kinda both?)

I actually do both (name and value) in the above example. Name: value.tupleof[i].stringof["value.".length..$] Value: v You can also use value.tupleof[i] if all you want is to set a field.
May 17 2011
prev sibling next sibling parent "Robert Jacques" <sandford jhu.edu> writes:
On Tue, 17 May 2011 20:52:02 -0400, Robert Jacques <sandford jhu.edu>  
wrote:

 On Tue, 17 May 2011 20:44:24 -0400, Mehrdad <wfunction hotmail.com>  
 wrote:

 On 5/17/2011 5:13 PM, Robert Jacques wrote:
 On Tue, 17 May 2011 19:47:29 -0400, Mehrdad <wfunction hotmail.com>  
 wrote:

 Is there any (hacky) way of accessing a private field from outside a  
 data type? (The equivalent of reflection in managed languages.)

 I'm trying to write a piece of marshaling code that needs access to a  
 data type's fields, but can't access them because it's not allowed  
 to. :(

The short answer: T.tupleof works for anything that you have the source to, but doesn't support polymorphism out of the box. The long answer (from my json library): static Value from(T)(T value) { static if(is(T == class) ) if( value is null ) return Value(Null.init); //... static if(is(T == struct) || is(T == class)) { Value[string] result; foreach(i,v;value.tupleof) { result[value.tupleof[i].stringof["value.".length..$]] = from(v); } return Value( result ); } //.. } P.S. Are you marshaling to/from an open format or something proprietary?

access the value; it just give me a tuple I can't do anything with. Your example only gets the name of the field, but you never actually seem to access it. (P.S.: I'm trying to marshal from/to Windows data structures, so I guess it's kinda both?)

I actually do both (name and value) in the above example. Name: value.tupleof[i].stringof["value.".length..$] Value: v You can also use value.tupleof[i] if all you want is to set a field.

to use value.tupleof[i] to assign to a field.
May 17 2011
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2011-05-18 01:47, Mehrdad wrote:
 Is there any (hacky) way of accessing a private field from outside a
 data type? (The equivalent of reflection in managed languages.)

 I'm trying to write a piece of marshaling code that needs access to a
 data type's fields, but can't access them because it's not allowed to. :(

You can have a look at my serialization library, Orange: http://www.dsource.org/projects/orange I don't think it works with the latest compilers but you have have a look at the source: http://www.dsource.org/projects/orange/browser/orange/util/Reflection.d#L277 -- /Jacob Carlborg
May 18 2011
parent reply =?ISO-8859-1?Q?g=F6lgeliyele?= <usuldan gmail.com> writes:
On 5/18/11 5:30 AM, Jacob Carlborg wrote:
 You can have a look at my serialization library, Orange:
 http://www.dsource.org/projects/orange

 I don't think it works with the latest compilers but you have have a
 look at the source:
 http://www.dsource.org/projects/orange/browser/orange/util/Reflection.d#L277

This is interesting. The list of limitations seem quite minimal. You mention: 'Due to several bugs in the compiler even the D2 version requires you to register a serializer when serializing through base class references' Is there a list of these bugs? Would resolving these bugs remove the need for registration functions? Would it be possible to have a library like this in Phobos? Are there any performance gotchas?
May 18 2011
parent Jacob Carlborg <doob me.com> writes:
On 2011-05-18 12:32, gölgeliyele wrote:
 On 5/18/11 5:30 AM, Jacob Carlborg wrote:
 You can have a look at my serialization library, Orange:
 http://www.dsource.org/projects/orange

 I don't think it works with the latest compilers but you have have a
 look at the source:
 http://www.dsource.org/projects/orange/browser/orange/util/Reflection.d#L277

This is interesting. The list of limitations seem quite minimal. You mention: 'Due to several bugs in the compiler even the D2 version requires you to register a serializer when serializing through base class references' Is there a list of these bugs? Would resolving these bugs remove the need for registration functions?

Don't know if they're actually bugs, more limitations. You would need more reflection capabilities. Better support for getting and setting instance variables via reflection. Using ClassInfo.getMembers you can get the members of a class, but you can get or set the values. In addition to that there are also two bugs related to getMembers: * http://d.puremagic.com/issues/show_bug.cgi?id=2844 * And one I never can find, getMembers always returns an empty array If I understand ClassInfo.getMembers correctly, and when it's implementation is correct, you should be able to get the members of a subclass trough a base class reference.
 Would it be possible to have a library like this in Phobos? Are there
 any performance gotchas?

It would be possible, yes. The current implementation is not the best, I'm in the middle of a complete rewrite. The current implementation adds instance variables to classes/structs but these should be static. -- /Jacob Carlborg
May 18 2011