使用ctypes模块我可以轻松地将POINTER(c_char)或c_char_p类型导入到python中,但这些都没有提供一种方法来结束包含零值字节的python字符串.
c_char_p为零终止,表示来自C的char*数组在第一个零值处终止.
POINTER(c_char)是导入可以具有0值的二进制数据的推荐方法,但似乎没有办法直接将其转换为python字符串.
我可以做这个:
pixels = clibblah.get_pixels()
a = ""
for i in range(0, clibblah.get_pixel_length()):
a += pixels[i]
Run Code Online (Sandbox Code Playgroud)
...但是这1)似乎并不是非常pythony,并且2)永远需要(在我的mac上转换640x480像素数据块大约需要2秒).
我已经在堆栈溢出时看到了很多关于此问题的问题,但是如果我能看到一个不是"人们为什么需要这样做?或者"c_char_p会做你想要的"(它没有,正如我上面所描述的那样).
我见过的唯一可信的建议是使用c api PyString_FromStringAndSize,如下所示:http: //www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/version/Doc/FAQ.html
不能真正看到它有多大帮助,因为afaik是一个cython功能,而不是python功能.
对于感兴趣的人,我需要这样做的原因是我正在使用panda3d和kinect,而kinect c api提供了一组unsigned char*值,panda3d api提供了一个setPixels()调用,只需要一个python字符串作为参数.
我天真地尝试这样做:
struct Foo<'a, S: Send, T:Send> {
next_:Box<Fn<(&'a mut S,), Option<T>> + Send>,
state:S
}
impl<'a, S: Send, T: Send> Iterator<T> for Foo<'a, S, T> {
fn next(&mut self) -> Option<T> {
return self.next_.call((&mut self.state,));
}
}
Run Code Online (Sandbox Code Playgroud)
要创建迭代器,我可以使用闭包轻松发送到任务。
然而,它会产生可怕的生命周期不匹配错误:
<anon>:8:33: 8:48 error: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
<anon>:8 return self.next_.call((&mut self.state,));
^~~~~~~~~~~~~~~
<anon>:7:5: 9:6 help: consider using an explicit lifetime parameter as shown: fn next(&'a mut self) -> Option<T>
<anon>:7 fn next(&mut self) …Run Code Online (Sandbox Code Playgroud) 我一直试图在https://github.com/shadowmint/rust-dl-example上使用 cmake 和 rust 来获得基本的概念证明并运行,但无济于事。
基本思想是构建一个 DLL,然后像这样加载符号:
let dl = DynamicLibrary::open(Some(dl_path));
match dl {
Ok(dll) => {
// Try loading symbols. Note that because of the api we can't
// directly pass T as fn(c_int) -> c_int, because the return is
// a pointer, not a pointer to a pointer.
unsafe{
rtn.foo = match dll.symbol::<c_void>("foo") {
Ok(symbol) => Some(transmute(symbol)),
Err(_) => None
};
rtn.bar = match dll.symbol::<c_void>("bar") {
Ok(symbol) => Some(transmute(symbol)),
Err(_) => None
};
trace!("Read: {}", dll.symbol::<c_void>("foo")); …Run Code Online (Sandbox Code Playgroud) 关于静态和动态调度的生锈书部分中有关于此主题的一些基本背景,但tldr基本上是:在特征引用上调用方法和其他一些不同的情况(函数指针等)导致动态而不是静态调度.
所以,问题:
在应用优化后,实际的运行时成本是多少?
例如,想象一下这组结构和特征:
struct Buffer;
struct TmpBuffer;
struct TmpMutBuffer;
impl BufferType for Buffer { ... }
impl BufferType for BufferTmp { ... }
impl BufferType for BufferTmpMut { ... }
impl Buffer2D for BufferType { ... }
impl Buffer2DExt for Buffer2D { ... }
Run Code Online (Sandbox Code Playgroud)
特别注意,这里的特征是在特征本身上实现的.
在struct reference上从Buffer2DExt调用方法的动态调度的调用成本是多少?
最近有一个关于解除引用规则的问题这是什么是Rust的确切自动解除引用规则?; 这些规则是在编译时还是运行时应用的?
我在 Rust 代码中看到了一些这种模式的实例:
trait Task {
fn run(self: Box<Self>) -> i32;
}
struct SomeTask {}
impl Task for SomeTask {
fn run(self: Box<SomeTask>) -> i32 {
1
}
}
fn main() {
let task: Box<Task> = Box::new(SomeTask {});
task.run();
}
Run Code Online (Sandbox Code Playgroud)
现在......我理解这段代码的意图,它是一个实现自消费模式的特征:
fn foo(self);
Run Code Online (Sandbox Code Playgroud)
好吧……但是什么?
您可以将 self 限定为Self? 除了Self, &Self,&mut Self和, 显然还有其他东西 self 可以Box<Self>吗?
为什么存在此功能,因为您已经可以在没有它的情况下执行此操作:
trait Runnable {
fn run(self) -> i32;
}
trait Task {
fn value(&self) -> i32;
}
struct …Run Code Online (Sandbox Code Playgroud) 在 Windows 上,Path::canonicalize()以以下格式返回路径:
\\\\?\\C:\\projects\\3rdparty\\rust...
Run Code Online (Sandbox Code Playgroud)
这是因为它是正确的规范路径,并且允许在 Windows 上使用“长”路径(请参阅为什么我的规范化路径以 \\?\ 为前缀)。
然而,这并不是一条人性化的道路,人们并不理解。
出于显示和记录目的,我如何以独立于通用平台的方式轻松删除此前缀?
Path::components将返回一个组件\\?\C:作为第一个组件...
我应该将其转换为 a&str并使用正则表达式吗?是否有其他更符合人体工程学的方法来删除前缀,例如某种带有Display实现可以自动做正确的事情?
我的要求具体是:
X:\\...在 Windows 上正确显示规范路径。例子:
use std::path::{Path, PathBuf};
fn simple_path<P: AsRef<Path>>(p: P) -> String {
String::from(p.as_ref().to_str().unwrap()) // <-- ?? What to do here?
}
pub fn main() {
let path = PathBuf::from("C:\temp").canonicalize().unwrap();
let display_path = simple_path(path);
println!("Output: {}", display_path);
}
Run Code Online (Sandbox Code Playgroud) 我讨厌bash'历史'命令.它永远不会找到我想要的历史项目.有时我可以通过'历史|获得我想要的东西 grep XXX',但往往是历史太长(400次点击!yay)或太短(没有点击.嘘).
我心想,为什么我不写一个小小的'历史帮手'命令让我基本上'明星'特定的历史项目,并使它们总是出现在我的历史中,同时包括全球明星列表和cwd特定明星列表.
听起来很棒.所以我天真地尝试通过这样做来阅读历史:
system("history > blah")
FILE *fp = fopen("blah", "r")
Run Code Online (Sandbox Code Playgroud)
哦,那没用.啊,我明白了,system()命令在它自己的上下文中运行,无法访问bash历史记录.Drats.好的,所以我会尝试阅读〜/ .bash_history
ba baaa~不.这只是历史记录,直到最后一次调用a)历史-w,或b)调用退出shell.
所以,问题:我如何以编程方式访问C中的当前bash历史记录?
(注意:不,不是〜/ .bash_history中的内容,当前历史记录,当您从提示中键入"历史记录"时看到的确切输出;另外,为什么C要问?为什么不...但是真的,因为我已经有一个方便的ncurses包装我打算用来让我在正常终端上进行花式自动完成和子选择历史搜索...)
编辑:请,如果你有一些有用的东西可以贡献,我很高兴听到它,但我有点厌恶像"你应该阅读bash历史手册页"这样的评论.
我读过它们.有什么可以让我"明星"历史项,并将它一直都在我的历史打开了,并没有什么可以让我保持每个目录历史文脉.这些是历史不支持的事情.我很欣赏这个.这就是为什么我想写一个帮助函数,为了我的特定目的.如果你有一个评论,"也许你应该阅读更多的历史手册页",请把它拿进来,不要回应; 它并没有真正解决我的问题.:)
我一直在使用自定义构建作为virtualenv的替代品一段时间了,而且它很棒.它需要更长的时间来构建,但实际上它可以工作,并且它永远不会搞砸.
部分内容在一个简单的python包装器中,它将一些特定的文件夹添加到库路径中,我发现它非常有用.它的代码是微不足道的:
#include <stdio.h>
#include <n/text/StringUtils.h>
#include <Python.h>
int main(int argc, char *argv[]) {
/* Setup */
Py_SetProgramName(argv[0]);
Py_Initialize();
PySys_SetArgv(argc, argv);
/* Add local path */
PyObject *sys = PyImport_ImportModule("sys");
PyObject *path = PyObject_GetAttrString(sys, "path");
/* Custom path */
char *cwd = nrealpath(argv[0]);
char *libdir = nstrpath(cwd, "python_lib", NULL);
PyList_Append(path, PyString_FromString(libdir));
free(cwd);
free(libdir);
/* Run the 'main' module */
int rtn = Py_Main(argc, argv); // <-- Notice the command line arguments.
Py_Finalize();
return rtn;
}
Run Code Online (Sandbox Code Playgroud)
那么,转向python3是对的吗?所以...
我尽职尽责地用PyByte_FromString()替换了对PyString_FromString()的调用并尝试重新编译,但它引发了错误:
/Users/doug/env/src/main.c:8:21: error: incompatible …Run Code Online (Sandbox Code Playgroud) 我发现这是允许方法重载的特别有用的模式:
struct Foo {
value:uint
}
trait HasUIntValue {
fn as_uint(self) -> uint;
}
impl Foo {
fn add<T:HasUIntValue>(&mut self, value:T) {
self.value += value.as_uint();
}
}
impl HasUIntValue for int {
fn as_uint(self) -> uint {
return self as uint;
}
}
impl HasUIntValue for f64 {
fn as_uint(self) -> uint {
return self as uint;
}
}
#[test]
fn test_add_with_int()
{
let mut x = Foo { value: 10 };
x.add(10i);
assert!(x.value == 20);
}
#[test]
fn test_add_with_float() …Run Code Online (Sandbox Code Playgroud) 现在等一下,然后再将其标记为重复,因为这是一个非常具体的问题.
我不是在问你是否可以使用另一种使用NDK绑定的语言编写应用程序; 我想知道的是:
根据我的理解,(1)的答案是因为android基本上是一个Linux系统,这是通过系统调用完成的.也就是说,在某种程度上,davlik/art VM 必须通过C API与C Linux内核进行交互.
所以,当然这将是一个痛苦的经历,但从技术上讲,有什么理由为什么不用纯粹在C中编写应用程序,而根本不使用android运行时?
(注意:不是没有运行时;显然必须存在运行时才能执行各种操作,例如设备初始化;但是一个独立的二进制文件,它不与运行时交互).
(我可以想到为什么会出现这种情况的几个原因,特别是需要对各种硬件进行独占硬件访问的运行时,但我找不到任何关于它的具体文档)