python stack在哪个模块_python ctypes 模块

ctype模块可以让python 调用c写的动态库。主要是对应两种语言的基本数据类型,指针,函数指针,结构体等类型的支持,从而可以让python可调用c库。

ff65c5262b7294a388709ae548ec3158.png

例子1,用c自定义一个函数,编译后用python调用:

great_module.c

C

// great_module.c

//#include

#ifdef _MSC_VER

#define DLL_EXPORT __declspec( dllexport )

#else

#define DLL_EXPORT

#endif

DLL_EXPORT int great_function(unsigned int n) {

//return __mm_popcnt_u32(n);

return n+1;

}

DLL_EXPORT int array_get(int a[], int index) {

return a[index];

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

// great_module.c

//#include

#ifdef _MSC_VER

#define DLL_EXPORT __declspec( dllexport )

#else

#define DLL_EXPORT

#endif

DLL_EXPORTintgreat_function(unsignedintn){

//return __mm_popcnt_u32(n);

returnn+1;

}

DLL_EXPORTintarray_get(inta[],intindex){

returna[index];

}

编译后生成动态库文件:

linux:

Shell

gcc -fPIC -shared great_module.c -o great_module.so

1

gcc-fPIC-sharedgreat_module.c-ogreat_module.so

windows:

Shell

gcc -fPIC -shared great_module.c -o great_module.dll

1

gcc-fPIC-sharedgreat_module.c-ogreat_module.dll

python 调用动态库:

great_module_test.py

Python

from ctypes import *

# igreat_module = cdll.LoadLibrary('./great_module.dll')

great_module = cdll.LoadLibrary('./great_module.so')

print great_module.great_function(15)

type_int_array_10 = c_int * 10 # generate ctypes array of basic type

my_array = type_int_array_10() # instantiate a object using new array type

my_array[2] = c_int(5)

print great_module.array_get(my_array,2) #5

print great_module.array_get(my_array,1) #0

print great_module.array_get(my_array,0) #0

1

2

3

4

5

6

7

8

9

10

11

fromctypesimport*

# igreat_module = cdll.LoadLibrary('./great_module.dll')

great_module=cdll.LoadLibrary('./great_module.so')

printgreat_module.great_function(15)

type_int_array_10=c_int*10# generate ctypes array of basic type

my_array=type_int_array_10()# instantiate a object using new array type

my_array[2]=c_int(5)

printgreat_module.array_get(my_array,2)#5

printgreat_module.array_get(my_array,1)#0

printgreat_module.array_get(my_array,0)#0

运行结果:

Shell

pi@raspberrypi:~/python-ctypes $ python great_module_test.py

16

5

0

0

1

2

3

4

5

pi@raspberrypi:~/python-ctypes$pythongreat_module_test.py

16

5

0

0

例子2, 调用系统的printf函数, 跨平台支持mac, linux, windows:

printf.py

Python

from ctypes import *

from platform import *

print system()

cdll_names = {

'Darwin' : 'libc.dylib',

'Linux' : 'libc.so.6',

'Windows': 'msvcrt.dll'

}

clib = cdll.LoadLibrary(cdll_names[system()])

clib.printf(c_char_p("Hello %d %f\n"), c_int(15), c_double(2.3))

str_format = c_char_p()

int_val = c_int()

double_val = c_double()

str_format.value = "Hello %d %f\n"

int_val.value = 15

double_val.value = 2.3

clib.printf(str_format, int_val, double_val)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

fromctypesimport*

fromplatformimport*

printsystem()

cdll_names={

'Darwin':'libc.dylib',

'Linux':'libc.so.6',

'Windows':'msvcrt.dll'

}

clib=cdll.LoadLibrary(cdll_names[system()])

clib.printf(c_char_p("Hello %d %f\n"),c_int(15),c_double(2.3))

str_format=c_char_p()

int_val=c_int()

double_val=c_double()

str_format.value="Hello %d %f\n"

int_val.value=15

double_val.value=2.3

clib.printf(str_format,int_val,double_val)

运行结果:

Shell

pi@raspberrypi:~/python-ctypes $ python printf.py

Linux

Hello 15 0.000000

Hello 15 0.000000

1

2

3

4

pi@raspberrypi:~/python-ctypes$pythonprintf.py

Linux

Hello150.000000

Hello150.000000

例子3,关于类型自动转换:

可以自动转换:

001_type_auto_conv_Pass.py

Python

from ctypes import *

from platform import *

cdll_names = {

'Darwin' : 'libc.dylib',

'Linux' : 'libc.so.6',

'Windows': 'msvcrt.dll'

}

clib = cdll.LoadLibrary(cdll_names[system()])

# can auto convert type

s1 = c_char_p('a')

s3 = clib.strcat(s1, 'b')

print s1.value #ab

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

fromctypesimport*

fromplatformimport*

cdll_names={

'Darwin':'libc.dylib',

'Linux':'libc.so.6',

'Windows':'msvcrt.dll'

}

clib=cdll.LoadLibrary(cdll_names[system()])

# can auto convert type

s1=c_char_p('a')

s3=clib.strcat(s1,'b')

prints1.value#ab

运行结果:

能自动转换

Shell

pi@raspberrypi:~/python-ctypes $ python 001_type_auto_conv_Pass.py

ab

1

2

pi@raspberrypi:~/python-ctypes$python001_type_auto_conv_Pass.py

ab

001_type_auto_conv_Fail.py

Python

from ctypes import *

from platform import *

cdll_names = {

'Darwin' : 'libc.dylib',

'Linux' : 'libc.so.6',

'Windows': 'msvcrt.dll'

}

clib = cdll.LoadLibrary(cdll_names[system()])

# can Not auto convert type

clib.printf(c_char_p("Hello %d %f"), 15, 2.3)

1

2

3

4

5

6

7

8

9

10

11

12

13

fromctypesimport*

fromplatformimport*

cdll_names={

'Darwin':'libc.dylib',

'Linux':'libc.so.6',

'Windows':'msvcrt.dll'

}

clib=cdll.LoadLibrary(cdll_names[system()])

# can Not auto convert type

clib.printf(c_char_p("Hello %d %f"),15,2.3)

结果:

不能自动转换,报错

Shell

pi@raspberrypi:~/python-ctypes $ python 001_type_auto_conv_Fail.py

Traceback (most recent call last):

File "001_type_auto_conv_Fail.py", line 13, in

clib.printf(c_char_p("Hello %d %f"), 15, 2.3)

ctypes.ArgumentError: argument 3: : Don't know how to convert parameter 3

1

2

3

4

5

pi@raspberrypi:~/python-ctypes$python001_type_auto_conv_Fail.py

Traceback(mostrecentcalllast):

File"001_type_auto_conv_Fail.py",line13,in

clib.printf(c_char_p("Hello %d %f"),15,2.3)

ctypes.ArgumentError:argument3::Don'tknowhowtoconvertparameter3

例子4, 函数的参数可以是指针类型,然后可以通过参数返回值:

002_pointer_return_value.py

Python

from ctypes import *

from platform import *

cdll_names = {

'Darwin' : 'libc.dylib',

'Linux' : 'libc.so.6',

'Windows': 'msvcrt.dll'

}

clib = cdll.LoadLibrary(cdll_names[system()])

s1 = c_char_p('a')

s2 = c_char_p('b')

s3 = clib.strcat(s1,s2)

print s1.value #ab

1

2

3

4

5

6

7

8

9

10

11

12

13

14

fromctypesimport*

fromplatformimport*

cdll_names={

'Darwin':'libc.dylib',

'Linux':'libc.so.6',

'Windows':'msvcrt.dll'

}

clib=cdll.LoadLibrary(cdll_names[system()])

s1=c_char_p('a')

s2=c_char_p('b')

s3=clib.strcat(s1,s2)

prints1.value#ab

运行结果:

Shell

pi@raspberrypi:~/python-ctypes $ python 002_pointer_return_value.py

ab

1

2

pi@raspberrypi:~/python-ctypes$python002_pointer_return_value.py

ab

例子5, 指定返回值类型:

Python

from ctypes import *

from platform import *

cdll_names = {

'Darwin' : 'libc.dylib',

'Linux' : 'libc.so.6',

'Windows' : 'msvcrt.dll'

}

clib = cdll.LoadLibrary(cdll_names[system()])

s3 = clib.strcat('a', 'b')

print s3 # return a number, not 'ab'

clib.strcat.restype = c_char_p

s4 = clib.strcat('c', 'd')

print s4 # cd

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

fromctypesimport*

fromplatformimport*

cdll_names={

'Darwin':'libc.dylib',

'Linux':'libc.so.6',

'Windows':'msvcrt.dll'

}

clib=cdll.LoadLibrary(cdll_names[system()])

s3=clib.strcat('a','b')

prints3# return a number, not 'ab'

clib.strcat.restype=c_char_p

s4=clib.strcat('c','d')

prints4# cd

运行结果:

Shell

pi@raspberrypi:~/python-ctypes $ python 003_return_type_specify.py

1992801740

cd

1

2

3

pi@raspberrypi:~/python-ctypes$python003_return_type_specify.py

1992801740

cd

例子6, 关于多维数组,ctype 重载了 * 号

重载*号,用于生成多维数组类型

Python

from ctypes import *

type_int_array_10 = c_int * 10

type_int_array_10_10 = type_int_array_10 * 10

my_array = type_int_array_10_10()

my_array[1][2] = 3

1

2

3

4

5

6

fromctypesimport*

type_int_array_10=c_int*10

type_int_array_10_10=type_int_array_10*10

my_array=type_int_array_10_10()

my_array[1][2]=3

例子7, 指针, 用POINTER(),pointer()

用POINTER(), pointer()

Python

from ctypes import *

type_p_int = POINTER(c_int)

v = c_int(4)

p_int = type_p_int(v)

print type(p_int)

print p_int[0]

print p_int.contents

print p_int[100], "\n"

# ------above and below result are the same------

p_int = pointer(v)

print type(p_int)

print p_int[0]

print p_int.contents

print p_int[100], "\n"

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

fromctypesimport*

type_p_int=POINTER(c_int)

v=c_int(4)

p_int=type_p_int(v)

printtype(p_int)

printp_int[0]

printp_int.contents

printp_int[100],"\n"

# ------above and below result are the same------

p_int=pointer(v)

printtype(p_int)

printp_int[0]

printp_int.contents

printp_int[100],"\n"

运行结果:

Shell

pi@raspberrypi:~/python-ctypes $ python 005_POINTER_type.py

4

c_long(4)

1992517056

4

c_long(4)

1992517056

1

2

3

4

5

6

7

8

9

10

pi@raspberrypi:~/python-ctypes$python005_POINTER_type.py

4

c_long(4)

1992517056

4

c_long(4)

1992517056

例子8,关于函数指针,用CFUNCTYPE()

Python

from ctypes import *

from platform import *

cdll_names = {

'Darwind' : 'libc.dylib',

'Linux' : 'libc.so.6',

'Windows' : 'msvcrt.dll'

}

clib = cdll.LoadLibrary(cdll_names[system()])

CMPFUNC = CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))

