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

标签 ios opengl-es-2.0 powervr-sgx

我一直在尝试将 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 - 应用内购买无效

ios - 导航栏顶部项目标题左对齐

java - 法线发生了变化,但光照仍然很奇怪?

android - PowerVR Android 示例 : makefile not working

ios - 检索 WebVie URL Swift ||无法将类型 'ViewController' 的值分配给类型 'UIWebViewDelegate?'

ios - 通过 REST API 将 NSAttributedString 发布到服务器

Android : OpenGL 2. 0 第一人称相机

opengl-es - 在 OpenGL ES 2 中正确进行 Sprite 四边形和深度测试

opengl-es - OpenGL ES 渲染到用户空间内存