C vararg: Swift Package Manager and System Modules

If I need access to the C fcntl(2):

  int fcntl(int, int, ...)

can I get the swift-package-manager or swift-build-tool to compile C code that wraps this into a non-vararg version:

  int SocketHelper_fcntl_setFlags(int const fildes, int const flags)
  {
    return fcntl(fildes, F_SETFL, flags);
  }
  
  int SocketHelper_fcntl_getFlags(int const fildes)
  {
    return fcntl(fildes, F_GETFL);
  }

?

The “System Modules” approach from <https://github.com/apple/swift-package-manager/blob/master/Documentation/SystemModules.md&gt; doesn’t really work. I’d have to create a .a file and put it into a /usr/lib/SocketHelper.so and /usr/include/SocketHelper.h -- which doesn’t make much sense for something this specific and trivial.

Should I look into libffi for this particular case?

/Daniel

I solved it like this:

typealias fcntlType = @convention(c) (CInt, CInt, CInt) -> (CInt)
let fcntlAddr = dlsym(UnsafeMutablePointer<Void>(bitPattern: Int(-2)), "fcntl")
let fcntlType: myFcntl = unsafeBitCast(fcntlAddr, fcntlType.self)

which admittedly is a bit tacky, but it works for now.

/Daniel

···

On 17 Dec 2015, at 22:47, Daniel Eggert via swift-users <swift-users@swift.org> wrote:

If I need access to the C fcntl(2):

int fcntl(int, int, ...)

can I get the swift-package-manager or swift-build-tool to compile C code that wraps this into a non-vararg version:

int SocketHelper_fcntl_setFlags(int const fildes, int const flags)
{
   return fcntl(fildes, F_SETFL, flags);
}

int SocketHelper_fcntl_getFlags(int const fildes)
{
   return fcntl(fildes, F_GETFL);
}

?

Hi Daniel,

I’m pretty sure that Swift 2.2 master supports fcntl on both linux and darwin platforms. What version are you using?

This support is done with “overlays” that you can see here:
https://github.com/apple/swift/blob/master/stdlib/public/Glibc/Glibc.swift
https://github.com/apple/swift/blob/master/stdlib/public/SDK/Darwin/Darwin.swift

-Chris

···

On Dec 17, 2015, at 1:47 PM, Daniel Eggert via swift-users <swift-users@swift.org> wrote:

If I need access to the C fcntl(2):

int fcntl(int, int, ...)

can I get the swift-package-manager or swift-build-tool to compile C code that wraps this into a non-vararg version:

This is broken, since fcntl is variadic and you're calling it like a non-variadic function. C doesn't guarantee that variadic and non-variadic ABIs are compatible—this will break watchOS and ARM64 iOS/tvOS, for instance. The latest open-source builds should provide a working fcntl in the Darwin/Glibc overlays.

-Joe

···

On Dec 18, 2015, at 1:52 AM, Daniel Eggert via swift-users <swift-users@swift.org> wrote:

On 17 Dec 2015, at 22:47, Daniel Eggert via swift-users <swift-users@swift.org> wrote:

If I need access to the C fcntl(2):

int fcntl(int, int, ...)

can I get the swift-package-manager or swift-build-tool to compile C code that wraps this into a non-vararg version:

int SocketHelper_fcntl_setFlags(int const fildes, int const flags)
{
  return fcntl(fildes, F_SETFL, flags);
}

int SocketHelper_fcntl_getFlags(int const fildes)
{
  return fcntl(fildes, F_GETFL);
}

?

I solved it like this:

typealias fcntlType = @convention(c) (CInt, CInt, CInt) -> (CInt)
let fcntlAddr = dlsym(UnsafeMutablePointer<Void>(bitPattern: Int(-2)), "fcntl")
let fcntlType: myFcntl = unsafeBitCast(fcntlAddr, fcntlType.self)

which admittedly is a bit tacky, but it works for now.

Indeed. Thanks!

/Daniel

···

On 18 Dec 2015, at 20:42, Chris Lattner <clattner@apple.com> wrote:

On Dec 17, 2015, at 1:47 PM, Daniel Eggert via swift-users <swift-users@swift.org> wrote:

If I need access to the C fcntl(2):

int fcntl(int, int, ...)

can I get the swift-package-manager or swift-build-tool to compile C code that wraps this into a non-vararg version:

Hi Daniel,

I’m pretty sure that Swift 2.2 master supports fcntl on both linux and darwin platforms. What version are you using?

This support is done with “overlays” that you can see here:
https://github.com/apple/swift/blob/master/stdlib/public/Glibc/Glibc.swift
https://github.com/apple/swift/blob/master/stdlib/public/SDK/Darwin/Darwin.swift

-Chris