1

I am trying to use C library source files inside my Cocoa Framework which has function named

void swe_set_ephe_path(char *path);

Which will basically be

swe_set_ephe_path(”C:\\SWEPH\\EPHE”);

for windows.

This library contains other data files which only work after this function is set. When imported to Swift the function looks like this

swe_set_ephe_path(path: UnsafeMutablePointer<Int8!>)

Since i want to bundle up all the data files in framework and use it in my application, i have done something like this

public class SwissEphemeris {
     public init() {
        let path = Bundle.main.bundlePath
        let swePath = UnsafeMutablePointer<Int8>(mutating: (path as NSString).utf8String)
        swe_set_ephe_path(swePath)
     }
}

But it seems it's not working and the functions which needs data to be searched in files are not able to operate.

Here is the picture for my directory structure

If anybody interested to look into Swiss library documentation, check here for the link, https://www.astro.com/swisseph/swephprg.htm#_Toc505244836

B K.
  • 534
  • 5
  • 18
John
  • 31
  • 5
  • @MartinR, Thanks for Bundle.main.bundlePath thing. I have looked into both of the links you have provided but still i am not able to sort out my problem. swe_set_ephe_path(path: UnsafeMutablePointer) takes path of data files inside framework. `let bundle = Bundle(identifier: "com.myframework.id")` is of Bundle? type and can't be passed as String. I tried to do following but didn't work `let path = Bundle(identifier: "com.Abhi.SwissFramework")?.bundlePath` and passed **path** as above in picture but still with no luck ! – John May 11 '19 at 18:57

1 Answers1

0

There are two problems:

First, the resource files are in the “Resources” subdirectory of the framework, not in the top-level framework directory. You can obtain a path to that directory with

let resourcePath = Bundle(identifier: "com.Abhi.SwissFramework")!.resourcePath!

or with

let resourcePath = Bundle(for: type(of: self)).resourcePath!

I suggest to force-unwrap the optionals because you know that the bundle and the resources directory exist. A failure would indicate a build problem which should be detected early.

Second, the C function takes a char * argument even though it does not mutate the passed string. Here you can use the approach from UnsafeMutablePointer<Int8> from String in Swift:

resourcePath.withCString {
    swe_set_ephe_path(UnsafeMutablePointer(mutating: $0))
}

Even better: use the dedicated method withUnsafeFileSystemRepresentation() to get the file system representation of the resource path as a C string:

let resourceURL = Bundle(for: type(of: self)).resourceURL!
resourceURL.withUnsafeFileSystemRepresentation {
    swe_set_ephe_path(UnsafeMutablePointer(mutating: $0))
}
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • It worked, Fantastic ! Martin ! . I still didn't understand how this worked. ``` resourcePath.withCString { swe_set_ephe_path(UnsafeMutablePointer(mutating: $0)) } ``` Could you guide me to some resources where i can grasp this concept ? – John May 12 '19 at 09:11
  • @John: I had tried to explain it in https://stackoverflow.com/a/27876849/1187415. The methods are also all documented: https://developer.apple.com/documentation/swift/string/1538904-withcstring, https://developer.apple.com/documentation/swift/unsafemutablepointer/2431122-init – Martin R May 12 '19 at 09:21