You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用ctypes分发含Go编译.so文件的Python库遇导入错误

解决导入Go编译共享库时的ImportError: dynamic module does not define module export function问题

你遇到的问题核心是把普通C共享库当成了Python原生扩展模块来配置setuptools,导致Python导入时找不到它期望的PyInit_display_status函数。咱们一步步拆解解决:

问题根源

你用Go编译的display_status.so是标准的C共享库,不是符合Python扩展规范的模块——Python扩展必须导出PyInit_<module_name>函数,而你的Go库没有这个入口。之前setup.py里的Extension配置,让setuptools误以为要构建Python原生扩展,完全偏离了用ctypes加载普通共享库的需求。

另外,本地运行正常是因为脚本能直接找到当前目录下的.so,但安装到PyPI后,库文件会被放到site-packages的子目录里,原有的相对路径加载方式会失效,这也是要修正的点。

修正后的setup.py配置

先移除错误的Extension部分,正确配置package_data来包含预编译的共享库:

import pathlib
from setuptools import setup, find_packages

HERE = pathlib.Path(__file__).parent
README = (HERE / "README.md").read_text()

setup(
    name="display_status",
    version="1.0.11",
    description="Displays the status of links",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/KingAkeem/display_status",
    author="Akeem King",
    author_email="akeemtlking@gmail.com",
    license="GNU GPLv3",
    classifiers=[
        "License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)",
        "Programming Language :: Python :: 3",
        "Programming Language :: Python :: 3.6",
    ],
    packages=find_packages(),
    # 明确指定要打包的共享库文件
    package_data={
        'display_status': [
            'display_status.so',
            # 如果.h文件不需要安装可以移除
            'display_status.h'
        ]
    },
    include_package_data=True,
    python_requires=">=3.6"
)

修改Python库中的.so加载逻辑

安装后.so的路径不再是本地相对路径,需要用Python的资源加载工具获取正确位置,提供两种兼容方案:

方案1:Python 3.7+ 使用importlib.resources

import ctypes
from importlib.resources import files

def load_go_library():
    # 获取安装后共享库的绝对路径
    lib_path = files('display_status').joinpath('display_status.so')
    # 加载共享库
    lib = ctypes.CDLL(str(lib_path))
    
    # 根据你的Go函数实际情况,配置参数和返回类型
    # 示例:假设Go函数CheckLink接收字符串,返回状态码
    lib.CheckLink.argtypes = [ctypes.c_char_p]
    lib.CheckLink.restype = ctypes.c_int
    
    return lib

# 初始化全局库实例
go_lib = load_go_library()

# 封装成Python函数供用户调用
def check_link_status(url):
    return go_lib.CheckLink(url.encode('utf-8'))

方案2:兼容Python 3.6 使用pkg_resources

import ctypes
import pkg_resources

def load_go_library():
    # 获取安装后共享库的绝对路径
    lib_path = pkg_resources.resource_filename('display_status', 'display_status.so')
    lib = ctypes.CDLL(lib_path)
    
    # 配置Go函数的参数和返回类型
    lib.CheckLink.argtypes = [ctypes.c_char_p]
    lib.CheckLink.restype = ctypes.c_int
    
    return lib

go_lib = load_go_library()

额外注意事项

  1. 跨平台支持:预编译的.so仅适用于对应平台(比如Linux x86_64),如果要支持Windows(.dll)、macOS(.dylib),需要交叉编译Go代码生成对应平台的共享库,再在setup.py中根据平台选择对应文件。
  2. Go编译验证:确保你用正确命令生成C共享库:
    go build -buildmode=c-shared -o display_status.so main.go
    

内容的提问来源于stack exchange,提问作者Akeem

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:19:52