我正在研究rust-efl项目,该项目是对Enlightenment EFL C库的绑定。
有一个函数需要两个C风格的枚举来配置库。我想根据第一个参数的值将第二个参数限制为某个枚举。
我将使用此示例的实际代码,因为它使用它更容易理解用例。
示例电话:
elementary::policy_set(ElmPolicy::Quit, ElmPolicyQuit::LastWindowClosed as i32);
Library Rust代码:
#[repr(C)]
pub enum ElmPolicy {
/// under which circumstances the application should quit automatically. See ElmPolicyQuit
Quit = 0,
/// defines elm_exit() behaviour. See ElmPolicyExit
Exit,
/// defines how throttling should work. See ElmPolicyThrottle
Throttle
}
#[repr(C)]
pub enum ElmPolicyQuit {
/// never quit the application automatically
None = 0,
/// quit when the application's last window is closed
LastWindowClosed,
/// quit when the application's last window is hidden
LastWindowHidden
}
pub fn policy_set(policy: ElmPolicy, value: i32) {
ElmPolicyQuit
的每个值都有类似于ElmPolicy
的枚举。 policy_set
的第二个参数应该是相应的枚举类型。
我想修改policy_set
,以便调用者不必通过定义i32
的类型将值转换为value
。理想情况下,我希望Rust检查第二个参数是否为给定policy
参数的正确类型。
实施尝试
我是Rust的新手,所以这可能会有所不同,但这是我目前的尝试:
pub fn policy_set<P: ElmPolicy, V: ElmPolicyValue<P>>(policy: P, value: V) {
unsafe { elm_policy_set(policy as c_int, value as c_int) }
}
trait ElmPolicyValue<P> {}
impl ElmPolicyValue<ElmPolicy::Quit> for ElmPolicyQuit {}
但是我收到了这个错误:
src / elementary.rs:246:22:246:31错误:
ElmPolicy
不是特质 [E0404] src / elementary.rs:246 pub fn policy_set&gt;(政策:P,价值:V){
(箭头指向第一个参数的类型)
我为ElmPolicy制作了一个虚拟特征,但后来我得到了
src / elementary.rs:111:21:111:36错误:找到值
elementary::ElmPolicy::Quit
用作类型[E0248] src / elementary.rs:111 impl ElmPolicyValue for ElmPolicyQuit {}
所以看起来我不能以这种方式使用enums作为泛型类型。 实现这个的正确方法是什么?
我想我不需要这些实际上是枚举。我只需要将值转换为与EFL库的C enum对应的c_int
。
另外,我想到了一个论点。
elementary::policy_set(elementary::Policy::Quit::LastWindowClosed);
但是,尽管我找到了文档,但嵌套的类似C的枚举似乎不起作用,我不确定将#[repr(C)]
用于嵌套枚举。
答案 0 :(得分:2)
我不会试图一举解决这两个问题。创建一个直接的Rust绑定到C库,它按原样公开API(*-sys
package)。然后在顶部提供更具惯用性的Rust API:
enum ElmPolicy {
Quit(QuitDetail),
Exit(ExitDetail),
Throttle(ThrottleDetail),
}
enum QuitDetail {
None,
LastWindowClosed,
LastWindowHidden,
}
然后,您可以在ElmPolicy
上创建生成C枚举元组的方法,或者根据需要直接调用相应的C函数。
请注意,可能会有一些样板文件,因为*-sys
包中的枚举将反映惯用API中的枚举,您需要在它们之间进行转换。宏可能有助于减少这种情况。
答案 1 :(得分:1)
以下是我将如何做到的:我将其定义为具有关联类型的特征,而不是将<?php
header('Content-Type: text/html; charset=utf-8');
header('Location:http://localhost/php/getjs/index.php?start=main');
if (isset($_GET["start"])){
$main=$_GET["start"];
if ($main==="main"){
include 'file.php';
}
}
if (isset($_GET["start"])){
$main=$_GET["start"];
if ($main==="list"){
include 'file2.php';
}
}
?>
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
<input type="button" id="list" value="Load File2">
<script>
$("#list").click(function(){
window.location.href="http://localhost/php/getjs/index.php?start=list";
});
</script>
定义为ElmPolicy
,该特征指定了策略值的参数类型。每个策略都将定义一个实现enum
的单元结构。
ElmPolicy
您可以根据需要向pub trait ElmPolicy {
type Value;
}
pub struct ElmPolicyQuit;
impl ElmPolicy for ElmPolicyQuit {
type Value = ElmPolicyQuitValue;
}
// TODO: ElmPolicyExit and ElmPolicyThrottle
#[repr(C)]
pub enum ElmPolicyQuitValue {
/// never quit the application automatically
None = 0,
/// quit when the application's last window is closed
LastWindowClosed,
/// quit when the application's last window is hidden
LastWindowHidden
}
pub fn policy_set<P: ElmPolicy>(policy: P, value: P::Value) {
// TODO
}
fn main() {
policy_set(ElmPolicyQuit, ElmPolicyQuitValue::LastWindowClosed);
//policy_set(ElmPolicyQuit, ElmPolicyQuitValue::LastWindowClosed as i32); // does not compile
}
添加方法或超级作品,并向ElmPolicy
添加约束。例如,您可能希望在ElmPolicy::Value
上添加Into<i32>
作为约束,以便在ElmPolicy::Value
中使用value.into()
将值转换为policy_set