复杂 Ctypes 结构的问题
Issues with complex Ctypes Structure
我一直在使用 ctypes 将一些 C 代码 [FANUC FOCAS 库] 移植到 Python。
在我必须移植的最复杂的结构之一中,我无法捕获所有变量的值,也无法找出原因。
In C(来自FANUC的fwlib32.h)
typedef struct speedelm {
long data;
short dec;
short unit;
short disp;
char name;
char suff;
} SPEEDELM ;
typedef struct odbspeed {
SPEEDELM actf;
SPEEDELM acts;
} ODBSPEED ;
FWLIBAPI short WINAPI cnc_rdspeed( unsigned short, short, ODBSPEED * );
然后,对于Python我写道:
import ctypes
class SpeedElmT(ctypes.Structure):
pass
SpeedElmT._fields_ = [
("data", ctypes.c_long),
("dec", ctypes.c_short),
("unit", ctypes.c_short),
("disp", ctypes.c_short),
("name", ctypes.c_char_p),
("suff", ctypes.c_char_p)
]
class ODBSpeed_T(ctypes.Structure):
_fields_ = [
("actf", SpeedElmT),
("acts", SpeedElmT),
]
# import library
fwl = ctypes.cdll.LoadLibrary("/fwlib_path/")
fwl.cnc_rdspeed.argtypes = ctypes.c_ushort, ctypes.c_short, ctypes.POINTER(ODBSpeed_T)
fwl.cnc_rdspeed.restype = ctypes.c_short
一个示例 运行 它在 C 中(在 inventcom.net 找到)
#include "fwlib32.h"
void example( void )
{
ODBSPEED speed;
short ret = cnc_rdspeed(h, -1, &speed);
if(!ret) {
printf("%c = %d\n", speed.actf.name, speed.actf.data);
printf("%c = %d\n", speed.acts.name, speed.acts.data);
}
}
而且,在 Python 我试过
speed = ctypes.pointer(ODBSpeed_T())
r = fwl.cnc_rdspeed(h, ctypes.c_short(-1), speed)
if r == 0:
print(speed[0].actf.data) # This one returns the correct value
print(speed[0].acts.data) # Zero when not Zero
我真的想不通为什么acts.data没有return期望值。
有人可以帮我解决这个问题吗?非常感谢。
错误是 C 代码有 char
而不是 char*
。 Python 中的字段需要 c_char
而不是 c_char_p
因此结构大小错误。
这是一个具有相同接口的测试 DLL:
#include <windows.h>
#ifdef _WIN32
# define FWLIBAPI __declspec(dllexport)
#else
# define FWLIBAPI
#endif
typedef struct speedelm {
long data;
short dec;
short unit;
short disp;
char name;
char suff;
} SPEEDELM;
typedef struct odbspeed {
SPEEDELM actf;
SPEEDELM acts;
} ODBSPEED;
FWLIBAPI short WINAPI cnc_rdspeed(unsigned short a, short b, ODBSPEED* p) {
p->actf.data = a + b;
p->actf.dec = 1;
p->actf.unit = 2;
p->actf.disp = 3;
p->actf.name = 'A';
p->actf.suff = 'B';
p->acts.data = a - b;
p->acts.dec = 4;
p->acts.unit = 5;
p->acts.disp = 6;
p->acts.name = 'C';
p->acts.suff = 'D';
return 7;
}
test.py:
import ctypes
class SpeedElmT(ctypes.Structure):
_fields_ = (('data', ctypes.c_long),
('dec', ctypes.c_short),
('unit', ctypes.c_short),
('disp', ctypes.c_short),
('name', ctypes.c_char), # C code had char not char*
('suff', ctypes.c_char)) # ditto
def __repr__(self):
return f'SpeedElemT({self.data},{self.dec},{self.unit},{self.disp},{self.name},{self.suff})'
class ODBSpeed_T(ctypes.Structure):
_fields_ = (('actf', SpeedElmT),
('acts', SpeedElmT))
def __repr__(self):
return f'ODBSpeed_T({self.actf!r},{self.acts!r})'
fwl = ctypes.WinDLL('./test') # WinDLL for WINAPI, which is __stdcall (matters on 32-bit Python)
fwl.cnc_rdspeed.argtypes = ctypes.c_ushort, ctypes.c_short, ctypes.POINTER(ODBSpeed_T)
fwl.cnc_rdspeed.restype = ctypes.c_short
speed = ODBSpeed_T() # Create an instance
r = fwl.cnc_rdspeed(333, 111, ctypes.byref(speed)) # pass instance by reference
print(r)
print(speed)
输出:
7
ODBSpeed_T(SpeedElemT(444,1,2,3,b'A',b'B'),SpeedElemT(222,4,5,6,b'C',b'D'))
我一直在使用 ctypes 将一些 C 代码 [FANUC FOCAS 库] 移植到 Python。
在我必须移植的最复杂的结构之一中,我无法捕获所有变量的值,也无法找出原因。
In C(来自FANUC的fwlib32.h)
typedef struct speedelm {
long data;
short dec;
short unit;
short disp;
char name;
char suff;
} SPEEDELM ;
typedef struct odbspeed {
SPEEDELM actf;
SPEEDELM acts;
} ODBSPEED ;
FWLIBAPI short WINAPI cnc_rdspeed( unsigned short, short, ODBSPEED * );
然后,对于Python我写道:
import ctypes
class SpeedElmT(ctypes.Structure):
pass
SpeedElmT._fields_ = [
("data", ctypes.c_long),
("dec", ctypes.c_short),
("unit", ctypes.c_short),
("disp", ctypes.c_short),
("name", ctypes.c_char_p),
("suff", ctypes.c_char_p)
]
class ODBSpeed_T(ctypes.Structure):
_fields_ = [
("actf", SpeedElmT),
("acts", SpeedElmT),
]
# import library
fwl = ctypes.cdll.LoadLibrary("/fwlib_path/")
fwl.cnc_rdspeed.argtypes = ctypes.c_ushort, ctypes.c_short, ctypes.POINTER(ODBSpeed_T)
fwl.cnc_rdspeed.restype = ctypes.c_short
一个示例 运行 它在 C 中(在 inventcom.net 找到)
#include "fwlib32.h"
void example( void )
{
ODBSPEED speed;
short ret = cnc_rdspeed(h, -1, &speed);
if(!ret) {
printf("%c = %d\n", speed.actf.name, speed.actf.data);
printf("%c = %d\n", speed.acts.name, speed.acts.data);
}
}
而且,在 Python 我试过
speed = ctypes.pointer(ODBSpeed_T())
r = fwl.cnc_rdspeed(h, ctypes.c_short(-1), speed)
if r == 0:
print(speed[0].actf.data) # This one returns the correct value
print(speed[0].acts.data) # Zero when not Zero
我真的想不通为什么acts.data没有return期望值。
有人可以帮我解决这个问题吗?非常感谢。
错误是 C 代码有 char
而不是 char*
。 Python 中的字段需要 c_char
而不是 c_char_p
因此结构大小错误。
这是一个具有相同接口的测试 DLL:
#include <windows.h>
#ifdef _WIN32
# define FWLIBAPI __declspec(dllexport)
#else
# define FWLIBAPI
#endif
typedef struct speedelm {
long data;
short dec;
short unit;
short disp;
char name;
char suff;
} SPEEDELM;
typedef struct odbspeed {
SPEEDELM actf;
SPEEDELM acts;
} ODBSPEED;
FWLIBAPI short WINAPI cnc_rdspeed(unsigned short a, short b, ODBSPEED* p) {
p->actf.data = a + b;
p->actf.dec = 1;
p->actf.unit = 2;
p->actf.disp = 3;
p->actf.name = 'A';
p->actf.suff = 'B';
p->acts.data = a - b;
p->acts.dec = 4;
p->acts.unit = 5;
p->acts.disp = 6;
p->acts.name = 'C';
p->acts.suff = 'D';
return 7;
}
test.py:
import ctypes
class SpeedElmT(ctypes.Structure):
_fields_ = (('data', ctypes.c_long),
('dec', ctypes.c_short),
('unit', ctypes.c_short),
('disp', ctypes.c_short),
('name', ctypes.c_char), # C code had char not char*
('suff', ctypes.c_char)) # ditto
def __repr__(self):
return f'SpeedElemT({self.data},{self.dec},{self.unit},{self.disp},{self.name},{self.suff})'
class ODBSpeed_T(ctypes.Structure):
_fields_ = (('actf', SpeedElmT),
('acts', SpeedElmT))
def __repr__(self):
return f'ODBSpeed_T({self.actf!r},{self.acts!r})'
fwl = ctypes.WinDLL('./test') # WinDLL for WINAPI, which is __stdcall (matters on 32-bit Python)
fwl.cnc_rdspeed.argtypes = ctypes.c_ushort, ctypes.c_short, ctypes.POINTER(ODBSpeed_T)
fwl.cnc_rdspeed.restype = ctypes.c_short
speed = ODBSpeed_T() # Create an instance
r = fwl.cnc_rdspeed(333, 111, ctypes.byref(speed)) # pass instance by reference
print(r)
print(speed)
输出:
7
ODBSpeed_T(SpeedElemT(444,1,2,3,b'A',b'B'),SpeedElemT(222,4,5,6,b'C',b'D'))