我在Windows 7(64位)下运行Python 3.3(Anaconda发行版)。我试图安装Weasyprint应用程序/库,它具有许多依赖性,包括CFFI,我必须从源代码进行编译,因为在二进制发行版中没有兼容的版本。
当我运行weasyprint时,它会在导入加载过程中阻塞,特别是当它调用CFFI以便为开罗加载GTK +库dll时。我得到的错误如下:
$ weasyprint
Traceback (most recent call last):
File "c:\anaconda\envs\py33\lib\site-packages\cffi-0.8-py3.3-win-amd64.egg\cffi\api.py", line 399, in _make_ffi_library
backendlib = backend.load_library(name, flags)
OSError: cannot load library libcairo-2.dll: error 0x7e
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Anaconda\envs\py33\Scripts\weasyprint-script.py", line 9, in <module>
load_entry_point('WeasyPrint==0.20', 'console_scripts', 'weasyprint')()
File "C:\Anaconda\envs\py33\lib\site-packages\pkg_resources.py", line 343, in load_entry_point
return get_distribution(dist).load_entry_point(group, name)
File "C:\Anaconda\envs\py33\lib\site-packages\pkg_resources.py", line 2355, in load_entry_point
return ep.load()
File "C:\Anaconda\envs\py33\lib\site-packages\pkg_resources.py", line 2061, in load
entry = __import__(self.module_name, globals(),globals(), ['__name__']) …Run Code Online (Sandbox Code Playgroud) 有一种方法用字典初始化结构:
fooData= {'y': 1, 'x': 2}
fooStruct = ffi.new("foo_t*", fooData)
fooBuffer = ffi.buffer(fooStruct)
Run Code Online (Sandbox Code Playgroud)
是否有一些准备好的功能来进行转换?
fooStruct = ffi.new("foo_t*")
(ffi.buffer(fooStruct))[:] = fooBuffer
fooData= convert_to_python( fooStruct[0] )
Run Code Online (Sandbox Code Playgroud)
我必须自己使用ffi.typeof("foo_t").字段吗?
到目前为止,我想出了这个代码:
def __convert_struct_field( s, fields ):
for field,fieldtype in fields:
if fieldtype.type.kind == 'primitive':
yield (field,getattr( s, field ))
else:
yield (field, convert_to_python( getattr( s, field ) ))
def convert_to_python(s):
type=ffi.typeof(s)
if type.kind == 'struct':
return dict(__convert_struct_field( s, type.fields ) )
elif type.kind == 'array':
if type.item.kind == 'primitive':
return [ s[i] for i in …Run Code Online (Sandbox Code Playgroud) 在开发过程中构建CFFI模块的最佳实践是什么?
现在我正在使用Makefile:
mylib/_ffi.so: my_lib/build_ffi.py
python $<
Run Code Online (Sandbox Code Playgroud)
然后测试我可以使用:
$ make && python test.py
Run Code Online (Sandbox Code Playgroud)
但这似乎不是最理想的.在开发过程中是否有更好的方法来构建CFFI模块?
我想编写使用的Python软件CFFI.CFFI本身抛出错误:
distutils.errors.DistutilsPlatformError: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++ Build Tools": http://landinghub.visualstudio.com/visual-cpp-build-tools
Run Code Online (Sandbox Code Playgroud)
该页面上有多个下载.我不想从Microsoft Visual C++ Build Tools安装数GB的数据.我安装CFFI工作的最低要求是多少?
我使用 cffi 模块来包装简单的 C 代码。问题是,我需要添加一个标志来使其编译(std=c99)。目前我有类似的东西:
from cffi import FFI
ffibuilder = FFI()
with open("test.c", 'r') as f:
ffibuilder.set_source("mymodule", f.read())
with open("test.h", 'r') as f:
ffibuilder.cdef(f.read())
if __name__ == "__main__":
ffibuilder.compile(verbose=True)
Run Code Online (Sandbox Code Playgroud)
问题是,cffi 自己调用 gcc,我想将 std=c99 添加到它调用 gcc 的标志中。我缺少任何参数吗?
(注意:我可以更改 gcc 命令本身或运行 cffi 自己使用的 gcc 命令,我想知道我是否缺少一些正确的方法来执行此操作)
使用用于Python的CFFI库,我试图将Python字符串哄骗到char *中,以便将其传递给接受char *的C函数。我似乎无法弄清楚什么是正确的咒语。
考虑以下示例:
>>> from cffi import FFI
>>> ffi = FFI()
>>> ffi.new("char[]", "bob")
Run Code Online (Sandbox Code Playgroud)
结果是:
TypeError: initializer for ctype 'char[]' must be a bytes or list or tuple, not str
Run Code Online (Sandbox Code Playgroud)
以下内容也不起作用:
>>> ffi.new("char*", "bob")
Run Code Online (Sandbox Code Playgroud)
它说:
TypeError: initializer for ctype 'char' must be a bytes of length 1, not str
Run Code Online (Sandbox Code Playgroud) 我想从 python 调用一些 c 函数来提高代码的性能。但我无法在网上找到当我使用 ctypes 库调用 C 函数时 GIL 是否被释放。举个简单的例子:
from ctypes import *
fun = cdll.LoadLibrary("libc.so.6")
fun.sleep.argtypes = [c_uint]
fun.sleep(c_uint(5))
Run Code Online (Sandbox Code Playgroud)
GIL 是否在调用期间被释放fun.sleep?
我有一个示例代码,该示例代码具有一个text()返回新分配的字符串的函数:
ffi_test = FFI()
ffi_test.set_source('_test', '''
char* test() { return strdup("hello world"); }
''')
ffi_test.cdef('''
char* test();
void free(void *);
''')
ffi_test.compile(verbose=True)
Run Code Online (Sandbox Code Playgroud)
这很好用:
In [1]: from _test import ffi, lib
In [2]: x = lib.test()
In [3]: ffi.string(x)
Out[3]: b'hello world'
In [4]: lib.free(x)
Run Code Online (Sandbox Code Playgroud)
但是,我在文档中找不到任何内容,是否我真的需要手动free()返回的字符串,如果CFFI在返回到Python代码后立即拥有该指针的所有权。
另外,如果我确实需要手动执行free()此操作,是否需要free()在cdef中公开它?CFFI是否为此提供了更好的方法?
我正在尝试使用PyPy和cffi将Python函数嵌入C中。我正在遵循PyPy文档中的本指南。
问题是,我发现的所有示例都在ints上操作,并且我的函数采用字符串并返回字符串。我似乎无法弄清楚如何将此函数嵌入C中,因为C似乎并没有真正的字符串,而是使用char数组。
这是我尝试过的:
# interface.py
import cffi
ffi = cffi.FFI()
ffi.cdef('''
struct API {
char (*generate_cool_page)(char url[]);
};
''')
...
@ffi.callback("char[] (char[])")
def generate_cool_page(url):
# do some processing with BS4
return str(soup)
def fill_api(ptr):
global api
api = ffi.cast("struct API*", ptr)
api.generate_cool_page = generate_cool_page
Run Code Online (Sandbox Code Playgroud)
-
// c_tests.c
#include "PyPy.h"
#include <stdio.h>
#include <stdlib.h>
struct API {
char (*generate_cool_page)(char url[]);
};
struct API api; /* global var */
int initialize_api(void)
{
static char source[] =
"import sys; sys.path.insert(0, '.'); …Run Code Online (Sandbox Code Playgroud) 我将reqwestrust 的一些函数包装到req.lib文件中,并使用cffi. 然而reqwest::blocking::Client强迫我在 python 中使用多线程。我发现reqwest可以在 Rust 中以异步模式调用。我想知道有没有办法实现req.lib异步?即使是半异步对我来说也可以。
例如,当前存根签名是:
#[no_mangle]
pub extern "C" fn urlopen(url: *const c_char) -> *mut c_char
Run Code Online (Sandbox Code Playgroud)
我可以写一些类似的东西:
#[no_mangle]
pub extern "C" fn urlopen(url: *const c_char) -> u64 // return request unique id
#[no_mangle]
pub extern "C" fn is_finished(req_id: u64) -> bool // whether given request is done
#[no_mangle]
pub extern "C" fn fetch_result(req_id: u64) -> *mut c_char // fetch response
Run Code Online (Sandbox Code Playgroud)
因此cffi调用不再锁定主线程。我可以使用单线程来调用多个请求。欢迎任何建议或最佳实践。
我试图用来python-cffi包装C代码.以下example_build.py显示了包装lstat()调用的尝试:
import cffi
ffi = cffi.FFI()
ffi.set_source("_cstat",
"""
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
""",
libraries=[])
ffi.cdef("""
struct stat {
mode_t st_mode;
off_t st_size;
...;
};
int lstat(const char *path, struct stat *buf);
""")
if __name__ == '__main__':
ffi.compile()
Run Code Online (Sandbox Code Playgroud)
当编译时python example_build.py会抱怨解析错误mode_t st_mode.
cffi.api.CDefError: cannot parse "mode_t st_mode;"
:4:13: before: mode_t
Run Code Online (Sandbox Code Playgroud)
但手册中给出的类似示例没有任何问题.我错过了什么?TIA.