草庐IT

ios - 如何为 cpp 类创建 objective-c 委托(delegate)?

coder 2024-01-13 原文

我一直在尝试将 openGL-es(xcode openGL 游戏模板与 powervr 3.0 sdk 的 ogles2tools 库结合起来。我的问题是我加载效果文件的代码行:

/* 
 Load the effect.
 We pass 'this' as an argument as we wish to receive callbacks as the PFX is loaded.
 This is optional and supplying NULL implies that the developer will take care
 of all texture loading and binding to to the Effect instead.
*/
if(m_pEffect->Load(*m_pEffectParser, "Effect", c_szPfxFile, NULL, uiUnknownUniforms, &error) != PVR_SUCCESS)
{
    NSLog(@"%s",error.c_str());
    return;
}

我应该传递一个“this”指针以便接收回调。我需要实现的委托(delegate)方法是:

EPVRTError OGLES2IntroducingPFX::PVRTPFXOnLoadTexture(const CPVRTStringHash& TextureName, GLuint& uiHandle, unsigned int& uiFlags)
{
    /*
     This is an optional callback function for PVRTPFXEffect and can be used to automate 
     the texture loading process.
     If multiple effects are to be loaded and they share textures it would be
     prudent to have a caching system in place so texture memory is not wasted.
     Please see OGLES2MagicLantern for an example of this.
    */
    if(PVRTTextureLoadFromPVR(TextureName.String().c_str(), &uiHandle) != PVR_SUCCESS)
    return PVR_FAIL;

    return PVR_SUCCESS;
}

我想对我来说最大的问题是如何在 objective-c 中提供 cpp 委托(delegate)方法?我对这个问题做了一些阅读,但似乎我正在阅读的内容是相反的。也就是说,cpp 中的 objective-c 委托(delegate)。这很令人困惑,但这是我的想法......

我创建了一个 cpp 类来实现我需要的方法。我将它添加到我的 viewController 类,并在 m_pEffect->Load 调用中将指针传递给这个 cpp 类。这看起来正确吗?

谢谢。

附言对不起,如果我的代码格式不好。我还在学习。

编辑: Here's the example我发现关于混合 objective-c 和 cpp。这看起来真的和我想做的很相似。

更新:这是一些额外的信息(由 user1118321 请求)

需要委托(delegate)的 CPP 类是 CPVRTPFXEffect(PVRTPFXParserAPI.h - 来自 powerVR SDK 3.0)。我会添加一个链接,但我不确定这是否被允许。 Here's a link 到类头,但是这个版本(和网络上的其他版本)没有包含 load 方法的 pDelegate 属性。我假设它们是以前版本的示例。让我知道是否可以发布这个类文件,我会这样做。

我找到了一个 good example我认为我应该从阅读中做什么 this thread .所以这是我到目前为止所拥有的:

我的 CPP 委托(delegate)类...

    class myCppDelegate : public PVRTPFXEffectDelegate {
public:
    myCppDelegate() {};
    EPVRTError PVRTPFXOnLoadTexture(const CPVRTStringHash& TextureName, GLuint& uiHandle, unsigned int& uiFlags) { 
        return PVR_FAIL; 
    };

};

我的 Obj-C 包装器类(刚刚从上面的示例链接修改而来)...

struct RNWrapOpaque;

@interface RNWrap : NSObject {
struct RNWrapOpaque *_cpp;
}

- (id)init;
@end

实现...

#import "RNWrap.h"
#import "Wrap.h"

@interface RNWrap ()
@property (nonatomic, readwrite, assign) RNWrapOpaque *cpp;
@end

@implementation RNWrap
@synthesize cpp = _cpp;


struct RNWrapOpaque
{
public:
    RNWrapOpaque() : wrap() {};
    myCppDelegate wrap;
};

- (id)init
{
    self = [super init];
    if (self != nil)
    {
        self.cpp = new RNWrapOpaque();
    }
    return self;
}

- (void)dealloc
{
    delete _cpp;
    _cpp = NULL;

//  [super dealloc];
}

@end

基本上我能够编译代码和调试,但是当 CPVRTPFEffect 类进行此调用时:

        if(pDelegate->PVRTPFXOnLoadTexture(pTexDesc->FileName, uiHandle, uiFlags) != PVR_SUCCESS)

我得到 EXC_BAD_ACCESS。我假设它没有找到我的回调方法,因为我设置了一个断点并且该行永远不会被调用。

这是我更新的代码,它使用代理参数的桥接命令调用 CPVRTPFXEffect::Load。

    if(m_pEffect->Load(*m_pEffectParser, "Effect", c_szPfxFile,(__bridge myCppDelegate*)opaqueCppWrap, uiUnknownUniforms, &error) != PVR_SUCCESS)

感谢您的帮助!

更新 2: 该项目使用 ARC。这是我的 viewController 界面的样子:

@interface ViewController : GLKViewController {
    ...
    RNWrap* opaqueCppWrap;
    ...
}

@property (strong) RNWrap *opaqueCppWrap;

添加@property 对 EXC_BAD_ACCESS 没有帮助。当我跟踪 CPP 代码时,我不确定如何“查看”pDelegate 的值。当我将鼠标悬停在变量上时,Xcode 不会显示任何内容。

我将以下代码行添加到 CPVRTPFXEffect::Load 方法(就在它崩溃的行之前):

        *pReturnError += PVRTStringFromFormattedStr("Here is your class typeid: %s.\n", typeid(pDelegate).name());
        return PVR_FAIL;

这是调试输出窗口中显示的内容:

这是您的类 typeid:P21PVRTPFXEffectDelegate。

我不确定“P21”是什么意思(如果有的话),但看起来我快要开始工作了。我不知道,也许这已经很接近了。仍然崩溃,找不到我的方法。

最佳答案

首先,您可能需要查看 last article in the series on wrapping C++ .在最新版本的 clang 中,大部分内容变得更加简单。您可能不再需要这段代码的一半了。 ObjC++ 对象现在无需任何技巧即可拥有私有(private) C++ 属性,同时保持纯 ObjC 接口(interface)。

下面是你想如何思考这个问题:

  • 构建一个作为委托(delegate)的 C++ 对象。用 C++ 编写所有涉及设置委托(delegate)等的代码。所以当它说“传递一个 this 指针”时,你实际上应该传递一个 this 指针(因为你应该在 C++ 代码中这样做)。事实上,您正在 C++ 调用中执行 _bridge 强制转换,这是一个真正的暗示出了问题。
  • 让 ObjC 拥有 C++ 对象作为属性。
  • 在 C++ 对象内用 C++ 编写委托(delegate)回调。如果有用,您可以让 C++ 对象根据需要调用 ObjC 对象,但如果 C++ 对象完成所有委托(delegate)工作,可能会更容易。

关于ios - 如何为 cpp 类创建 objective-c 委托(delegate)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14008844/

有关ios - 如何为 cpp 类创建 objective-c 委托(delegate)?的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby - 如何在 Ruby 中顺序创建 PI - 2

    出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits

  3. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  4. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  5. ruby-on-rails - 无法使用 Rails 3.2 创建插件? - 2

    我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby​​1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在

  6. ruby - 如何为 emacs 安装 ruby​​-mode - 2

    我刚刚为fedora安装了emacs。我想用emacs编写ruby。为ruby​​提供代码提示、代码完成类型功能所需的工具、扩展是什么? 最佳答案 ruby-mode已经包含在Emacs23之后的版本中。不过,它也可以通过ELPA获得。您可能感兴趣的其他一些事情是集成RVM、feature-mode(Cucumber)、rspec-mode、ruby-electric、inf-ruby、rinari(用于Rails)等。这是我当前用于Ruby开发的Emacs配置:https://github.com/citizen428/emacs

  7. ruby - 如何使用 RSpec::Core::RakeTask 创建 RSpec Rake 任务? - 2

    如何使用RSpec::Core::RakeTask初始化RSpecRake任务?require'rspec/core/rake_task'RSpec::Core::RakeTask.newdo|t|#whatdoIputinhere?endInitialize函数记录在http://rubydoc.info/github/rspec/rspec-core/RSpec/Core/RakeTask#initialize-instance_method没有很好的记录;它只是说:-(RakeTask)initialize(*args,&task_block)AnewinstanceofRake

  8. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  9. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  10. ruby - 为什么 SecureRandom.uuid 创建一个唯一的字符串? - 2

    关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?

随机推荐