如何在 macOS 的 Python 项目中使用 Swift dylib?

How to use Swift dylib in Python Project in macOS?

提问人:Eress 提问时间:9/7/2023 最后编辑:Eress 更新时间:10/30/2023 访问量:117

问:

我使用命令创建了简单的 Swift 包

cd 桌面

mkdir AICore

cd AICore

swift package init --type 库

并将配置编辑为动态库配置,如下所示,

包.Swift

// swift-tools-version: 5.6
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
    name: "AICore",
    platforms: [.macOS(.v10_15)],
    
    products: [  
        .library(name: "AICore", type: .dynamic, targets: ["AICore"]),
    ],
    dependencies: [
    ],
    targets: [
        .target(
            name: "AICore",
            dependencies: [])
    ]
)

AICore.swift:

import Cocoa
 
public func launchMyAppKitWindow() {
    let app = NSApplication.shared
    let window = NSWindow(contentRect: NSRect(x: 0, y: 0, width: 400, height: 300), styleMask: [.titled, .closable, .resizable], backing: .buffered, defer: false)
    window.center()
    window.title = "My AppKit Window"
    window.makeKeyAndOrderFront(nil)
    app.run()
}

项目结构:

├── AICore
│   ├── Package.swift
│   ├── README.md
│   └── Sources
│       └── AICore
│           └── AICore.swift
└── Test
    ├── libAICore.dylib
    └── main.py

我已经使用 swift build 编译了我的 swift 程序,并且我已经取消了 AICore 父文件夹中隐藏的构建文件夹。图书馆位于build->x86_64-apple-macosx->libAICore.dylib

我复制了库并粘贴到 Test 文件夹,该文件夹包含以下要测试的 python 脚本。

import ctypes
# https://docs.python.org/3/library/ctypes.html
# Load the dylib
my_appkit_lib = ctypes.CDLL("/Users/YxT2/Desktop/PY/Test/libAICore.dylib")

# Call the launch function
my_appkit_lib.launchMyAppKitWindow()

我使用命令运行代码并出现以下错误python3 main.py

Traceback (most recent call last):
  File "/Users/YxT2/Desktop/PY/Test/main.py", line 7, in <module>
    my_appkit_lib.launchMyAppKitWindow()
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/Cellar/[email protected]/3.11.3/Frameworks/Python.framework/Versions/3.11/lib/python3.11/ctypes/__init__.py", line 389, in __getattr__
    func = self.__getitem__(name)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/Cellar/[email protected]/3.11.3/Frameworks/Python.framework/Versions/3.11/lib/python3.11/ctypes/__init__.py", line 394, in __getitem__
    func = self._FuncPtr((name_or_ordinal, self))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: dlsym(0x21db45be0, launchMyAppKitWindow): symbol not found

我测试了我的swift代码,它实际上启动了下面的屏幕截图中的窗口。

enter image description here

但是我想使用这个测试库来python代码来调用用Swift编写的函数,谁能帮我解决这个问题?launchMyAppKitWindow

蟒蛇 python-3.x 斯威夫特 cocoa dylib

评论


答:

1赞 xPetersue 9/16/2023 #1
  1. Swift 函数不能直接从 Python 访问,因为 Swift 使用不同的应用程序二进制接口 (ABI)。若要使函数可访问,应使用 @_cdecl 属性对其进行标记以使用 C ABI。像这样修改你的 AICore.swift:
    import Cocoa
    
    @_cdecl("launchMyAppKitWindow")
    public func launchMyAppKitWindow() {
      ...
    }
  1. 编译 AICore.swift。 注:OS X“libAICore.dylib”
    # creates "libXXX.so" (or on OS X, "libAICore.dylib")
    swiftc -emit-library AICore.swift 
    
    
    
    

enter image description here

(上图取自 https://gist.github.com/jiaaro/e111f0f64d0cdb8aca38

  1. main.py 中的路径 - 检查库路径。

    -- 此行错误 --

my_appkit_lib = ctypes.CDLL("/Users/YxT2/Desktop/PY/Test/libAICore.dylib")