Wrap a local C .so shared library

I have .so library written in C under my home directory:
/home/ljh/libhello.so,
/home/ljh/hello.h,

I create swift package to wrap the .so like this:
swift package init --type system-module

in Package.swift:
name: "hello",
dependencies: [
//path: for url:
.package(name: "hello", url: "/home/ljh/libhello.so"),
]

and in module.modulemap:
module hello [system] {
header "/home/ljh/hello.h"
link "hello"
export *
}

But it doesn't work.

Can you support path: instead of url: here for local .so shared library too:
.package(name: "hello", path: "/home/ljh/libhello.so"),

I think you can get away with url: file:///home/ljh/libhello.so

I follow this link:

https://github.com/apple/swift-package-manager/blob/main/Documentation/Usage.md

But keep getting this error:

$ swift build -Xlinker -L/home/ljh/hello/
'example' /home/ljh/example: warning: system packages are deprecated; use system library targets instead
error: the package does not contain a buildable target
$

To wrap a local C shared library you don't express it as a dependency. Swift Package Manager dependencies can only be other Swift packages, not a naked .so file. Instead, you do what the warning tells you, and use a system library target instead.

Your Package.swift should look like this:

let package = Package(
    name: "hello",
    dependencies: [],
    targets: [
        .systemLibrary(name: "hello")
    ]
)

You then need to create a directory at Sources/hello, and put your module.modulemap inside that directory.

You can then build with swift build -Xlinker -L/home/ljh/hello/.

3 Likes

Thanks

Finally got it to work :)

[1] GitHub - ljhm/Swift-C: Use C code from shared library in Swift
[2] System target library: How to use them? - #2 by taylorswift
[3] swift-package-manager/Usage.md at 263171977ebcd47f4aaca1202cff5a96c5158a64 · apple/swift-package-manager · GitHub

Hi,

Can I also call C function directly from source code {.c,.h} instead of shared library {.so}, in Swift?

Can I call C++ function in Swift too?

Thanks

You can build both C and C++ using the Swift Package Manager. You can find more on this topic in How to call C code from Swift - The.Swift.Dev.. How to use C code from Swift is described here: Apple Developer Documentation. Notice, that using Clang, you can annotate your C API to work with Swift in better fashion.

Notice, that Swift does not have the same level of interoperability with Cpp as with C. Nor is to my knowledge ObjC available on non-Apple platform. AFAIK you can use only APIs exposed using extern "C".
You can also execute Swift code from C using @convention(c) closured and @_cdecl annotated global functions.

1 Like