def py_cmp_func(a, b):

print type(a)

print "py_cmp_func", a[0], b[0]

return a[0] - b[0]

type_array_5 = c_int * 5

ia = type_array_5(5, 1, 7, 33, 99)

clib.qsort(ia, len(ia), sizeof(c_int), CMPFUNC(py_cmp_func))

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

fromctypesimport*

fromplatformimport*

cdll_names={

'Darwind':'libc.dylib',

'Linux':'libc.so.6',

'Windows':'msvcrt.dll'

}

clib=cdll.LoadLibrary(cdll_names[system()])

CMPFUNC=CFUNCTYPE(c_int,POINTER(c_int),POINTER(c_int))

defpy_cmp_func(a,b):

printtype(a)

print"py_cmp_func",a[0],b[0]

returna[0]-b[0]

type_array_5=c_int*5

ia=type_array_5(5,1,7,33,99)

clib.qsort(ia,len(ia),sizeof(c_int),CMPFUNC(py_cmp_func))

运行结果, linux和windows的结果有点不一样:

linux

Shell

pi@raspberrypi:~/python-ctypes $ python 006_pointer_function.py

py_cmp_func 5 1

py_cmp_func 33 99

py_cmp_func 7 33

py_cmp_func 1 7

py_cmp_func 5 7

