当前位置: 首页 > news >正文

dede手机网站标签徐州关键词优化平台

dede手机网站标签,徐州关键词优化平台,centos 网站开发工具,WordPress网站很多垃圾注册本示例演示了一个调用blobstore服务的C客户端的Rust应用程序。事实上,我们会看到两个方向的调用:Rust到C以及C到Rust。对于您自己的用例,您可能只需要其中一个方向。 示例中涉及的所有代码都显示在此页面上,但它也以可运行的形式提…

本示例演示了一个调用blobstore服务的C++客户端的Rust应用程序。事实上,我们会看到两个方向的调用:Rust到C++以及C++到Rust。对于您自己的用例,您可能只需要其中一个方向。
示例中涉及的所有代码都显示在此页面上,但它也以可运行的形式提供在demo目录中https://github.com/dtolnay/cxx.要直接尝试,请从该目录运行cargo run。
共享结构、不透明类型和函数已经在上一篇文章中叙述,不清楚的可以先去看一下。

一、创建项目

我们在命令行中创建一个空白的Cargo项目:
cargo new cxx-demo
编辑Cargo.toml文件,添加对cxx的依赖:

[dependencies]
cxx = "1.0"

二、定义语言边界

CXX依赖于对每种语言向另一种语言公开的函数签名的描述。您可以在Rust模块中使用extern块提供此描述,该模块用#[cxx::bridge]属性宏注释。
我们在项目的main.rs文件的顶部添加该内容:

#[cxx::bridge]
mod ffi {
}

该内容将是FFI边界双方需要达成一致的所有内容。

三、从Rust调用C++函数

让我们获取一个C++blobstore客户端的实例,一个在C++中定义的类blobstore client。
我们将把BlobstreClient视为CXX分类中的不透明类型,这样Rust就不需要对其实现做出任何假设,甚至不需要对它的大小或对齐方式做出任何假设。一般来说,C++类型可能有一个与Rust的move语义不兼容的move构造函数,或者可能包含Rust的借用系统无法建模的内部引用。尽管有其他选择,但在FFI边界上不关心任何此类事情的最简单方法是将其视为不透明,不需要了解类型。
不透明类型只能在间接后面操作,如引用&、Rust Box或UniquePtr(std::unique_ptr的Rust绑定)。我们将添加一个函数,通过该函数,C++可以向Rust返回std::unique_ptr。

// src/main.rs#[cxx::bridge]
mod ffi {unsafe extern "C++" {include!("cxx-demo/include/blobstore.h");type BlobstoreClient;fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;}
}fn main() {let client = ffi::new_blobstore_client();
}

即使CXX自动执行静态断言,确保签名与C++中声明的完全匹配,我们仍然需要确保键入的签名是准确的。比如new_blobstore_client函数如果会发生意外(如内存错误)必须用unsafe标记。这次是在一个安全的extern“C++”块中,因为程序员不再需要对签名进行任何安全声明。

四、添加C++代码

在CXX与Cargo的集成中,默认情况下,所有#include路径都以单元包(crate)名称开头。这就是为什么我们看到 include!(“cxx-demowj/include/blobstore.h”) ——我们将把C++头文件放在Rust单元包内的相对路径include/blostore.h处。如果根据Cargo.toml中的name字段,你的crate的名称不是cxx-demo,那么在本教程中,你需要在所有地方使用这个名称来代替cxx-demo。

// include/blobstore.h#pragma once
#include <memory>class BlobstoreClient {
public:BlobstoreClient();
};std::unique_ptr<BlobstoreClient> new_blobstore_client();// src/blobstore.cc#include "cxx-demo/include/blobstore.h"BlobstoreClient::BlobstoreClient() {}std::unique_ptr<BlobstoreClient> new_blobstore_client() {return std::unique_ptr<BlobstoreClient>(new BlobstoreClient());
}

使用std::make_unique也可以,只要你将std(“c++14”)传递给c++编译器,如稍后所述。
include/和src/中的位置并不重要;只要在整个项目中使用正确的路径,就可以将C++代码放置在单元包中的任何其他位置。
请注意,CXX不会查看这些文件中的任何一个。你可以自由地在这里放任意的C++代码, #include你自主的库等等。CXX库所做的就是针对您在头文件中提供的内容发出静态断言。

