私は Rust で C ライブラリをラップしており、その関数の多くは構造体へのポインターによってパラメーターを受け取ります。構造体自体が他の構造体へのポインターを持っていることがよくあります。オーバーヘッドを削減するために、Rust データを C 構造体にマーシャリングした結果をキャッシュする機能を提供したいと思います。
C ライブラリがいくつかのパラメーターを期待する方法の例を次に示します。
#[repr(C)]
struct Foo {
x: i32,
y: f32
}
#[repr(C)]
struct Bar {
p_foo: *const Foo,
z: bool
}
そして、所有している「キャッシュされた」バージョンがどのように見えるかを想像する方法:
struct Cached {
foo: Option<Foo>,
bar: Bar
}
のp_foo
フィールドは、内の値bar
を指すように構築されるか、存在する場合はヌル ポインタになります。Some
foo
None
もちろん、ここでの問題は、値Cached
が移動される場合、ストレートmemcpy
は不適切であり、bar.p_foo
さらにリダイレクトする必要があるということです。bar.p_foo
これは、定義可能な移動セマンティクスを備えたC++で簡単に保証できますが、Rustは「使用されるまで設定しない」以外の解決策を提供しますか? そのようにすることは確かに機能しますが、これらのキャッシュされた値が再利用される以上に (またはそれに近い頻度で) 移動されるとは思いません。これらを設定するには少し作業が必要です。特にネスト/チェーンが深い/長い場合。Box
また、ヒープ上にサブ構造を配置したくありません。
明確にするために、Rustで複製したいC++で書くことができるものを次に示します。
struct Foo {
int x;
float y;
};
struct Bar {
Foo const*pFoo;
bool z;
};
// bear with me while I conjure up a Maybe for C++
class Cached {
public:
// would have appropriate copy constructor/assignment
Cached(Cached &&other) {
m_foo = other.m_foo;
m_bar = other.m_bar;
if(m_foo.isJust()) {
m_bar.pFoo = &m_foo.value();
} // else already nullptr
}
// similar move assignment
private:
Maybe<Foo> m_foo;
Bar m_bar;
};