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

如何用Python ctypes调用Dlang结构体中的静态load函数?

解决Python调用Dlang共享库中结构体静态函数的问题

首先要明确:Dlang结构体的静态成员函数本质是全局函数,只是命名上和结构体关联,并不会作为结构体实例的成员存储。你的Python代码错误地将其当作结构体字段定义,这是无法调用到目标函数的。

步骤1:修正Dlang代码的导出方式

为了让Python能方便调用,需要在Dlang中用extern(C)标记静态函数,确保导出的符号名符合C规范,避免D的名字修饰。如果需要自定义符号名,还可以用@mangle指定:

struct A
{
    // 用extern(C)导出,让符号名符合C规则;如果需要更友好的名字,加上@mangle
    extern(C) @mangle("A_load") 
    static A* load(const(char)* folder)
    {
        // 将C字符串转为D的string
        string dir = cast(string)folder;
        // 示例:分配A的实例并返回
        return new A();
    }
}

编译成共享库:

dmd -fPIC -shared your_code.d -o libmycode.so

步骤2:Python中调用静态函数

在Python里,直接从共享库中获取导出的全局函数,无需定义结构体的load字段:

from ctypes import *

# 定义函数类型:返回值为void*(对应D的A*),参数为const char*(对应D的const(char)*)
A_LoadFunc = CFUNCTYPE(c_void_p, c_char_p)

if __name__ == '__main__':
    so_path = "./libmycode.so"
    lib = CDLL(so_path)
    
    # 获取导出的静态函数
    a_load = A_LoadFunc(lib.A_load)
    
    # 调用函数:传入bytes类型的路径(对应C的const char*)
    a_ptr = a_load(b"./target_folder")
    
    # 如果需要操作A的实例,可定义结构体字段并转换指针
    class A(Structure):
        # 根据实际结构体字段定义,示例为int类型的id字段
        _fields_ = [("id", c_int)]
    
    # 将void*转为A的指针
    a_instance = cast(a_ptr, POINTER(A))
    # 访问实例字段(如果有的话)
    # print(a_instance.contents.id)

无extern(C)时的备选方案

如果无法修改Dlang代码,需要先查看共享库的符号名:

nm -D libmycode.so

找到类似_D4test1A4loadFAAxaZS4test1A的符号(格式随D模块名变化),然后在Python中直接使用该符号名获取函数:

a_load = A_LoadFunc(lib._D4test1A4loadFAAxaZS4test1A)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 02:05:22