1

2

3

4

5

6

7

8

9

10

11

pi@raspberrypi:~/python-ctypes$python006_pointer_function.py

py_cmp_func51

py_cmp_func3399

py_cmp_func733

py_cmp_func17

py_cmp_func57

windows

Shell

c:\python-ctypes>python 006_pointer_function.py

py_cmp_func 1 5

py_cmp_func 7 5

py_cmp_func 33 7

py_cmp_func 99 33

py_cmp_func 1 5

py_cmp_func 7 5

py_cmp_func 33 7

py_cmp_func 1 5

py_cmp_func 7 5

py_cmp_func 1 5

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

c:\python-ctypes>python006_pointer_function.py

py_cmp_func15

py_cmp_func75

py_cmp_func337

py_cmp_func9933

py_cmp_func15

py_cmp_func75

py_cmp_func337

py_cmp_func15

py_cmp_func75

py_cmp_func15

还参考了:

官方DOC:

dir(ctypes), 手动分了行,好看些:

Shell

pi@raspberrypi:~/python-ctypes $ python

Python 2.7.9 (default, Sep 17 2016, 20:26:04)

[GCC 4.9.2] on linux2

Type "help", "copyright", "credits" or "license" for more information.

>>> import ctypes

>>> dir(ctypes)

['ARRAY',

'ArgumentError',

'Array',

'BigEndianStructure',

'CDLL',

'CFUNCTYPE',

'DEFAULT_MODE',

'LibraryLoader',

'LittleEndianStructure',

'POINTER',

'PYFUNCTYPE',

'PyDLL',

'RTLD_GLOBAL',

'RTLD_LOCAL',

'SetPointerType',

'Structure',

'Union',

'_CFuncPtr',

'_FUNCFLAG_CDECL',

'_FUNCFLAG_PYTHONAPI',

'_FUNCFLAG_USE_ERRNO',

'_FUNCFLAG_USE_LASTERROR',

'_Pointer',

'_SimpleCData',

'__builtins__',

'__doc__',

'__file__',

'__name__',

'__package__',

'__path__',

'__version__',

'_c_functype_cache',

'_calcsize',

'_cast',

'_cast_addr',

'_check_size',

'_ctypes_version',

'_dlopen',

'_endian',

'_memmove_addr',

'_memset_addr',

'_os',

'_pointer_type_cache',

'_reset_cache',

'_string_at',

'_string_at_addr',

'_sys',

'_wstring_at',

'_wstring_at_addr',

'addressof',

'alignment',

'byref',

'c_bool',

'c_buffer',

'c_byte',

'c_char',

'c_char_p',

'c_double',

'c_float',

'c_int',

'c_int16',

'c_int32',

'c_int64',

'c_int8',

'c_long',

'c_longdouble',

'c_longlong',

'c_short',

'c_size_t',

'c_ssize_t',

'c_ubyte',

'c_uint',

'c_uint16',

'c_uint32',

'c_uint64',

'c_uint8',

'c_ulong',

'c_ulonglong',

'c_ushort',

'c_void_p',

'c_voidp',

'c_wchar',

'c_wchar_p',

'cast',

'cdll',

'create_string_buffer',

'create_unicode_buffer',

'get_errno',

'memmove',

'memset',

'pointer',

'py_object',

'pydll',

'pythonapi',

'resize',

'set_conversion_mode',

'set_errno',

'sizeof',

'string_at',

'wstring_at']

