How to declare structure as return type of typealias in Swift

I am using .dylib for using c function in swift package. I am using dlopen function of swift for using from c function . c function (i.e uplink function ) will return a structure . for this method i have to create typealias of c function .

C struture

typedef struct Uplink  { long _handle; } UplinkRef;

C function declaration

extern UplinkRef uplink(UplinkConfig p0, char** p1);

uplink function in c will return UplinkRef structure.

So i have declared UplinkRef structure in swift for typealias

UplinkRef struct in swift

struct UplinkRef{
 var _handle = -1
}

I have to create typealias in swift so that i can call c function

typealias uplink = @convention(c) ()->UplinkRef

Swift code that i am using is

let handle = dlopen("test.dylib", RTLD_LOCAL|RTLD_NOW)
            if(handle != nil){
                print("Handle")
                let sym = dlsym(handle, "uplink")
                if(sym != nil){
                 let uplink = unsafeBitCast(sym, to: uplink.self)

                }
}
  1. Anyother method that i can use for calling c function from .dylib file ?
  2. How can i define structure (i.e UplinkRef) as returned type of typealise ?
    i have used code below for declaring typealias
    typealias Uplink1 = (()->(UplinkRef))
    
    But getting error while bitCast
    let uplink = unsafeBitCast(sym, to: uplink.self)
    
  3. How can i define structure (i.e UplinkRef) as argument of typealias ?
  4. Can i add Bridging-Header file in swift package because i was getting error of 2 different language not allowed ?

There are a bunch of challenges here but the one you need to solve first is defining a Swift equivalent of the UplinkRef C structure. What you’re currently doing is not valid because it relies on Swift and C structs laying out the same way, and that’s not something we guarantee [1]. Right now, the only way to get a Swift struct that lays out the same way as a C struct is no import the struct from C.

As with your earlier thread, I recommend that you start by putting these C declarations in a bridging header. That will allow you to get your dynamic loader code working. Once you have that sorted out, you can tackle the problem of making these declarations available in your SPM setup.

Share and Enjoy

Quinn “The Eskimo!” @ DTS @ Apple

[1] Admittedly, for a struct with a single integer member there’s limited scope for problems, but it’s best to start out on the right path.

3 Likes

@eskimo Thanks for replying .
can i add Bridging-Header file to Swift Package in swift 5 ?

can i add Bridging-Header file to Swift Package in swift 5 ?

I believe the answer is “No”, but I don’t know enough about SPM to give you a definitive answer.

@NeoNacho, can you help out here?

Share and Enjoy

Quinn “The Eskimo!” @ DTS @ Apple

1 Like

You're right, Swift packages don't have support for bridging headers.

1 Like

Since you're using SPM, you can put the C header in a separate target that you then import in the Swift source files of your main target.

You can look at swift-nio for examples of how to do this. For example, it defines a CNIOSHA1 target with C source code that declares SHA1_CTX (a typedef for a struct) and some functions that operate on SHA1_CTX. Then in the NIOWebSocket target, it uses the C-defined type and functions from Swift.

1 Like