Я использую Djinni, чтобы поделиться большой базой кода на c ++ между android и ios. Один из различных компонентов (назовем его Foo
!!!) имеет различную реализацию на android и ios. Foo
- это интерфейс, который используется кодом C ++ без необходимости что-либо знать о его внутренностях.
В реализации Android (FooAndroid
) есть несколько дополнительных методов, которые клиент Android может использовать для изменения поведения компонента способами, имеющими смысл только для платформы Android.
Это усложняет работу с джиннами из-за отсутствия наследования интерфейса. Я придумал своего рода решение, основанное на том факте, что FooAndroid
может создавать подклассы двух разных интерфейсов 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>();
}
Затем я могу использовать FooAndroid и Bar в Java следующим образом:
FooAndroid fooAndroid = FooAndroid.create();
fooAndroid.doAnotherThing();
Bar bar = Bar.create();
bar.useFoo(fooAndroid.asFoo());
Это работает, но это уродливо, мне приходится вручную определять два почти идентичных интерфейса djinni, и я до сих пор не уверен во всех последствиях сохранения этого weak_ptr для жизненного цикла объекта.
Я чувствую, что злоупотребляю целью и моделью Джинни, так что, может быть, есть лучший способ достичь того, что я пытаюсь сделать?