我正在使用 Djinni 在 android 和 ios 之间共享一些大型 c++ 代码库。各种组件之一(我们称之为Foo
!!!)在 android 和 ios 上具有不同的实现。Foo
是一个接口,c++ 代码无需了解其内部结构就可以使用该接口。
android 实现虽然 ( FooAndroid
) 有一些额外的方法,android 客户端可以使用这些方法以仅对 android 平台有意义的方式修改组件的行为。
由于缺乏接口继承,这使 djinni 的事情变得复杂。我想出了一种解决方案,它依赖于这样一个事实,即FooAndroid
可以子类化两个不同的 djinni 接口,它们的大多数方法都具有相同的签名,但结果并不漂亮。
这是djinni接口说明:
foo = interface +c {
static create() : foo;
doSomething();
}
foo_android = interface +c {
static create() : foo_android;
doSomething();
doAnotherThing();
asFoo(): foo;
}
bar = interface +c {
static create() : bar;
useFoo(f: foo);
}
您会注意到Bar
一个只需要访问Foo
实例的组件。
然后以这种方式实现生成的接口:
// Foo android implementation:
class FooAndroidImpl : public Foo, public FooAndroid {
public:
void doSomething() override { LOGI("do something"); }
void doAnotherThing() override { LOGI(" do something"); }
std::weak_ptr<Api::Foo> fooSelfReference;
std::shared_ptr<Api::Foo> asFoo() override { return fooSelfRef.lock(); }
};
// instance creation methods:
std::shared_ptr<FooAndroidImpl> createImpl() {
auto p = std::make_shared<FooAndroidImpl>();
p->fooSelfRef = p;
return p;
}
std::shared_ptr<FooAndroid> FooAndroid::create()
{
return createImpl();
}
std::shared_ptr<Foo> Foo::create()
{
return createImpl();
}
// Bar implementation:
class BarImpl : public Bar {
public:
void useFoo(const std::shared_ptr<Foo> & f) override { f->doSomething(); }
};
std::shared_ptr<Bar> Bar::create()
{
return std::make_shared<BarImpl>();
}
然后我可以通过这种方式在 java 中使用 FooAndroid 和 Bar:
FooAndroid fooAndroid = FooAndroid.create();
fooAndroid.doAnotherThing();
Bar bar = Bar.create();
bar.useFoo(fooAndroid.asFoo());
这行得通,但很难看,我必须手动定义两个几乎相同的 djinni 接口,而且我仍然不确定存储该 weak_ptr 对对象生命周期的所有影响。
我觉得我在滥用 Djinni 的目的和模式,所以也许有更好的方法来实现我想要做的事情?