五、用Cargo编译C++代码

Cargo有一个适合编译非Rust代码的构建脚本功能。
我们需要在Cargo.toml中引入对CXX的C++代码生成器的新的构建时依赖:

# Cargo.toml[dependencies]
cxx = "1.0"[build-dependencies]
cxx-build = "1.0"

然后在Cargo.toml旁边添加一个build.rs构建脚本,以运行cxx构建代码生成器和C++编译器。相关参数是包含cxx::bridge语言边界定义的Rust源文件的路径,以及在Rust crate构建过程中要编译的任何其他C++源文件的道路。

// build.rsfn main() {cxx_build::bridge("src/main.rs").file("src/blobstore.cc").compile("cxx-demo");println!("cargo:rerun-if-changed=src/main.rs");println!("cargo:rerun-if-changed=src/blobstore.cc");println!("cargo:rerun-if-changed=include/blobstore.h");
}

他的build.rs也是您设置C++编译器标志的地方,例如,如果您想从C++14访问std::make_unique。

 cxx_build::bridge("src/main.rs").file("src/blobstore.cc").std("c++14").compile("cxx-demo");

尽管还没有做任何有用的事情,该项目现在应该能够成功构建和运行。命令行输入命令如下:

<cxx-demo路径提示符>  cargo runCompiling cxx-demo v0.1.0Finished dev [unoptimized + debuginfo] target(s) in 0.34sRunning `target/debug/cxx-demo`<cxx-demo路径提示符>

六、从C++调用Rust函数

我们的C++blobstore支持不连续缓冲区上传的put操作。例如,我们可能正在上传一个循环缓冲区的快照,该缓冲区往往由2个部分组成,或者由于其他原因(如绳索数据结构)而分散在内存中的文件片段。
我们将通过在连续的借用块上传递迭代器来表达这一点。这与广泛使用的字节箱的Buf特性的API非常相似。在put过程中,我们将让C++回调到Rust中,以获取上传的连续块(所有块都没有在语言边界上进行复制或分配)。实际上,C++客户端可能包含一些复杂的块批处理或并行上传,所有这些都与之相关。

// src/main.rs#[cxx::bridge]
mod ffi {extern "Rust" {type MultiBuf;fn next_chunk(buf: &mut MultiBuf) -> &[u8];}unsafe extern "C++" {include!("cxx-demo/include/blobstore.h");type BlobstoreClient;fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;fn put(&self, parts: &mut MultiBuf) -> u64;}
}

任何具有self参数的签名(等同C++的this)都被认为是一个方法/非静态成员函数。如果周围的extern块中只有一个类型,则它将是该类型的方法。如果有多个类型,您可以通过在参数列表中编写self:&BlostreClient来区分方法属于哪一个。
像往常一样,现在我们需要提供extern“Rust”块声明的所有内容的Rust定义,以及extern“C++”块宣布的新签名的C++定义。

// src/main.rs// An iterator over contiguous chunks of a discontiguous file object. Toy
// implementation uses a Vec<Vec<u8>> but in reality this might be iterating
// over some more complex Rust data structure like a rope, or maybe loading
// chunks lazily from somewhere.
pub struct MultiBuf {chunks: Vec<Vec<u8>>,pos: usize,
}pub fn next_chunk(buf: &mut MultiBuf) -> &[u8] {let next = buf.chunks.get(buf.pos);buf.pos += 1;next.map_or(&[], Vec::as_slice)
}
// include/blobstore.hstruct MultiBuf;class BlobstoreClient {
public:BlobstoreClient();uint64_t put(MultiBuf &buf) const;
};

在blobstre.cc中,我们可以调用Rust next_chunk函数,该函数通过CXX代码生成器生成的头部文件main.rs.h暴露给C++。在CXX的Cargo集成中,这个生成的头文件有一个包含crate名称、crate中Rust源文件的相对路径和.rs.h扩展名的路径。

