Re: [swift-users] Accessing the bundle of the call-site

2016-12-02 Thread Rick Aurbach via swift-users
Jordan,

You are oh, so right! Thank you for helping me resolve a particularly major 
piece of stupidity on my part.

The following code seems (subject to testing, of course), achieve what I’m 
looking for:

public extension String {

public func localized(dsoHandle : UnsafeRawPointer = #dsohandle) -> 
String {
var dlInformation : dl_info = dl_info()
let _ = dladdr(dsoHandle, )
let path = String(cString: dlInformation.dli_fname)
let url = URL(fileURLWithPath: path).deletingLastPathComponent()
let bundle = Bundle(url: url)
let str = bundle?.localizedString(forKey: self, value: self, 
table: nil)
return str!
}
}

Cheers,

Rick

> On Dec 2, 2016, at 5:37 PM, Jordan Rose  wrote:
> 
> 
>> On Dec 2, 2016, at 15:36, Rick Aurbach > > wrote:
>> 
>> Greg,
>> 
>> This is looking quite strange, because I didn’t see anything like what I 
>> expected.
>> 
>> Here’s the code that I’ve been using to test #dsohandle:
>> 
>> public extension String {
>>  
>>  public func localized(dsoHandle : UnsafeRawPointer = #dsohandle) {
>>  var dlInformation : dl_info = dl_info()
>>  let _ = dladdr(dsoHandle, )
>>  let path = String(describing: dlInformation.dli_fname!)
> 
> ^ You asked for a string describing a pointer and you got one. :-) Try 
> String(cString:) instead.
> 
> 
> 
>>  let bundle = Bundle(path: path)
>>  }
>> }
>> 
>> which is consistent with the following excerpt from the header file:
>> 
>> /*
>>  * Structure filled in by dladdr().
>>  */
>> public struct dl_info {
>> 
>> public var dli_fname: UnsafePointer! /* Pathname of shared object 
>> */
>> 
>> public var dli_fbase: UnsafeMutableRawPointer! /* Base address of shared 
>> object */
>> 
>> public var dli_sname: UnsafePointer! /* Name of nearest symbol */
>> 
>> public var dli_saddr: UnsafeMutableRawPointer! /* Address of nearest 
>> symbol */
>> 
>> public init()
>> 
>> public init(dli_fname: UnsafePointer!, dli_fbase: 
>> UnsafeMutableRawPointer!, dli_sname: UnsafePointer!, dli_saddr: 
>> UnsafeMutableRawPointer!)
>> }
>> public typealias Dl_info = dl_info
>> 
>> public func dladdr(_: UnsafeRawPointer!, _: UnsafeMutablePointer!) 
>> -> Int32
>> /* not POSIX */
>> 
>> 
>> I would have expected path to look something like a URL. However, here is 
>> what the debugger says (with a breakpoint on the “let bundle…” line:
>> 
>> 
>> 
>> As you can see, dli_fname doesn’t look anything like the “pathname of the 
>> shared object”. Instead it looks more like the address where it was loaded. 
>> Which, unfortunately, doesn’t get me any further along.
>> 
>> Thoughts?
>> 
>> Has this gotten hairy (and time consuming) enough that I should handle this 
>> as a Technical Incident??
>> 
>> Cheers,
>> 
>> Rick Aurbach
>> 
>>> On Dec 2, 2016, at 3:08 PM, Greg Parker >> > wrote:
>>> 
>>> On Darwin #dsohandle points to a Mach-O file header. You can pass that 
>>> address to dyld but I don't see an easy way to pass it to NSBundle.
>>> 
>>> This might work:
>>> 1. Pass #dsohandle to dladdr()
>>> 2. Pass the dli_fname returned by dladdr() to NSBundle(path:).
>>> 
>>> 
 On Dec 2, 2016, at 12:50 PM, Rick Aurbach > wrote:
 
 Jordan,
 
 I agree — #dsohandle is, indeed, little known. In fact, I’m having a devil 
 of a time figuring out what it is and what I can do with it. It is clearly 
 an UnsafeRawPointer, but to what?? 
 
 Can you offer either a reference or a few lines of code that can help me 
 get the information I need from it? [recall that I want the framework’s 
 bundle so I can find it’s localized.strings file].
 
 Cheers,
 
 Rick Aurbach
 
> On Dec 2, 2016, at 12:56 PM, Jordan Rose  > wrote:
> 
> On Apple platforms, we'd probably prefer you use the little-known 
> #dsoHandle, a magic pointer that's unique to the current dylib. Parsing 
> out a module name seems incredibly brittle; the form of #function is not 
> guaranteed to be stable or useful across Swift versions.
> 
> Jordan
>> 
>> 
> 

___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


Re: [swift-users] Accessing the bundle of the call-site

2016-12-02 Thread Jordan Rose via swift-users

> On Dec 2, 2016, at 15:36, Rick Aurbach  wrote:
> 
> Greg,
> 
> This is looking quite strange, because I didn’t see anything like what I 
> expected.
> 
> Here’s the code that I’ve been using to test #dsohandle:
> 
> public extension String {
>   
>   public func localized(dsoHandle : UnsafeRawPointer = #dsohandle) {
>   var dlInformation : dl_info = dl_info()
>   let _ = dladdr(dsoHandle, )
>   let path = String(describing: dlInformation.dli_fname!)

^ You asked for a string describing a pointer and you got one. :-) Try 
String(cString:) instead.



>   let bundle = Bundle(path: path)
>   }
> }
> 
> which is consistent with the following excerpt from the header file:
> 
> /*
>  * Structure filled in by dladdr().
>  */
> public struct dl_info {
> 
> public var dli_fname: UnsafePointer! /* Pathname of shared object */
> 
> public var dli_fbase: UnsafeMutableRawPointer! /* Base address of shared 
> object */
> 
> public var dli_sname: UnsafePointer! /* Name of nearest symbol */
> 
> public var dli_saddr: UnsafeMutableRawPointer! /* Address of nearest 
> symbol */
> 
> public init()
> 
> public init(dli_fname: UnsafePointer!, dli_fbase: 
> UnsafeMutableRawPointer!, dli_sname: UnsafePointer!, dli_saddr: 
> UnsafeMutableRawPointer!)
> }
> public typealias Dl_info = dl_info
> 
> public func dladdr(_: UnsafeRawPointer!, _: UnsafeMutablePointer!) 
> -> Int32
> /* not POSIX */
> 
> 
> I would have expected path to look something like a URL. However, here is 
> what the debugger says (with a breakpoint on the “let bundle…” line:
> 
> 
> 
> As you can see, dli_fname doesn’t look anything like the “pathname of the 
> shared object”. Instead it looks more like the address where it was loaded. 
> Which, unfortunately, doesn’t get me any further along.
> 
> Thoughts?
> 
> Has this gotten hairy (and time consuming) enough that I should handle this 
> as a Technical Incident??
> 
> Cheers,
> 
> Rick Aurbach
> 
>> On Dec 2, 2016, at 3:08 PM, Greg Parker > > wrote:
>> 
>> On Darwin #dsohandle points to a Mach-O file header. You can pass that 
>> address to dyld but I don't see an easy way to pass it to NSBundle.
>> 
>> This might work:
>> 1. Pass #dsohandle to dladdr()
>> 2. Pass the dli_fname returned by dladdr() to NSBundle(path:).
>> 
>> 
>>> On Dec 2, 2016, at 12:50 PM, Rick Aurbach >> > wrote:
>>> 
>>> Jordan,
>>> 
>>> I agree — #dsohandle is, indeed, little known. In fact, I’m having a devil 
>>> of a time figuring out what it is and what I can do with it. It is clearly 
>>> an UnsafeRawPointer, but to what?? 
>>> 
>>> Can you offer either a reference or a few lines of code that can help me 
>>> get the information I need from it? [recall that I want the framework’s 
>>> bundle so I can find it’s localized.strings file].
>>> 
>>> Cheers,
>>> 
>>> Rick Aurbach
>>> 
 On Dec 2, 2016, at 12:56 PM, Jordan Rose > wrote:
 
 On Apple platforms, we'd probably prefer you use the little-known 
 #dsoHandle, a magic pointer that's unique to the current dylib. Parsing 
 out a module name seems incredibly brittle; the form of #function is not 
 guaranteed to be stable or useful across Swift versions.
 
 Jordan
> 
> 

___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


Re: [swift-users] Accessing the bundle of the call-site

2016-12-02 Thread Jordan Rose via swift-users
Heh, we probably should document it somewhere. It is an opaque 
UnsafeRawPointer, and maybe you can't really get from there to a Bundle. The 
dladdr function can get you from an address to a particular dylib, and it's 
supposed to have the path, and maybe you could then turn that into a URL to get 
to the bundle…

As far as I know no one has done this yet in Swift, though Mike Ash has an 
example using dladdr for unrelated purposes. 
https://www.mikeash.com/pyblog/friday-qa-2014-08-29-swift-memory-dumping.html

Jordan


> On Dec 2, 2016, at 12:50, Rick Aurbach  wrote:
> 
> Jordan,
> 
> I agree — #dsohandle is, indeed, little known. In fact, I’m having a devil of 
> a time figuring out what it is and what I can do with it. It is clearly an 
> UnsafeRawPointer, but to what?? 
> 
> Can you offer either a reference or a few lines of code that can help me get 
> the information I need from it? [recall that I want the framework’s bundle so 
> I can find it’s localized.strings file].
> 
> Cheers,
> 
> Rick Aurbach
> 
>> On Dec 2, 2016, at 12:56 PM, Jordan Rose > > wrote:
>> 
>> On Apple platforms, we'd probably prefer you use the little-known 
>> #dsoHandle, a magic pointer that's unique to the current dylib. Parsing out 
>> a module name seems incredibly brittle; the form of #function is not 
>> guaranteed to be stable or useful across Swift versions.
>> 
>> Jordan
>> 
>> 
>>> On Dec 2, 2016, at 10:35, Rick Aurbach via swift-users 
>>> > wrote:
>>> 
>>> That’s clever! Thank you; I’d probably never have thought of that.
>>> 
>>> Cheers,
>>> 
>>> Rick Aurbach
>>> 
 On Dec 2, 2016, at 12:25 PM, Greg Parker > wrote:
 
> 
> On Dec 2, 2016, at 9:44 AM, Rick Aurbach via swift-users 
> > wrote:
> 
> Does anyone know if it is possible to do the following in Swift 3.x? 
> (I’ll describe the issue abstractly first, then give the use-case.)
> 
> Consider two modules: A and B. A could be either the main module of an 
> application or an embedded framework. B is a different embedded framework.
> 
> Now A contains an public extension of class X which contains a function 
> f(). Inside B, there is a reference to X.f(). Now what I want to do in 
> f() is to access information (a module name or bundle name or bundle ID 
> or something) that allows me to construct a Bundle object referring to B, 
> without f() having any external knowledge of the organization of the 
> application.
> 
> The use-case I’m thinking about is a localization extension of String 
> that works in a multi-framework application architecture without 
> requiring the caller to specify the name of the framework and/or module.
> 
> I.e., I want to write
> 
>   extension String {
>   func locate() -> String {…}
>   }
> 
> and put this extension into framework “A”. Then, from framework “B”, I 
> want to use this function from within a function f() and [somehow] figure 
> out from the runtime what the bundle of “B” is, so that I can use it’s 
> localized strings file.
> 
> I understand that from within the locate() method, I can use #function 
> and from it, parse out the module name of “A” and then use the 
> correspondence between module names and framework names to figure out the 
> bundle of “A”. BUT what I want here is the bundle resource for “B”, not 
> “A”.
 
 You should be able to use a trick similar to the one that assert() uses to 
 collect file and line numbers:
 
 func locate(caller: StaticString = #function) {
 // `caller` is the caller's #function
 }
 
 
 -- 
 Greg Parker gpar...@apple.com  Runtime 
 Wrangler
>>> 
>>> ___
>>> swift-users mailing list
>>> swift-users@swift.org 
>>> https://lists.swift.org/mailman/listinfo/swift-users 
>>> 
>> 
> 

___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


Re: [swift-users] Accessing the bundle of the call-site

2016-12-02 Thread Rick Aurbach via swift-users
Jordan,

I agree — #dsohandle is, indeed, little known. In fact, I’m having a devil of a 
time figuring out what it is and what I can do with it. It is clearly an 
UnsafeRawPointer, but to what?? 

Can you offer either a reference or a few lines of code that can help me get 
the information I need from it? [recall that I want the framework’s bundle so I 
can find it’s localized.strings file].

Cheers,

Rick Aurbach

> On Dec 2, 2016, at 12:56 PM, Jordan Rose  wrote:
> 
> On Apple platforms, we'd probably prefer you use the little-known #dsoHandle, 
> a magic pointer that's unique to the current dylib. Parsing out a module name 
> seems incredibly brittle; the form of #function is not guaranteed to be 
> stable or useful across Swift versions.
> 
> Jordan
> 
> 
>> On Dec 2, 2016, at 10:35, Rick Aurbach via swift-users 
>> > wrote:
>> 
>> That’s clever! Thank you; I’d probably never have thought of that.
>> 
>> Cheers,
>> 
>> Rick Aurbach
>> 
>>> On Dec 2, 2016, at 12:25 PM, Greg Parker >> > wrote:
>>> 
 
 On Dec 2, 2016, at 9:44 AM, Rick Aurbach via swift-users 
 > wrote:
 
 Does anyone know if it is possible to do the following in Swift 3.x? (I’ll 
 describe the issue abstractly first, then give the use-case.)
 
 Consider two modules: A and B. A could be either the main module of an 
 application or an embedded framework. B is a different embedded framework.
 
 Now A contains an public extension of class X which contains a function 
 f(). Inside B, there is a reference to X.f(). Now what I want to do in f() 
 is to access information (a module name or bundle name or bundle ID or 
 something) that allows me to construct a Bundle object referring to B, 
 without f() having any external knowledge of the organization of the 
 application.
 
 The use-case I’m thinking about is a localization extension of String that 
 works in a multi-framework application architecture without requiring the 
 caller to specify the name of the framework and/or module.
 
 I.e., I want to write
 
extension String {
func locate() -> String {…}
}
 
 and put this extension into framework “A”. Then, from framework “B”, I 
 want to use this function from within a function f() and [somehow] figure 
 out from the runtime what the bundle of “B” is, so that I can use it’s 
 localized strings file.
 
 I understand that from within the locate() method, I can use #function and 
 from it, parse out the module name of “A” and then use the correspondence 
 between module names and framework names to figure out the bundle of “A”. 
 BUT what I want here is the bundle resource for “B”, not “A”.
>>> 
>>> You should be able to use a trick similar to the one that assert() uses to 
>>> collect file and line numbers:
>>> 
>>> func locate(caller: StaticString = #function) {
>>> // `caller` is the caller's #function
>>> }
>>> 
>>> 
>>> -- 
>>> Greg Parker gpar...@apple.com  Runtime 
>>> Wrangler
>> 
>> ___
>> swift-users mailing list
>> swift-users@swift.org 
>> https://lists.swift.org/mailman/listinfo/swift-users
> 

___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


Re: [swift-users] Accessing the bundle of the call-site

2016-12-02 Thread Jordan Rose via swift-users
On Apple platforms, we'd probably prefer you use the little-known #dsoHandle, a 
magic pointer that's unique to the current dylib. Parsing out a module name 
seems incredibly brittle; the form of #function is not guaranteed to be stable 
or useful across Swift versions.

Jordan


> On Dec 2, 2016, at 10:35, Rick Aurbach via swift-users 
>  wrote:
> 
> That’s clever! Thank you; I’d probably never have thought of that.
> 
> Cheers,
> 
> Rick Aurbach
> 
>> On Dec 2, 2016, at 12:25 PM, Greg Parker > > wrote:
>> 
>>> 
>>> On Dec 2, 2016, at 9:44 AM, Rick Aurbach via swift-users 
>>> > wrote:
>>> 
>>> Does anyone know if it is possible to do the following in Swift 3.x? (I’ll 
>>> describe the issue abstractly first, then give the use-case.)
>>> 
>>> Consider two modules: A and B. A could be either the main module of an 
>>> application or an embedded framework. B is a different embedded framework.
>>> 
>>> Now A contains an public extension of class X which contains a function 
>>> f(). Inside B, there is a reference to X.f(). Now what I want to do in f() 
>>> is to access information (a module name or bundle name or bundle ID or 
>>> something) that allows me to construct a Bundle object referring to B, 
>>> without f() having any external knowledge of the organization of the 
>>> application.
>>> 
>>> The use-case I’m thinking about is a localization extension of String that 
>>> works in a multi-framework application architecture without requiring the 
>>> caller to specify the name of the framework and/or module.
>>> 
>>> I.e., I want to write
>>> 
>>> extension String {
>>> func locate() -> String {…}
>>> }
>>> 
>>> and put this extension into framework “A”. Then, from framework “B”, I want 
>>> to use this function from within a function f() and [somehow] figure out 
>>> from the runtime what the bundle of “B” is, so that I can use it’s 
>>> localized strings file.
>>> 
>>> I understand that from within the locate() method, I can use #function and 
>>> from it, parse out the module name of “A” and then use the correspondence 
>>> between module names and framework names to figure out the bundle of “A”. 
>>> BUT what I want here is the bundle resource for “B”, not “A”.
>> 
>> You should be able to use a trick similar to the one that assert() uses to 
>> collect file and line numbers:
>> 
>> func locate(caller: StaticString = #function) {
>> // `caller` is the caller's #function
>> }
>> 
>> 
>> -- 
>> Greg Parker gpar...@apple.com  Runtime 
>> Wrangler
> 
> ___
> swift-users mailing list
> swift-users@swift.org
> https://lists.swift.org/mailman/listinfo/swift-users

___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


Re: [swift-users] Accessing the bundle of the call-site

2016-12-02 Thread Rick Aurbach via swift-users
That’s clever! Thank you; I’d probably never have thought of that.

Cheers,

Rick Aurbach

> On Dec 2, 2016, at 12:25 PM, Greg Parker  wrote:
> 
>> 
>> On Dec 2, 2016, at 9:44 AM, Rick Aurbach via swift-users 
>> > wrote:
>> 
>> Does anyone know if it is possible to do the following in Swift 3.x? (I’ll 
>> describe the issue abstractly first, then give the use-case.)
>> 
>> Consider two modules: A and B. A could be either the main module of an 
>> application or an embedded framework. B is a different embedded framework.
>> 
>> Now A contains an public extension of class X which contains a function f(). 
>> Inside B, there is a reference to X.f(). Now what I want to do in f() is to 
>> access information (a module name or bundle name or bundle ID or something) 
>> that allows me to construct a Bundle object referring to B, without f() 
>> having any external knowledge of the organization of the application.
>> 
>> The use-case I’m thinking about is a localization extension of String that 
>> works in a multi-framework application architecture without requiring the 
>> caller to specify the name of the framework and/or module.
>> 
>> I.e., I want to write
>> 
>>  extension String {
>>  func locate() -> String {…}
>>  }
>> 
>> and put this extension into framework “A”. Then, from framework “B”, I want 
>> to use this function from within a function f() and [somehow] figure out 
>> from the runtime what the bundle of “B” is, so that I can use it’s localized 
>> strings file.
>> 
>> I understand that from within the locate() method, I can use #function and 
>> from it, parse out the module name of “A” and then use the correspondence 
>> between module names and framework names to figure out the bundle of “A”. 
>> BUT what I want here is the bundle resource for “B”, not “A”.
> 
> You should be able to use a trick similar to the one that assert() uses to 
> collect file and line numbers:
> 
> func locate(caller: StaticString = #function) {
> // `caller` is the caller's #function
> }
> 
> 
> -- 
> Greg Parker gpar...@apple.com  Runtime 
> Wrangler

___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users