3

我一直在尝试将 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”指针,以便接收回调。我需要实现的委托方法是:

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 委托方法?我在这个问题上做了一些阅读,但似乎我正在阅读的内容是相反的。也就是cpp中的一个objective-c委托。这很令人困惑,但这是我的想法......

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

谢谢。

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

编辑: 这是我发现的关于混合objective-c和cpp的示例。这似乎与我想要做的非常相似。

更新:这是一些附加信息(由 user1118321 请求)

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

我从阅读这个帖子中找到了一个很好的例子,说明我认为我应该做什么。所以这是我到目前为止所拥有的:

我的CPP代表课...

    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;

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

这是您的课程类型 ID:P21PVRTPFXEffectDelegate。

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

4

2 回答 2

0

首先,您可能想查看包装 C++ 系列的最后一篇文章。在最新版本的 clang 中,大部分内容变得更加简单。您可能不再需要一半的代码了。ObjC++ 对象现在无需任何技巧即可拥有私有 C++ 属性,同时保持纯 ObjC 接口。

以下是您想如何考虑这个问题:

  • 构建一个作为委托的 C++ 对象。用 C++ 编写所有涉及设置委托等的代码。因此,当它说“传递this指针”时,您实际上应该传递一个this指针(因为您应该在 C++ 代码中执行此操作)。您_bridge在 C++ 调用中进行强制转换的事实确实暗示出了问题。
  • 让 ObjC 拥有 C++ 对象作为属性。
  • 在 C++ 对象内用 C++ 编写委托回调。如果有用,您可以让 C++ 对象根据需要调用 ObjC 对象,但如果 C++ 对象完成所有委托工作,可能会更容易。
于 2012-12-24T03:19:53.497 回答
0

我终于得到了这个工作,但必须从我的 viewController 中删除 obj-c 包装类才能这样做。代码如下所示:

视图控制器.h

struct Opaque;

@interface ViewController : GLKViewController {

    ...
    //RNWrap* opaqueCppWrap;  // this didn't work 
    struct Opaque *opaqueCpp; // try this
    ...
}

视图控制器.mm

// declare the Opaque structure
struct Opaque {
public:
    Opaque() : cppobject() {};

    myCppDelegate cppobject;
};

viewDidLoad

    // ... create opaque member on initialization
    opaqueCpp = new Opaque();

    //opaqueCppWrap = [[RNWrap alloc] init];  // old way of doing things using wrapper

将委托传递给 Load 方法

// old way using bridge cast and wrapper 
//if(m_pEffect->Load(*m_pEffectParser, "Effect", c_szPfxFile,(__bridge myCppDelegate*)opaqueCppWrap, uiUnknownUniforms, &error) != PVR_SUCCESS)

// this works...
if(m_pEffect->Load(*m_pEffectParser, "Effect", c_szPfxFile, (myCppDelegate*)opaqueCpp, uiUnknownUniforms, &error) != PVR_SUCCESS)

不知道为什么包装类不起作用,但我很高兴我的回调正在工作(appy no crashy!)

呸,那太粗糙了。有什么想法/意见吗?

于 2012-12-24T03:28:43.553 回答