>>>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

pi@raspberrypi:~/python-ctypes$python

Python2.7.9(default,Sep172016,20:26:04)

[GCC4.9.2]onlinux2

Type"help","copyright","credits"or"license"formoreinformation.

>>>importctypes

>>>dir(ctypes)

['ARRAY',

'ArgumentError',

'Array',

'BigEndianStructure',

'CDLL',

'CFUNCTYPE',

'DEFAULT_MODE',

'LibraryLoader',

'LittleEndianStructure',

'POINTER',

'PYFUNCTYPE',

'PyDLL',

'RTLD_GLOBAL',

'RTLD_LOCAL',

'SetPointerType',

'Structure',

'Union',

'_CFuncPtr',

'_FUNCFLAG_CDECL',

'_FUNCFLAG_PYTHONAPI',

'_FUNCFLAG_USE_ERRNO',

'_FUNCFLAG_USE_LASTERROR',

'_Pointer',

'_SimpleCData',

'__builtins__',

'__doc__',

'__file__',

'__name__',

'__package__',

'__path__',

'__version__',

'_c_functype_cache',

'_calcsize',

'_cast',

'_cast_addr',

'_check_size',

'_ctypes_version',

'_dlopen',

'_endian',

'_memmove_addr',

'_memset_addr',

'_os',

'_pointer_type_cache',

'_reset_cache',

'_string_at',

'_string_at_addr',

'_sys',

'_wstring_at',

'_wstring_at_addr',

'addressof',

'alignment',

'byref',

'c_bool',

'c_buffer',

'c_byte',

'c_char',

'c_char_p',

'c_double',

'c_float',

'c_int',

'c_int16',

'c_int32',

'c_int64',

'c_int8',

'c_long',

'c_longdouble',

'c_longlong',

'c_short',

'c_size_t',

'c_ssize_t',

'c_ubyte',

'c_uint',

'c_uint16',

'c_uint32',

'c_uint64',

'c_uint8',

'c_ulong',

'c_ulonglong',

'c_ushort',

'c_void_p',

'c_voidp',

'c_wchar',

'c_wchar_p',

'cast',

'cdll',

'create_string_buffer',

'create_unicode_buffer',

'get_errno',

'memmove',

'memset',

'pointer',

'py_object',

'pydll',

'pythonapi',

'resize',

'set_conversion_mode',

'set_errno',

'sizeof',

'string_at',

'wstring_at']

>>>

打赏

8eae9108a78867806b4e64ad29af48f8.png微信扫一扫,打赏作者吧~

Post Views:

2,760

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值