我有一个类(EAGLView),它可以毫无问题地调用C++类的成员函数.现在的问题是,我需要调用C++类a objective-C function [context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer];,这在C++语法中是做不到的.

我可以把这Objective-C个调用封装到同一个Objective-C类中,这一类首先称为C++类,但是我需要从C++中调用这个方法,我无法理解如何go 做.

我试图给指针指向C++成员函数EAGLView个对象,在C++个类头中包含"EAGLView.h",但我得到了3999个错误.

所以我该怎么做?举个例子就好了..我只找到了C个这样做的例子.

推荐答案

如果你仔细地做C++,你可以将它与Objul-C混合.有一些警告,但一般来说,它们可能是混合的.如果希望将它们分开,可以设置一个标准的C包装函数,为Objective-C对象提供一个与非Objective-C代码不同的可用C风格接口(为文件 Select 更好的名称,我 Select 这些名称是为了更详细):

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

我的对象.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

我的对象.嗯

#import "我的对象.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

我的课.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);
}

包装函数does not need与Objective-C类位于同一个.m文件中,但它确实存在于needs to be compiled as Objective-C code中的文件中.声明包装器函数的头需要包含在CPP和Objective-C代码中.

(注意:如果ObjtoFor C实现文件被赋予了扩展名".m",它将不会在XCODE下链接.".mm"扩展告诉XCODE以Objy-C和C++,即Objul-C++为对象.


您可以使用PIMPL idiom以面向对象的方式实现上述功能.实现只是略有不同.简而言之,将包装函数(在"MyObject-C-Interface.H"中声明)放置在一个类中,该类具有指向MyClass实例的(私有)void指针.

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实例;

我的对象.H (PIMPL)

#import "MyObject-C-Interface.H"

@interface MyObject : NSObject
{
    int someVar;
}

- (int)  doSomethingWith:(void *) aParameter;
- (void) logMyMessage:(char *) aCStr;

@end

我的对象.嗯 (PIMPL)

#import "我的对象.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

我的课.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的实现...但老实说,这是否是一个更好的实现更是一个品味和需求的问题.

Objective-c相关问答推荐

错误无法使 UICollectionElementKindCell 类型的视图出列

TWTweetComposeViewController 在 IOS6 中已弃用

用 UIActivityIndi​​catorView 替换 UIBarButtonItem

将 NSInteger 变量传递给 NSMutableDictionary 或 NSMutableArray

将 HEX NSString 转换为 NSData

将长按手势和拖动手势结合在一起

go 掉 UISearchBar 下的 1px 边框

在 Objective-C 中在 iPhone 上使用 HTTP POST 和 GET 的教程

具有匿名函数/块的 NSTimer?

在Objective-C中从类名的NSString创建对象

使用 Objective-C 查找 IMEI 号码

在我的 iOS Mail 和 Safari 应用程序中支持 Open In... 菜单项

Objective-C 中是否有一些文字字典或数组语法?

如何制作真正的私有实例变量?

如何用 Java 开发 iPhone 应用程序?

NSMutableArray 按顺序添加对象

iPhone SDK:如何在视图中播放视频?而不是全屏

请求访问相机胶卷的权限

AVAudioPlayer 不播放任何声音

iOS 上的电话号码格式