3

openGL-es(xcodeopenGLゲームテンプレートとpowervr3.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から)です。リンクを追加しますが、これが許可されているかどうかはわかりません。 これがクラスヘッダーへのリンクですが、このバージョン(およびWeb上の他のバージョン)には、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 ++オブジェクトは、純粋なObjCインターフェイスを維持しながら、トリックなしでプライベートC++プロパティを持つことができるようになりました。

この問題についてどのように考えたいかを次に示します。

  • デリゲートであるC++オブジェクトを作成します。委任の設定などに関連するすべてのコードをC++で記述します。したがって、「thisポインターを渡す」と表示されている場合は、実際にはthisポインターを渡す必要があります(C ++コードでこれを行う必要があるため)。C ++呼び出しでキャストを行っているという事実_bridgeは、何かがうまくいかないという本当のヒントです。
  • ObjCがC++オブジェクトをプロパティとして所有するようにします。
  • デリゲートコールバックをC++オブジェクト内のC++で記述します。便利な場合は、必要に応じてC ++オブジェクトにObjCオブジェクトの呼び出しを行わせることができますが、C++オブジェクトがすべてのデリゲート作業を実行する方が簡単な場合があります。
于 2012-12-24T03:19:53.497 に答える
0

私はついにこれを機能させましたが、そうするためにviewControllerからobj-cラッパークラスを削除する必要がありました。コードは次のようになります。

ViewController.h

struct Opaque;

@interface ViewController : GLKViewController {

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

ViewController.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)

ラッパークラスが機能しない理由はわかりませんが、コールバックが機能していることを嬉しく思います(クラッシュしないでください!)

ふぅ、それはラフだった。何か考え/コメントはありますか?

于 2012-12-24T03:28:43.553 に答える