[解決済み] C++のメンバ関数からObjective-Cのメソッドを呼び出すには?
質問
クラス(
EAGLView
のメンバー関数を呼び出すクラスがあります。
C++
クラスのメンバー関数を問題なく呼び出すことができます。さて、問題なのはその
C++
クラスで
objective-C
function
[context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer];
でできないことを
C++
の構文ではできません。
これをラップして
Objective-C
の呼び出しを同じ
Objective-C
クラスのメソッドを呼び出します。
C++
からそのメソッドを呼び出す必要がありますが、それを行う方法がわかりません。
へのポインタを与えようとしたのですが
EAGLView
オブジェクトを C++ のメンバ関数に渡して、" をインクルードしてみました。
EAGLView.h
を私の
C++
クラスヘッダを作成しましたが、3999エラーが発生しました。
それで...私はこれをどのように行うべきですか?例があればいいのですが...。私が見つけたのは純粋な
C
の例しか見つけられませんでした。
どのように解決するのですか?
C++とObjective-Cは、注意深く行えば混ぜることができます。いくつかの注意点がありますが、一般的には混ぜることができます。これらを分離しておきたい場合は、Objective-C オブジェクトに非 Objective-C コードから使用可能な C スタイルのインターフェイスを与える標準 C ラッパー関数を設定できます (ファイルの名前をより良いものにします。私は冗長性のためにこれらの名前を選びました)。
MyObject-C-Interface.h
#ifndef __MYOBJECT_C_INTERFACE_H__
#define __MYOBJECT_C_INTERFACE_H__
// This is the C "trampoline" function that will be used
// to invoke a specific Objective-C method FROM C++
int MyObjectDoSomethingWith (void *myObjectInstance, void *parameter);
#endif
MyObject.h
#import "MyObject-C-Interface.h"
// An Objective-C class that needs to be accessed from C++
@interface MyObject : NSObject
{
int someVar;
}
// The Objective-C member function you want to call from C++
- (int) doSomethingWith:(void *) aParameter;
@end
MyObject.mm
#import "MyObject.h"
@implementation MyObject
// C "trampoline" function to invoke Objective-C method
int MyObjectDoSomethingWith (void *self, void *aParameter)
{
// Call the Objective-C method using Objective-C syntax
return [(id) self doSomethingWith:aParameter];
}
- (int) doSomethingWith:(void *) aParameter
{
// The Objective-C function you wanted to call from C++.
// do work here..
return 21 ; // half of 42
}
@end
MyCPPClass.cpp
#include "MyCPPClass.h"
#include "MyObject-C-Interface.h"
int MyCPPClass::someMethod (void *objectiveCObject, void *aParameter)
{
// To invoke an Objective-C method from C++, use
// the C trampoline function
return MyObjectDoSomethingWith (objectiveCObject, aParameter);
}
ラッパー関数
は必要ありません。
が同じ
.m
ファイルにあるはずですが、Objective-C のクラスが存在するファイルは
は Objective-C コードとしてコンパイルされる必要があります。
. ラッパー関数を宣言するヘッダはCPPとObjective-Cの両方のコードに含まれる必要があります.
(注意: Objective-Cの実装ファイルに拡張子 ".m" が与えられると、それはXcodeの下でリンクされないでしょう。 拡張子 ".mm" は、Objective-C と C++ の組み合わせ、つまり Objective-C++ を期待するように Xcode に伝えます)。
上記をオブジェクト指向で実装するためには、以下のように PIMPLイディオム . 実装はわずかに異なるだけです。 要するに、MyClass のインスタンスへの (private) void ポインタを持つクラスの中に、 ("MyObject-C-Interface.h" で宣言されている) ラッパー関数を配置するのです。
MyObject-C-Interface.h。 (PIMPL)
#ifndef __MYOBJECT_C_INTERFACE_H__
#define __MYOBJECT_C_INTERFACE_H__
class MyClassImpl
{
public:
MyClassImpl ( void );
~MyClassImpl( void );
void init( void );
int doSomethingWith( void * aParameter );
void logMyMessage( char * aCStr );
private:
void * self;
};
#endif
ラッパーメソッドはもはや MyClass のインスタンスへの void ポインタを必要としないことに注意してください; それは今 MyClassImpl のプライベートメンバです。 init メソッドは MyClass インスタンスを生成するために使用されます.
MyObject.h (PIMPL)
#import "MyObject-C-Interface.h"
@interface MyObject : NSObject
{
int someVar;
}
- (int) doSomethingWith:(void *) aParameter;
- (void) logMyMessage:(char *) aCStr;
@end
MyObject.mm (PIMPL)
#import "MyObject.h"
@implementation MyObject
MyClassImpl::MyClassImpl( void )
: self( NULL )
{ }
MyClassImpl::~MyClassImpl( void )
{
[(id)self dealloc];
}
void MyClassImpl::init( void )
{
self = [[MyObject alloc] init];
}
int MyClassImpl::doSomethingWith( void *aParameter )
{
return [(id)self doSomethingWith:aParameter];
}
void MyClassImpl::logMyMessage( char *aCStr )
{
[(id)self doLogMessage:aCStr];
}
- (int) doSomethingWith:(void *) aParameter
{
int result;
// ... some code to calculate the result
return result;
}
- (void) logMyMessage:(char *) aCStr
{
NSLog( aCStr );
}
@end
MyClass は MyClassImpl::init への呼び出しでインスタンス化されることに注意してください。 MyClassImpl のコンストラクタで MyClass をインスタンス化することもできますが、それは一般的に良いアイデアではありません。 MyClass のインスタンスは MyClassImpl のデストラクタから破壊されます。 C言語での実装と同様に,ラッパーメソッドはMyClassの各メソッドに委ねるだけです.
MyCPPClass.h (PIMPL)
#ifndef __MYCPP_CLASS_H__
#define __MYCPP_CLASS_H__
class MyClassImpl;
class MyCPPClass
{
enum { cANSWER_TO_LIFE_THE_UNIVERSE_AND_EVERYTHING = 42 };
public:
MyCPPClass ( void );
~MyCPPClass( void );
void init( void );
void doSomethingWithMyClass( void );
private:
MyClassImpl * _impl;
int _myValue;
};
#endif
MyCPPClass.cpp (PIMPL)
#include "MyCPPClass.h"
#include "MyObject-C-Interface.h"
MyCPPClass::MyCPPClass( void )
: _impl ( NULL )
{ }
void MyCPPClass::init( void )
{
_impl = new MyClassImpl();
}
MyCPPClass::~MyCPPClass( void )
{
if ( _impl ) { delete _impl; _impl = NULL; }
}
void MyCPPClass::doSomethingWithMyClass( void )
{
int result = _impl->doSomethingWith( _myValue );
if ( result == cANSWER_TO_LIFE_THE_UNIVERSE_AND_EVERYTHING )
{
_impl->logMyMessage( "Hello, Arthur!" );
}
else
{
_impl->logMyMessage( "Don't worry." );
}
}
これで、MyClassImpl のプライベートな実装を通して MyClass への呼び出しにアクセスできるようになりました。このアプローチはポータブルなアプリケーションを開発している場合、有利になります; MyClass の実装を他のプラットフォームに固有のものと単純に交換することができます ... しかし正直なところ、これがより良い実装であるかどうかは、より好みやニーズの問題です。
関連
-
[解決済み] [Solved] Error C1083: Cannot open include file: 'stdafx.h'
-
[解決済み】C++コンパイルタイムエラー:数値定数の前に期待される識別子
-
[解決済み] Objective-CでNSStringsを連結するためのショートカット集
-
[解決済み] Objective-Cの定数
-
[解決済み] Objective-Cで乱数を発生させる
-
[解決済み] なぜC++はPythonよりもstdinからの行の読み込みが遅いのですか?
-
[解決済み] Objective-Cで、ある文字列が他の文字列を含んでいるかどうかを調べるにはどうすればよいですか?
-
[解決済み] Objective-Cのtypedef enumとは何ですか?
-
[解決済み] SwiftからObjective-Cのコードを呼び出すにはどうしたらいいですか?
-
[解決済み] 関数ポインタを使ったC++メンバ関数の呼び出し
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】C++エラー。アーキテクチャ x86_64 に対して未定義のシンボル
-
[解決済み】識別子 "string "は未定義?
-
[解決済み】 != と =! の違いと例(C++の場合)
-
[解決済み] string does not name a type Errorが発生するのはなぜですか?
-
[解決済み】Cygwin Make bash コマンドが見つかりません。
-
[解決済み】「std::operator」で「operator<<」にマッチするものがない。
-
[解決済み】#include<iostream>は存在するのですが、「識別子 "cout "は未定義です」というエラーが出ます。なぜですか?
-
[解決済み] to_string は std のメンバーではない、と g++ が言っている (mingw)
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み】デバッグアサーションに失敗しました