从 C++ 成员函数调用 Objective-C 方法? [英] Calling Objective-C method from C++ member function?

查看:69
本文介绍了从 C++ 成员函数调用 Objective-C 方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a class (EAGLView) which calls a member function of a C++ class without problems. Now, the problem is that I need to call in that C++ class a objective-C function [context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer]; which I cannot do in C++ syntax.

我可以将这个 Objective-C 调用包装到同一个 Objective-C 类,它首先称为 C++ 类,但随后我需要以某种方式调用它来自 C++ 的方法,我不知道该怎么做.

I could wrap this Objective-C call to the same Objective-C class which in the first place called the C++ class, but then I need to somehow call that method from C++, and I cannot figure out how to do it.

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

I tried to give a pointer to EAGLView object to the C++ member function and include the "EAGLView.h" in my C++ class header but I got 3999 errors..

那么..我该怎么做呢?一个例子会很好..我只找到了这样做的纯 C 例子.

So.. how should I do this? An example would be nice.. I only found pure C examples of doing this.

推荐答案

如果你小心翼翼,你可以将 C++ 与 Objective-C 混合使用.有一些警告,但总的来说,它们可以混合使用.如果您想将它们分开,您可以设置一个标准的 C 包装函数,该函数为 Objective-C 对象提供一个来自非 Objective-C 代码的可用 C 样式接口(为您的文件选择更好的名称,我选择了这些名称详细):

You can mix C++ with Objective-C if you do it carefully. There are a few caveats but generally speaking they can be mixed. If you want to keep them separate, you can set up a standard C wrapper function that gives the Objective-C object a usable C-style interface from non-Objective-C code (pick better names for your files, I have picked these names for verbosity):

#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

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

包装函数不需要与Objective-C类在同一个.m文件中,但是它确实存在于需要编译为 Objective-C 代码.声明包装函数的头文件需要包含在 CPP 和 Objective-C 代码中.

The wrapper function does not need to be in the same .m file as the Objective-C class, but the file that it does exist in needs to be compiled as Objective-C code. The header that declares the wrapper function needs to be included in both CPP and Objective-C code.

(注意:如果 Objective-C 实现文件被赋予扩展名.m",它不会在 Xcode 下链接..mm"扩展名告诉 Xcode 期待 Objective-C 和 C++ 的组合,即,Objective-C++.)

(NOTE: if the Objective-C implementation file is given the extension ".m" it will not link under Xcode. The ".mm" extension tells Xcode to expect a combination of Objective-C and C++, i.e., Objective-C++.)

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

You can implement the above in an Object-Orientented manner by using the PIMPL idiom. The implementation is only slightly different. In short, you place the wrapper functions (declared in "MyObject-C-Interface.h") inside a class with a (private) void pointer to an instance of MyClass.

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

Notice the wrapper methods no longer require the void pointer to an instance of MyClass; it is now a private member of MyClassImpl. The init method is used to instantiate a MyClass instance;

#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 的相应方法.

Notice that MyClass is instantiated with a call to MyClassImpl::init. You could instantiate MyClass in MyClassImpl's constructor, but that generally isn't a good idea. The MyClass instance is destructed from MyClassImpl's destructor. As with the C-style implementation, the wrapper methods simply defer to the respective methods of MyClass.

#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 的实现替换为特定于另一个平台的实现……但老实说,这是否是更好的实现更取决于品味和需求.

You now access calls to MyClass through a private implementation of MyClassImpl. This approach can be advantageous if you were developing a portable application; you could simply swap out the implementation of MyClass with one specific to the other platform ... but honestly, whether this is a better implementation is more a matter of taste and needs.

这篇关于从 C++ 成员函数调用 Objective-C 方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