swift 로 만든 정적, 동적 라이브러리를 c, c++ 에서 사용하는 방법
라이브러리 패키지 생성
mkdir MySwiftLib
cd MySwiftLib
swift package init —type library
open Package.swift
Package.swift 수정
라이브러리 type 을 지정해 준다.
// swift-tools-version: 6.0
import PackageDescription
let package = Package(
name: "MySwiftLib",
products: [
.library(
name: "MySwiftLib",
type: .dynamic, // .static
targets: ["MySwiftLib"]
],
targets: [
.target(
name: "MySwiftLib",
path: "Sources/MySwiftLib",
publicHeaderPath: "include"
],
)
swift 함수 작성
c에서 호출할 함수들은 @_cdecl("함수명") 형식으로 작성되어야 한다.
// 기본 함수
@_cdecl("helloWorld")
public func helloWorld() {
print("hello world")
}
// 문자열 입력 함수 예시
@_cdecl("helloWorld")
public func helloWorld(_ cString: UnsafePointer<CChar>) {
let message = String(cString: cString)
print("hello world: \(message)")
}
클래스의 경우 직접 사용은 불가능 하고, 포인터 형으로 전달해 c 에서 void* 로 사용한다.
public class MyClass {
// 클래스 구현
func doSomething() {
print("hello world")
}
}
@_cdecl("createMyClass")
public func createMyClass() -> UnsafeMutableRawPointer {
let obj = MyClass()
return UnsafeMutableRawPointer(Unmanaged.passRetained(obj).toOpaque())
}
@_cdecl("doSomething")
public func doSomething(_ ptr: UnsafeMutableRawPointer) {
let obj = Unmanaged<MyClass>.fromOpaque(ptr).takeUnretainedValue()
obj.doSomething()
}
@_cdecl("releaseMyClass")
public func releaseMyClass(_ ptr: UnsafeMutableRawPointer) {
Unmanaged<MyClass>.fromOpaque(ptr).release()
}
호환 가능한 데이터 타입
Int32 : int32_t / int
UInt32 : uint32_t
Int64 : int64_t / long long
UInt64 : uint64_t
Float : float
Double : double
Bool : bool
UnsafePointer<T> : const T*
UnsafeMutablePointer<T> : void*
Void : void
c에서 include 할 헤더 파일작성
include/MySwiftLib-Swift.h
#ifndef My_SwiftLib_H
#define My_SwiftLib_H
#ifndef __cplusplus
extern "C" {
#endif
// swift 에서 작성한 함수들
void helloWorld(const char *msg)
.
.
.
#ifndef __cplusplus
}
#endif
#endif
라이브러리 빌드
swift build -c release
.build/release/ 폴더에 libMySwiftLib.a 혹은 libMySwiftLib.dylib 생성 확인
c/c++ 샘플 작성
샘플 c 프로젝트 폴더에 헤더와 빌드한 라이브러리 복사
동적 라이브러리의 경우 컴퍼일 시점에 링크해도 되고, 별도 런타임에 연결 할 수도 있음
main.c : 기본적인 연동 방법
#include <stdio.h>
#include "MySiwftLib-Swfit.h"
int main() {
helloWorld("hi");
return 0;
}
main.cpp : 동적라이브러리 + 동적 로드
#include <iostream>
#include <dlfcn.h>
int main() {
void* handle = dlopen("./libMySwiftLib.dylib", RTLD_LAZY);
if (!handle) {
std::cerr << "dlopen error: " << dlerror() << std::endl;
return 1;
}
auto helloWorld = (void(*)() dlsym(handle, "helloWorld");
if (!helloWorld) {
std::cerr << "dlsym error: " << dlerror() << std::endl;
return 1;
}
dlclose(handle);
return 0;
}
빌드
clang main.c -L. -lMySiwftLib -Wl,-rpath,@executable_path -o main
path 구성 등은 라이브러리 위치나 플랫폼에 따라 변경
정적라이브러리 사용하는 경우 swift runtime 위치를 지정해 주어야 한다.
xcrun -find swift 로 현재 swift 바이너리 위치를 얻고, dirname 으로 위치를 수정해 준다.
clang main.c \
-L. -lMySwiftLib \
-L$(dirname $(dirname $(xcrun —find swift)))/lib/swift/macosx \
-o main
'프로그래밍 > iOS,macOS' 카테고리의 다른 글
| [swift] swift에서 c함수호출시 void* 전달 (0) | 2025.10.26 |
|---|---|
| [swift] 커맨드라인 실행 파일 만들기(swift-argument-parser) (0) | 2025.10.16 |
| SPM Package.swift 관련 요소 목록 (0) | 2025.10.14 |
| [swift] SCNProgram 쉐이더 투명 적용 (0) | 2024.10.31 |
| [swift] SceneKit uv animation (0) | 2024.08.22 |
| [swift] swiftui fileImpoter로 파일 선택하기 (0) | 2024.08.08 |
| [concurrency] Task, TaskGroup, task timeout (0) | 2023.02.28 |
| [swift] sorted array 에 값 추가 (0) | 2022.06.10 |
| [concurrency] swift async/await (0) | 2022.05.13 |
| [Combine] 콜백 기반 여러 처리 결과를 배열로 받기 (0) | 2022.03.20 |