你有一些C函数已经被编译到共享库或DLL中。你希望可以使用纯Python代码调用这些函数, 而不用编写额外的C代码或使用第三方扩展工具。
可以参考这篇文章: https://www.baidu.com/link?url=6djl4oF9q-bjXsKIc7n5xA5eoO3YbD_ISURCaytWx9o0B2dmmEhXclgxb_R
对于需要调用C代码的一些小的问题,通常使用Python标准库中的 ctypes 模块就足够了。 要使用 ctypes ,你首先要确保你要访问的C代码已经被编译到和Python解释器兼容 (同样的架构、字大小、编译器等)的某个共享库中了。 为了进行本节的演示,假设你有一个共享库名字叫 libsample.so ,里面的内容就是15章介绍部分那样。 另外还假设这个 libsample.so 文件被放置到位于 sample.py 文件相同的目录中了。
要访问这个函数库,你要先构建一个包装它的Python模块,如下这样:
# sample.py
import ctypes
import os
# Try to locate the .so file in the same directory as this file
_file = 'libsample.so'
_path = os.path.join(*(os.path.split(__file__)[:-1] + (_file,)))
_mod = ctypes.cdll.LoadLibrary(_path)
# int gcd(int, int)
gcd = _mod.gcd
gcd.argtypes = (ctypes.c_int, ctypes.c_int)
gcd.restype = ctypes.c_int
# int in_mandel(double, double, int)
in_mandel = _mod.in_mandel
in_mandel.argtypes = (ctypes.c_double, ctypes.c_double, ctypes.c_int)
in_mandel.restype = ctypes.c_int
# int divide(int, int, int *)
_divide = _mod.divide
_divide.argtypes = (ctypes.c_int, ctypes.c_int, ctypes.POINTER(ctypes.c_int))
_divide.restype = ctypes.c_int
def divide(x, y):
rem = ctypes.c_int()
quot = _divide(x, y, rem)
return quot,rem.value
# void avg(double *, int n)
# Define a special type for the 'double *' argument
class DoubleArrayType:
def from_param(self, param):
typename = type(param).__name__
if hasattr(self, 'from_' + typename):
return getattr(self, 'from_' + typename)(param)
elif isinstance(param, ctypes.Array):
return param
else:
raise TypeError("Can't convert %s" % typename)
# Cast from array.array objects
def from_array(self, param):
if param.typecode != 'd':
raise TypeError('must be an array of doubles')
ptr, _ = param.buffer_info()
return ctypes.cast(ptr, ctypes.POINTER(ctypes.c_double))
# Cast from lists/tuples
def from_list(self, param):
val = ((ctypes.c_double)*len(param))(*param)
return val
from_tuple = from_list
# Cast from a numpy array
def from_ndarray(self, param):
return param.ctypes.data_as(ctypes.POINTER(ctypes.c_double))
DoubleArray = DoubleArrayType()
_avg = _mod.avg
_avg.argtypes = (DoubleArray, ctypes.c_int)
_avg.restype = ctypes.c_double
def avg(values):
return _avg(values, len(values))
# struct Point { }
class Point(ctypes.Structure):
_fields_ = [('x', ctypes.c_double),
('y', ctypes.c_double)]
# double distance(Point *, Point *)
distance = _mod.distance
distance.argtypes = (ctypes.POINTER(Point), ctypes.POINTER(Point))
distance.restype = ctypes.c_double
如果一切正常,你就可以加载并使用里面定义的C函数了。例如:
>>> import sample
>>> sample.gcd(35,42)
7
>>> sample.in_mandel(0,0,500)
1
>>> sample.in_mandel(2.0,1.0,500)
0
>>> sample.divide(42,8)
(5, 2)
>>> sample.avg([1,2,3])
2.0
>>> p1 = sample.Point(1,2)
>>> p2 = sample.Point(4,5)
>>> sample.distance(p1,p2)
4.242640687119285
>>>
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。