使用ctypes调用带结构体指针的函数

4 投票
2 回答
2605 浏览
提问于 2025-04-15 16:37

我想从Python中调用一个在共享对象里的C函数,使用ctypes似乎是实现这个目标的最佳方法。我需要将派生类型传递给这个函数,函数的原型如下:

int MyFunc (Config *config, int *argc, char **argv )

Config结构体的定义是:

 typedef struct{ char *some_filename ;
                 char **some_other_filenames ;
                 int some_value ;
                 Coord resolution;
               } Config; 

Coord的定义是:

 typdef struct { double x, y, area }  Coord ;

然后,Python中的ctypes代码只是对派生类型的重新编写:

 class COORD ( ctypes.Structure ):
       _fields = [ ("lon",ctypes.c_double),\
       ("lat", ctypes.c_double),\
       ("area", ctypes.c_double)]
 coords = COORD()
 class CONFIG( ctypes.Structure ):
       _fields = [ ("some_filename", ctypes.c_char_p),\
       ("some_other_filenames", ctypes.c_char_p('\0' * 256)),\
       ("some_value", ctypes.c_int ),\
       ("resolution", coords )   ]

接着,我为MyFunc设置了参数:

 MyFunc.argtypes = [ctypes.byref(CONFIG ) , ctypes.POINTER(ctypes.c_int),\
        ctypes.POINTER (ctypes.c_char_p)]
 MyFunc.restype = ctypes.c_int 
 myargv = ctypes.c_char_p * 2
 argv = myargv("One", "Two")
 argc = ctypes.c_int ( 2 )
 retval = MyFunc (  ctypes.byref(config), ctypes.byref(argc), ctypes(argv))

但是,这样做却导致了段错误(segfault)。有没有人知道这里发生了什么?

更新
我在问题中有个拼写错误,是因为复制粘贴,问题依然存在!

2 个回答

1

看起来你重新写的配置结构和原来的不太一样。如果你在两个之间来回传递的话,可能会对不上。

补充:我看到你修复了一部分。但我不太确定c_char_p和char**是不是一样的。

2

char** 对应的是 POINTER(c_char_p),而不是 c_char_p。

撰写回答