我创建了这个setup.py
编译一个libDIV.so
共享库并安装它。
from distutils.core import setup, Extension
libDIV = Extension(
'DIV',
sources = ['example.c']
)
setup (
name = 'divv',
version = '0.1',
description = 'DIVV, you want it',
ext_modules = [libDIV],
packages = [''],
package_data={'': ['libDIV.so']}
)
运行后python3 setup.py install
,共享库放置在 dist-packages 文件夹中,如下所示:
/usr/local/lib/python3.4/dist-packages/DIV.cpython-34m.so
在一个额外的文件中example.py
我想使用加载库ctypes.cdll.LoadLibrary
,使得example.py
可以将其功能包装在更优雅的、类型检查的 python 函数中。
import ctypes
lib = ctypes.cdll.LoadLibrary('DIV.so') # not sure what to do here
def divide_modulo(a, b):
div = ctypes.c_int(0)
rest = ctypes.c_int(0)
lib.divide_modulo(a, b, ctypes.byref(div), ctypes.byref(rest))
return (div.value, rest.value)
print(divide_modulo(11, 4))
class DynamicArray(ctypes.Structure):
_fields_ = [("n", ctypes.c_int), ("r", ctypes.POINTER(ctypes.c_int))]
但是我不确定如何传递创建的共享对象文件的正确文件名和位置。
我应该如何分发/配置 setup.py 来构建共享库和一些 python 代码来包装 c 功能的 c 文件库?
为了完整起见,这是 example.c:
#include <stdlib.h>
void divide_modulo(int a, int b, int *div, int *rest)
{
*div = a / b;
*rest = a % b;
}
typedef struct dynamic_array {
int n;
int *r;
} dynamic_array;
dynamic_array return_dynamic_array(int n)
{
dynamic_array r;
r.n = n;
r.r = (int *)malloc(sizeof(int) * n);
unsigned int i = 0;
for (; i < n; ++i)
r.r[i] = i;
return r;
}
EDIT:
目前我这样做是为了查找文件名:
import ctypes, numpy, site, os.path
from scipy.sparse import csr_matrix
so_file = next(
os.path.join(directory, filename)
for directory in site.getsitepackages()
for filename in os.listdir(directory)
if filename.startswith("DIV.") and filename.endswith(".so")
)
lib = ctypes.cdll.LoadLibrary(so_file)
但说实话,这确实有点臭。我不确定该文件将始终被调用DIV.something.so
反之亦然,其他文件不是这样命名的。