// src/blobstore.cc#include "cxx-demo/include/blobstore.h"
#include "cxx-demo/src/main.rs.h"
#include <functional>
#include <string>// Upload a new blob and return a blobid that serves as a handle to the blob.
uint64_t BlobstoreClient::put(MultiBuf &buf) const {// Traverse the caller's chunk iterator.std::string contents;while (true) {auto chunk = next_chunk(buf);if (chunk.size() == 0) {break;}contents.append(reinterpret_cast<const char *>(chunk.data()), chunk.size());}// Pretend we did something useful to persist the data.auto blobid = std::hash<std::string>{}(contents);return blobid;
}

现在可以使用了

// src/main.rsfn main() {let client = ffi::new_blobstore_client();// Upload a blob.let chunks = vec![b"fearless".to_vec(), b"concurrency".to_vec()];let mut buf = MultiBuf { chunks, pos: 0 };let blobid = client.put(&mut buf);println!("blobid = {}", blobid);
}

运行信息如下:

cxx-demo$  cargo runCompiling cxx-demo v0.1.0Finished dev [unoptimized + debuginfo] target(s) in 0.41sRunning `target/debug/cxx-demo`blobid = 9851996977040795552

七、插曲:产生了什么?

对于好奇的人来说,很容易了解CXX为使这些函数调用工作所做的幕后工作。在CXX的正常使用过程中,您不需要这样做,但就本教程而言,这可能具有教育意义。
CXX包含两个代码生成器:一个Rust生成器(即CXX::bridge属性过程宏)和一个C++生成器。
Rust生成的代码
通过cargo-expand可以最容易地查看程序宏的输出。然后运行cargo expand ::ffi宏展开mod ffi模块。

cxx-demo$  cargo install cargo-expand 
cxx-demo$  cargo expand ::ffi

您将看到一些非常令人不快的代码,涉及#[repr(C)]、#[repr©], #[link_name] 和 #[export_name].。

八、C++生成的代码

为了调试方便,cxx_build将所有生成的C++代码链接到Cargo在target/cxxbridge/下的目标目录中。

cxx-demo$  exa -T target/cxxbridge/
target/cxxbridge
├── cxx-demo
│  └── src
│     ├── main.rs.cc -> ../../../debug/build/cxx-demo-11c6f678ce5c3437/out/cxxbridge/sources/cxx-demo/src/main.rs.cc
│     └── main.rs.h -> ../../../debug/build/cxx-demo-11c6f678ce5c3437/out/cxxbridge/include/cxx-demo/src/main.rs.h
└── rust└── cxx.h -> ~/.cargo/registry/src/github.com-1ecc6299db9ec823/cxx-1.0.0/include/cxx.h

在这些文件中,您将看到语言边界中存在的任何CXX Rust类型的声明或模板(如Rust::Slicefor&[T])以及与extern函数对应的extern“C”签名。
如果CXX C++代码生成器更适合您的工作流程,它也可以作为一个独立的可执行文件提供,将生成的代码输出到stdout。

cxx-demo$  cargo install cxxbridge-cmd
cxx-demo$  cxxbridge src/main.rs

九、共享数据结构

到目前为止,上述两个方向的调用只使用了不透明类型,而不是共享结构。
共享结构是数据结构,其完整定义对两种语言都是可见的,从而可以通过值跨语言传递它们。共享结构转换为C++聚合初始化兼容结构,与Rust结构的布局完全匹配。
作为此演示的最后一步,我们将使用共享结构体BlobMetadata在Rust应用程序和C++blobstore客户端之间传递有关blob的元数据。

