如何用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
相关产品推荐
相关产品推荐

