首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >djinni创建的目标-c协议不起作用

djinni创建的目标-c协议不起作用
EN

Stack Overflow用户
提问于 2018-01-28 21:21:23
回答 1查看 345关注 0票数 0

我使用djinni在c++、java和objective之间创建跨平台代码,因为我目前正在将许多代码移到跨平台c++实现上。

问题是,我有一个接口,它是目标c中的一个协议。另一个接口,在c++中实现,将该协议的hte实现作为参数,然后调用该方法。但是这个方法在目标c中根本没有被调用(更快,但我也试图在目标c中实现这个协议,不起作用)。我已经做了更多的调查,但是首先我的代码。

为了查看我的问题是否是由现有代码引起的,我创建了一个测试项目,但它仍然是这样的:

这是我的djinni的idl文件:

代码语言:javascript
复制
DataProvider = interface +j +o {
    const getContentForUrl(url: string): string;
}

DataUser = interface +c {
    static create(url: string, dataProvider: DataProvider): DataUser;
    getContent(): string;
}

这是创建的c++文件:

DataProvider.hpp:

代码语言:javascript
复制
// AUTOGENERATED FILE - DO NOT MODIFY!
// This file generated by Djinni from htmlparser.djinni

#pragma once

#include <string>

namespace testdjinni {

class DataProvider {
public:
    virtual ~DataProvider() {}

    virtual std::string getContentForUrl(const std::string & url) = 0;
};

}  // namespace testdjinni

DataUser.hpp:

代码语言:javascript
复制
// AUTOGENERATED FILE - DO NOT MODIFY!
// This file generated by Djinni from htmlparser.djinni

#pragma once

#include <memory>
#include <string>
#include <vector>

namespace testdjinni {

class DataProvider;

class DataUser {
public:
    virtual ~DataUser() {}

    static std::shared_ptr<DataUser> create(const std::string & url, const std::shared_ptr<DataProvider> & dataProvider);

    virtual std::string getContent() = 0;

};

}  // namespace destdjinni

这是我的DataUser接口和C++中的实现:

DataUserImpl.h:

代码语言:javascript
复制
#ifndef TESTDJINNI_DATAUSER_H
#define TESTDJINNI_DATAUSER_H

#include <string>
#include "generated-src/cpp/DataUser.hpp"

using namespace std;

class DataUserImpl : public testdjinni::DataUser{

private:
    string *content;
    testdjinni::DataUser *dataUser;

public:
    DataUserImpl(const string &url, testdjinni::DataProvider *dataProvider);

    virtual string getContent();

};


#endif //TESTDJINNI_DATAUSER

DataUserImpl.cpp:

代码语言:javascript
复制
#include <iostream>
#include "DataUserImpl.h"
#include "generated-src/cpp/DataProvider.hpp"

DataUserImpl::DataUserImpl(const string &url, testdjinni::DataProvider *dataProvider): dataProvider(dataProvider) {
    this->url = new string(url);
}

HtmlDocumentImpl::~HtmlDocumentImpl() {
    delete url;
}

std::shared_ptr<testdjinni::DataUser> testdjinni::DataUser::create(const std::string & url, const std::shared_ptr<testdjinni::DataProvider> & dataProvider) {
    return std::shared_ptr<testdjinni::DataUser>(new DataUserImpl(url, dataProvider.get()));
}

string DataUserImpl::getContent() {
if (this->content == NULL || *this->content == "")
    this->content = new string(this->getDataProvider()->getContentForUrl(*this->url));
    return *this->content;
};

现在,我已经使用了快速代码(我在目标C中也尝试了同样的代码,但没有工作):

代码语言:javascript
复制
class Provider: HPDataProvider {
    func getContentForUrl(_ url: String) -> String {
        return "Testcontent und so"
    }
}

class ViewController: UIViewController {

    let provider = Provider()

    override func viewDidLoad() {
        super.viewDidLoad()

        let user = HPDataUser.create("http://www.testurl.com", dataProvider: provider)

        print(user?.getContent())
    }
}

问题是,实现的协议中的pethgetContentForUrl根本没有被调用。我撞车了:

Assertion failed: (string), function toCpp, file /Path/to/my/project/deps/djinni/support-lib/objc/DJIMarshal+Private.h, line 119.

所以我现在可以说的是,字符串似乎是null,我的协议实现没有被调用。

好吧,我下来看看会发生什么:

在为DataProvider+Private.mm生成的文件中,如下所示:

代码语言:javascript
复制
// AUTOGENERATED FILE - DO NOT MODIFY!
// This file generated by Djinni from htmlparser.djinni

#import "HPDataProvider+Private.h"
#import "HPDataProvider.h"
#import "DJIMarshal+Private.h"
#import "DJIObjcWrapperCache+Private.h"
#include <stdexcept>

static_assert(__has_feature(objc_arc), "Djinni requires ARC to be enabled for this file");

namespace djinni_generated {

class DataProvider::ObjcProxy final
: public ::htmlparser::DataProvider
, private ::djinni::ObjcProxyBase<ObjcType>
{
    friend class ::djinni_generated::DataProvider;
public:
    using ObjcProxyBase::ObjcProxyBase;
    std::string getContentForUrl(const std::string & c_url) override
    {
        @autoreleasepool {

            // Here, the objcpp_result is null, even if the object was not null, but my implementation of the protocol was never called.

            auto objcpp_result_ = [djinni_private_get_proxied_objc_object()  getContentForUrl:(::djinni::String::fromCpp(c_url))];
            return ::djinni::String::toCpp(objcpp_result_);
        }
    }
};

}  // namespace djinni_generated

namespace djinni_generated {

auto DataProvider::toCpp(ObjcType objc) -> CppType
{
    if (!objc) {
        return nullptr;
    }
    return ::djinni::get_objc_proxy<ObjcProxy>(objc);
}

auto DataProvider::fromCppOpt(const CppOptType& cpp) -> ObjcType
{
    if (!cpp) {
        return nil;
    }
    return dynamic_cast<ObjcProxy&>(*cpp).djinni_private_get_proxied_objc_object();
}

}  // namespace djinni_generated

我不知道我在这里能做什么。我是说,这只是基本代码..。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-01-29 08:25:33

您所经历的错误是由于不正确地使用shared_ptr造成的。

代码语言:javascript
复制
std::shared_ptr<testdjinni::DataUser> testdjinni::DataUser::create(const std::string & url, const std::shared_ptr<testdjinni::DataProvider> & dataProvider) {
    return std::shared_ptr<testdjinni::DataUser>(new DataUserImpl(url, dataProvider.get()));
}

将DataProvider原始指针(dataProvider.get())传递给DataUserImpl。当持有原始指针的shared_ptrs全部消失时,您用原始指针指向的对象将被销毁。

由于您没有在任何地方保存shared_ptr,因此在其结束时,您的DataProvider对象也会被销毁,并且指向无效内存。

解决方案是将shared_ptr保存为DataUserImpl字段,而不是原始指针。这样,您的对象的生存期将延长到DataUserImpl的生存期。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48491452

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档