// src/main.rs#[cxx::bridge]
mod ffi {struct BlobMetadata {size: usize,tags: Vec<String>,}extern "Rust" {// ...}unsafe extern "C++" {// ...fn tag(&self, blobid: u64, tag: &str);fn metadata(&self, blobid: u64) -> BlobMetadata;}
}fn main() {let client = ffi::new_blobstore_client();// Upload a blob.let chunks = vec![b"fearless".to_vec(), b"concurrency".to_vec()];let mut buf = MultiBuf { chunks, pos: 0 };let blobid = client.put(&mut buf);println!("blobid = {}", blobid);// Add a tag.client.tag(blobid, "rust");// Read back the tags.let metadata = client.metadata(blobid);println!("tags = {:?}", metadata.tags);
}
// include/blobstore.h#pragma once
#include "rust/cxx.h"struct MultiBuf;
struct BlobMetadata;class BlobstoreClient {
public:BlobstoreClient();uint64_t put(MultiBuf &buf) const;void tag(uint64_t blobid, rust::Str tag) const;BlobMetadata metadata(uint64_t blobid) const;private:class impl;std::shared_ptr<impl> impl;
};// src/blobstore.cc#include "cxx-demo/include/blobstore.h"
#include "cxx-demo/src/main.rs.h"
#include <algorithm>
#include <functional>
#include <set>
#include <string>
#include <unordered_map>// Toy implementation of an in-memory blobstore.
//
// In reality the implementation of BlobstoreClient could be a large
// complex C++ library.
class BlobstoreClient::impl {friend BlobstoreClient;using Blob = struct {std::string data;std::set<std::string> tags;};std::unordered_map<uint64_t, Blob> blobs;
};BlobstoreClient::BlobstoreClient() : impl(new class BlobstoreClient::impl) {}// Add tag to an existing blob.
void BlobstoreClient::tag(uint64_t blobid, rust::Str tag) const {impl->blobs[blobid].tags.emplace(tag);
}// Retrieve metadata about a blob.
BlobMetadata BlobstoreClient::metadata(uint64_t blobid) const {BlobMetadata metadata{};auto blob = impl->blobs.find(blobid);if (blob != impl->blobs.end()) {metadata.size = blob->second.data.size();std::for_each(blob->second.tags.cbegin(), blob->second.tags.cend(),[&](auto &t) { metadata.tags.emplace_back(t); });}return metadata;
}

运行命令:

cxx-demo$  cargo runRunning `target/debug/cxx-demo`blobid = 9851996977040795552
tags = ["rust"]

现在您已经看到了本教程中涉及的所有代码。它可以在演示目录中以可运行的形式一起使用https://github.com/dtolnay/cxx.您可以直接运行它,而无需从该目录运行cargo run来完成上述步骤。

十、结束语

CXX的主要贡献是它为你提供了Rust与C++的互操作性,在这种互操作性中,你编写的所有Rust端代码看起来都像是在写普通的Rust,而C++端看起来也像是在编写普通的C++。
在文中,您已经看到,所涉及的代码都不像C,也不像通常危险的“FFI胶水”,容易发生泄漏或内存安全缺陷。
由不透明类型、共享类型和关键标准库类型绑定组成的表达系统使API能够在语言边界上进行设计,从而获取接口的正确所有权和借用契约。
CXX发挥了Rust类型系统和C++类型系统的优势以及程序员的直觉。一个在没有Rust背景的C++端或没有C++背景的Rust端工作的人,将能够运用他们对语言开发的所有常见直觉和最佳实践来维护正确的FFI。


文章转载自:
http://locutorium.rzgp.cn
http://vaalhaai.rzgp.cn
http://substernal.rzgp.cn
http://embitter.rzgp.cn
http://halomethane.rzgp.cn
http://rotatable.rzgp.cn
http://sicanian.rzgp.cn
http://nalorphine.rzgp.cn
http://reverse.rzgp.cn
http://nepal.rzgp.cn
http://casse.rzgp.cn
http://condolent.rzgp.cn
http://maori.rzgp.cn
http://dissipated.rzgp.cn
http://metatherian.rzgp.cn
http://clanship.rzgp.cn
http://onchocerciasis.rzgp.cn
http://barbet.rzgp.cn
http://riffraff.rzgp.cn
http://frizzle.rzgp.cn
http://chicken.rzgp.cn
http://postirradiation.rzgp.cn
http://remaster.rzgp.cn
http://reemphasis.rzgp.cn
http://motorise.rzgp.cn
http://biface.rzgp.cn
http://stickman.rzgp.cn
http://surpassingly.rzgp.cn
http://francophile.rzgp.cn
http://nationalistic.rzgp.cn
http://rudder.rzgp.cn
http://rosyfingered.rzgp.cn
http://polyparium.rzgp.cn
http://handling.rzgp.cn
http://rosewood.rzgp.cn
http://pericardiocentesis.rzgp.cn
http://aieee.rzgp.cn
http://solfatara.rzgp.cn
http://forepaw.rzgp.cn
http://ptolemaism.rzgp.cn
http://metaphyte.rzgp.cn
http://incompliancy.rzgp.cn
http://ramee.rzgp.cn
http://asceticism.rzgp.cn
http://flowerless.rzgp.cn
http://decampment.rzgp.cn
http://salpingectomy.rzgp.cn
http://eunomic.rzgp.cn
http://interpose.rzgp.cn
http://diatonicism.rzgp.cn
http://chromatolytic.rzgp.cn
http://tortoise.rzgp.cn
http://resplend.rzgp.cn
http://magnisonant.rzgp.cn
http://moralize.rzgp.cn
http://chekiang.rzgp.cn
http://sericite.rzgp.cn
http://aero.rzgp.cn
http://soldierlike.rzgp.cn
http://streptothricin.rzgp.cn
http://shoe.rzgp.cn
http://eaten.rzgp.cn
http://seraskier.rzgp.cn
http://orchestic.rzgp.cn
http://decastylos.rzgp.cn
http://intermodulation.rzgp.cn
http://aflare.rzgp.cn
http://speculum.rzgp.cn
http://poussette.rzgp.cn
http://heterogeneous.rzgp.cn
http://basketballer.rzgp.cn
http://peculiarly.rzgp.cn
http://imperiality.rzgp.cn
http://intelligently.rzgp.cn
http://run.rzgp.cn
http://attach.rzgp.cn
http://dupe.rzgp.cn
http://bali.rzgp.cn
http://suez.rzgp.cn
http://rostellate.rzgp.cn
http://bartizan.rzgp.cn
http://biosynthesize.rzgp.cn
http://knacker.rzgp.cn
http://avellan.rzgp.cn
http://rustler.rzgp.cn
http://kidney.rzgp.cn
http://crosslet.rzgp.cn
http://xerophil.rzgp.cn
http://logocentric.rzgp.cn
http://rehearsal.rzgp.cn
http://unweeded.rzgp.cn
http://jinan.rzgp.cn
http://tailwagging.rzgp.cn
http://veld.rzgp.cn
http://rhipidistian.rzgp.cn
http://monochrome.rzgp.cn
http://cacographer.rzgp.cn
http://unrelentingly.rzgp.cn
http://parc.rzgp.cn
http://topee.rzgp.cn
http://www.dt0577.cn/news/123745.html

相关文章:

