Files
ailearning/docs/da/099.md
2020-10-19 21:08:55 +08:00

194 lines
2.6 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ctypes
## 基本用法
`ctypes` 是一个方便 `Python` 调用本地已经编译好的外部库的模块。
In [1]:
```py
from ctypes import util, CDLL
```
## 标准 C 库
使用 `util` 来找到标准 `C` 库:
In [2]:
```py
libc_name = util.find_library('c')
# on WINDOWS
print libc_name
```
```py
msvcr90.dll
```
使用 `CDLL` 来加载 `C` 库:
In [3]:
```py
libc = CDLL(libc_name)
```
libc 包含 `C` 标准库中的函数:
In [4]:
```py
libc.printf
```
Out[4]:
```py
<_FuncPtr object at 0x0000000003CEE048>
```
调用这个函数:
In [5]:
```py
libc.printf("%s, %d\n", "hello", 5)
```
Out[5]:
```py
9
```
这里显示的 `9``printf` 的返回值表示显示的字符串的长度(包括结尾的 `'\0'`),但是并没有显示结果,原因是 `printf` 函数默认是写在标准输出流上的,与 `IPython` 使用的输出流不一样,所以没有显示结果。
## C 数学库
找到数学库:
In [6]:
```py
libm_name = util.find_library('m')
print libm_name
```
```py
msvcr90.dll
```
调用 `atan2` 函数:
In [7]:
```py
libm = CDLL(libm_name)
libm.atan2(1.0, 2.0)
```
```py
---------------------------------------------------------------------------
ArgumentError Traceback (most recent call last)
<ipython-input-7-e784e41ee9f3> in <module>()
1 libm = CDLL(libm_name)
2
----> 3 libm.atan2(1.0, 2.0)
ArgumentError: argument 1: <type 'exceptions.TypeError'>: Don't know how to convert parameter 1
```
调用这个函数出错,原因是我们需要进行一些额外工作,告诉 `Python` 函数的参数和返回值是什么样的:
In [8]:
```py
from ctypes import c_double
libm.atan2.argtypes = [c_double, c_double]
libm.atan2.restype = c_double
```
In [9]:
```py
libm.atan2(1.0, 2.0)
```
Out[9]:
```py
0.4636476090008061
```
`Python` 数学库中的结果一致:
In [10]:
```py
from math import atan2
```
In [11]:
```py
atan2(1.0, 2.0)
```
Out[11]:
```py
0.4636476090008061
```
## Numpy 和 ctypes
假设我们有这样的一个函数:
```py
float _sum(float *vec, int len) {
float sum = 0.0;
int i;
for (i = 0; i < len; i++) {
sum += vec[i];
}
return sum
}
```
并且已经编译成动态链接库,那么我们可以这样调用:
```py
from ctypes import c_float, CDLL, c_int
from numpy import array, float32
from numpy.ctypeslib import ndpointer
x = array([1,2,3,4], dtype=float32)
lib = CDLL(<path>)
ptr = ndpointer(float32, ndim=1, flags='C')
lib._sum.argtypes = [ptr, c_int]
lib._sum.restype = c_float
result = lib._sum(x, len(x))
```