> On Jan 6, 2016, at 12:57 PM, Austin Zheng <austinzh...@gmail.com> wrote: > > Hey Slava, > > Thanks a lot for your detailed responses; it definitely helps to understand > how structs are passed to the C++ function. > > In a separate email, Joe Groff mentioned that there was a difference between > passing the enum value and passing a pointer to it. I think that might be the > root of my problem. I'll try a few things and send over a better code sample > tonight, if there are still issues.
Yeah, that sounds like it could be the problem. In general, expecting the Swift calling convention to line up with C++ in this manner is really not something we want to officially support, and I believe JoeG is currently working on refactoring the runtime reflection interface to be a bit more minimal and orthogonal on the runtime side. It would be great to see what you're working on, because I suspect we should be able to fold your use-case into the general reflection API. Slava > > Best, > Austin > > On Wed, Jan 6, 2016 at 11:37 AM, Slava Pestov <spes...@apple.com > <mailto:spes...@apple.com>> wrote: > Hi Austin, > > > On Jan 1, 2016, at 10:58 PM, Austin Zheng via swift-dev > > <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote: > > > > Hello, > > > > I'm trying to better understand how calls are made between the Swift > > standard library code and the runtime entry points. I've read through most > > of the documentation in the repo but still have some questions. > > > > More specifically, here's an example: the '_EnumMirror' struct below > > represents a mirror reflecting a value whose type is an enum. > > > > ------ > > > > struct _EnumMirror : _MirrorType { > > let data: _MagicMirrorData > > var value: Any { return data.value } > > var valueType: Any.Type { return data.valueType } > > // ... more stuff > > > > var caseName: UnsafePointer<CChar> { > > @_silgen_name("swift_EnumMirror_caseName")get > > } > > // ... (more stuff) > > } > > > > ------ > > > > The 'caseName' property represents the name of the enum value's case (e.g. > > "FirstCase" in Foo.FirstCase) as a C string. This property's getter calls > > into a C++ runtime function named "swift_EnumMirror_caseName", which is > > reproduced below (from Reflection.mm): > > > > extern "C" > > const char *swift_EnumMirror_caseName(HeapObject *owner, > > const OpaqueValue *value, > > const Metadata *type) { > > if (!isEnumReflectable(type)) > > return nullptr; > > > > const auto Enum = static_cast<const EnumMetadata *>(type); > > const auto &Description = Enum->Description->Enum; > > > > unsigned tag; > > getEnumMirrorInfo(value, type, &tag, nullptr, nullptr); // effectively, > > same as "tag = type->vw_getEnumTag(value);" > > return getFieldName(Description.CaseNames, tag); > > } > > > > Now, I had a few questions about exactly how this interoperation works, > > because I'd like to be able to get the name of an enum case using this > > entry point from a different context (not from within an _EnumMirror > > property). > > > > * swift_EnumMirror_caseName takes three arguments, but the Swift call site > > doesn't seem to specify what gets passed into the function. > > The three arguments together form the 'self' value of the call. That is, an > EnumMirror is a struct containing a pointer to the owner object, a pointer to > the value being reflected, and runtime type information for the value. You > can see this if you look at how the _MagicMirrorData struct is defined on the > swift side. > > > Is there a convention that is implicitly passing properties on _EnumMirror > > as arguments into the C++ function when it's being called? I did note that > > there were other runtime entry points (like > > "swift_MagicMirrorData_summary") where the number of arguments in the Swift > > function matched the number of arguments in the C++ function, but in those > > cases the Swift function was a free function and not a method. > > Right. > > > > > * What I really want to do is to get the tag of an enum. I wrote a > > different entry point that omits the unused "owner" property and simply > > calls swift_EnumMirror_caseName with nullptr as the first argument. This > > other C++ function takes 'value' (an OpaqueValue*) and 'type' (a > > Metadata*). I've surmised that 'type' should be the Swift metatype of the > > enum instance (e.g. myEnum.dynamicType), and I do get the case names table. > > However, if I pass in the enum instance itself as 'value', my tag is always > > retrieved as 0. > > The value should indeed be a pointer to the enum value itself. Not sure why > it's not working for you, maybe you can share more code? > > > I noticed that there's some sort of indirection in the form of > > "vw_getEnumTag", which goes through something called the "value witness". > > Is there somewhere I can read up about the value witness concept? I assume > > the reason the 'original' code worked was because it was passing in a > > different object as 'value', maybe one that could serve as a value witness > > for the reflected-upon instance's type. > > The value witness table is a member of the type metadata. It contains entry > points for runtime manipulation of values of that type. The value witness > table is used for runtime generics (when I have a generic parameter 'T' and a > value of type 'T', the value witness functions are used for > copying/moving/destroying/etc values of type 'T'). They are also used for > reflection. > > They're not really documented anywhere except for in the source code itself > -- see here: > > include/swift/Runtime/Metadata.h > lib/IRGen/ValueWitness.h > > Slava > > > > > Thanks a lot for your time. > > > > Best, > > Austin > > > > _______________________________________________ > > swift-dev mailing list > > swift-dev@swift.org <mailto:swift-dev@swift.org> > > https://lists.swift.org/mailman/listinfo/swift-dev > > <https://lists.swift.org/mailman/listinfo/swift-dev> > >
_______________________________________________ swift-dev mailing list swift-dev@swift.org https://lists.swift.org/mailman/listinfo/swift-dev