  • 网站建设及维护费算业务宣传费新闻投稿平台有哪些
  • 运城网站建设价格湘潭seo优化
  • 福州seo结算正规网络公司关键词排名优化
  • 深圳做网站网络营销公司如何用网站模板建站
  • WordPress资讯类主题破解郑州网站seo技术
  • 网站后台怎么做友情链接seo推广多少钱
  • 超市网站源码什么时候网络推广
  • 网站维护费计入什么科目大数据网站
  • 网站空间续费合同下载百度网盘app最新版
  • 网站好的案例百度快照官网登录
  • 湖北黄石市黄石市建设材料价格信息在哪个网站查询企业网站首页
  • 北京做网站建设的公司哪家好优化落实疫情防控新十条
  • 网站优化工具大数据分析师
  • 旅游网站模板下载品牌推广是做什么的
  • vps 同时翻墙和做网站软件推广平台有哪些?哪个比较好
  • 网站建设网站维护的具体内容是什么微信社群营销推广方案
  • 网站开发主流语言seo标题关键词怎么写
  • 专业网站建设定制公司北京网站优化外包
  • 福州网站建设市场没有限制的国外搜索引擎
  • 襄阳做网站公司电话微信群推广平台有哪些
  • 课程网站开发 预算百度引流怎么推广
  • 怎么找网站的后台地址域名在线查询
  • 魔方的网站百度搜索风云榜电脑版
  • 找人做网站被骗为什么不构成诈骗罪推广产品的软文怎么写
  • 外流网站建设seo建站要求
  • 芜湖哪些公司做公司网站看啥网一个没有人工干预的网
  • 网站公司怎么做推广广告营销推广
  • 电商网站开发方案淘宝网官方网站
  • 如何做网站的内容买卖链接网站
  • 网站的首页怎么做的今日热点新闻素材