C ++ सदस्य फ़ंक्शन से ऑब्जेक्टिव-सी विधि को कॉल करना?


111

मेरे पास एक वर्ग ( EAGLView) है जो C++समस्याओं के बिना एक वर्ग के सदस्य फ़ंक्शन को कॉल करता है। अब, समस्या यह है कि मुझे उस C++कक्षा में कॉल करने की आवश्यकता है objective-C function [context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer];जो मैं C++सिंटैक्स में नहीं कर सकता ।

मैं इस Objective-Cकॉल को उसी Objective-Cकक्षा में लपेट सकता हूं जिसे पहली बार C ++ वर्ग कहा जाता है, लेकिन फिर मुझे किसी तरह से उस पद्धति को कॉल करने की आवश्यकता होती है C++, और मैं यह पता नहीं लगा सकता कि यह कैसे करना है।

मैंने EAGLViewC ++ सदस्य फ़ंक्शन पर ऑब्जेक्ट के लिए एक पॉइंटर देने की कोशिश की और EAGLView.hअपने C++क्लास हेडर में " " शामिल किया, लेकिन मुझे 3999 त्रुटियाँ मिलीं।

तो .. मुझे यह कैसे करना चाहिए? एक उदाहरण अच्छा होगा .. मुझे केवल Cऐसा करने के शुद्ध उदाहरण मिले ।

जवाबों:


204

यदि आप इसे ध्यान से करते हैं तो आप 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 , लेकिन यह जिस फ़ाइल में मौजूद है उसे ऑब्जेक्टिव-सी कोड के रूप में संकलित करने की आवश्यकता है । रैपर को घोषित करने वाले हेडर को CPP और ऑब्जेक्टिव-सी कोड दोनों में शामिल किया जाना चाहिए।

(नोट: यदि ऑब्जेक्टिव-सी कार्यान्वयन फ़ाइल को एक्सटेंशन ".m" दिया गया है तो यह Xcode के तहत लिंक नहीं होगा। ".mm" एक्सटेंशन, ऑब्जेक्ट-सी और C ++ अर्थात, Objective-C ++ के संयोजन की अपेक्षा करने के लिए Xcode को बताता है। )


आप PIMPL मुहावरे का उपयोग करके ऑब्जेक्ट को ओरिएंटेड तरीके से ऊपर लागू कर सकते हैं । कार्यान्वयन केवल थोड़ा अलग है। संक्षेप में, आप रैपर फ़ंक्शन (MyObject-C-Interface.h में घोषित) को MyClass के उदाहरण के लिए एक (निजी) शून्य पॉइंटर के साथ एक वर्ग के अंदर रखते हैं।

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 के उदाहरण के लिए शून्य सूचक की आवश्यकता नहीं है; अब यह 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 के विध्वंसक से नष्ट हो जाता है। सी-स्टाइल के कार्यान्वयन के साथ, रैपर तरीके केवल मायक्लास के संबंधित तरीकों के लिए सुरक्षित हैं।

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 के कार्यान्वयन को एक विशिष्ट के साथ दूसरे प्लेटफ़ॉर्म पर स्वैप कर सकते हैं ... लेकिन ईमानदारी से, क्या यह एक बेहतर कार्यान्वयन स्वाद और आवश्यकताओं का मामला है।


6
नमस्ते, मैंने कोशिश की, लेकिन मुझे लिंकेज त्रुटि यह कहते हुए मिल गई कि प्रतीक नहीं मिला। यानी यह MyObjectDoSomethingWith नहीं मिल सकता है। कोई विचार?

3
आपको extern "C"int MyObjectDoSomethingWith
सपने देखने

2
कोशिश की कि पहले से ही, काम नहीं करता है और यह समझ में आता है क्योंकि बाह्य "सी" का उपयोग तब किया जाता है जब हम C ++ फ़ंक्शन को C से कॉल करना चाहते हैं, इस मामले में हम C ++ से C फ़ंक्शन कह रहे हैं, नहीं?

6
इसके अलावा, MyCPPClass.cpp में ऑब्जेक्टिव कैसे त्वरित हो जाता है?
रफी खाचदौरां

2
बहुत बढ़िया @dreamlax, जो अब संकलित हो रहा है, लेकिन मुझे उस "someMethod" को कॉल करने की जानकारी नहीं है। कौन से पैरामीटर होने चाहिए जो इसमें जोड़े जाने चाहिए: int MyCPPClass :: someMethod (शून्य * वस्तुनिष्ठ, शून्य * aParameter) ???
the_moon

15

आप अपने कोड को ऑब्जेक्टिव-सी ++ के रूप में संकलित कर सकते हैं - सबसे आसान तरीका है अपने। यह तब ठीक से संकलित करेगा यदि आप इसमें शामिल हैं EAGLView.h(आपको बहुत सारी त्रुटियां मिल रही थीं क्योंकि C ++ कंपाइलर किसी भी ऑब्जेक्टिव-सी विशिष्ट कीवर्ड को नहीं समझता था), और आप (अधिकांश भाग के लिए) ऑब्जेक्टिव-सी और सी ++ को मिक्स कर सकते हैं, हालांकि पसंद।


क्या आप इस सी ++ फ़ाइल में उन सभी कंपाइलर त्रुटियों को प्राप्त कर रहे हैं, या वे किसी अन्य सी ++ फाइल में हैं जो इस सी ++ हेडर को शामिल करने के लिए होता है?
जेसी बेडर

ऐसा लगता है कि मैं C ++ हेडर फ़ाइल में EAGLView.h को शामिल नहीं कर सकता क्योंकि तब यह किसी कारण से यह उम्मीद करता है कि उद्देश्य C कोड C ++ है, और @ + अन्य प्रतीकों को नहीं समझता है
juvenis

12

सबसे आसान उपाय यह है कि सब कुछ संकलित करने के लिए केवल Xcode को बताया जाए।

उद्देश्य सी + + और recompile के रूप में संकलन सूत्रों के लिए अपनी परियोजना या लक्ष्य सेटिंग्स निर्धारित करें।

फिर आप C ++ या ऑब्जेक्टिव C का उपयोग हर जगह कर सकते हैं, उदाहरण के लिए:

void CPPObject::Function( ObjectiveCObject* context, NSView* view )
{
   [context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)view.layer]
}

यह आपके .cpp या .m से .mm तक के सभी स्रोत फ़ाइलों का नाम बदलने के समान ही है।

इसके लिए दो छोटे डाउनसाइड हैं: क्लैंग C ++ स्रोत कोड का विश्लेषण नहीं कर सकता है; कुछ अपेक्षाकृत अजीब सी कोड C ++ के तहत संकलित नहीं होते हैं।


मैं बस थोड़ा उत्सुक हूं, जब आप सब कुछ सी-ऑब्जेक्टिव-सी ++ के रूप में संकलित करते हैं तो क्या आपको सी-स्टाइल कास्ट और / या अन्य सी ++ का उपयोग करने के बारे में चेतावनी मिलती है - वैध सी-स्टाइल कोड के बारे में विशिष्ट चेतावनी?
ड्रीमलैक्स

निश्चित रूप से, आप C ++ में प्रोग्रामिंग कर रहे हैं, इसलिए आपसे उचित व्यवहार करने की अपेक्षा की जाएगी - लेकिन एक सामान्य नियम के रूप में, C ++, C से बेहतर C है, भले ही आप कभी भी क्लास न बनाएं। यह आपको बेवकूफ चीजें करने नहीं देगा, और यह आपको अच्छी चीजें करने देता है (जैसे बेहतर स्थिरांक और एनम और ऐसे)। आप अभी भी सिर्फ एक ही (जैसे (CFFloat) x) कास्ट कर सकते हैं।
पीटर एन लुईस

10

चरण 1

एक उद्देश्य सी फ़ाइल (.m फ़ाइल) बनाएँ और यह संबंधित हेडर फ़ाइल है।

// हैडर फ़ाइल (हम इसे "ObjCFunc.h" कहते हैं)

#ifndef test2_ObjCFunc_h
#define test2_ObjCFunc_h
@interface myClass :NSObject
-(void)hello:(int)num1;
@end
#endif

// कॉरस्पॉन्डिंग ऑब्जेक्टिव सी फाइल (हम इसे "ओब्जेक्टफंड आदि" कहते हैं)

#import <Foundation/Foundation.h>
#include "ObjCFunc.h"
@implementation myClass
//Your objective c code here....
-(void)hello:(int)num1
{
NSLog(@"Hello!!!!!!");
}
@end

चरण 2

अब हम एक c ++ फंक्शन को कार्यान्वित करेंगे जिसका उद्देश्य हम अभी बनाये गए c फंक्शन को कहते हैं! तो इसके लिए हम एक .mm फ़ाइल और उसकी संबंधित हेडर फ़ाइल को परिभाषित करेंगे ("। Mm" फ़ाइल का उपयोग यहाँ किया जाना है क्योंकि हम फ़ाइल में ऑब्जेक्टिव C और C ++ कोडिंग दोनों का उपयोग कर पाएंगे)

// हैडर फ़ाइल (हम इसे "ObjCCall.h" कहते हैं)

#ifndef __test2__ObjCCall__
#define __test2__ObjCCall__
#include <stdio.h>
class ObjCCall
{
public:
static void objectiveC_Call(); //We define a static method to call the function directly using the class_name
};
#endif /* defined(__test2__ObjCCall__) */

// कॉरस्पॉन्डिंग ऑब्जेक्टिव C ++ फ़ाइल (हम इसे "ObjCCall.mm" कहते हैं)

#include "ObjCCall.h"
#include "ObjCFunc.h"
void ObjCCall::objectiveC_Call()
{
//Objective C code calling.....
myClass *obj=[[myClass alloc]init]; //Allocating the new object for the objective C   class we created
[obj hello:(100)];   //Calling the function we defined
}

चरण 3

C ++ फ़ंक्शन को कॉल करना (जो वास्तव में ऑब्जेक्टिव सी मेथड कहता है)

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include "cocos2d.h"
#include "ObjCCall.h"
class HelloWorld : public cocos2d::Layer
{
public:
// there's no 'id' in cpp, so we recommend returning the class instance pointer
static cocos2d::Scene* createScene();
// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning  'id' in cocos2d-iphone
virtual bool init();
// a selector callback
void menuCloseCallback(cocos2d::Ref* pSender);
void ObCCall();  //definition
// implement the "static create()" method manually
CREATE_FUNC(HelloWorld);
};
#endif // __HELLOWORLD_SCENE_H__

//अंतिम बुलावा

#include "HelloWorldScene.h"
#include "ObjCCall.h"
USING_NS_CC;
Scene* HelloWorld::createScene()
{
// 'scene' is an autorelease object
auto scene = Scene::create();
// 'layer' is an autorelease object
auto layer = HelloWorld::create();
// add layer as a child to scene
scene->addChild(layer);
// return the scene
return scene;
}
// on "init" you need to initialize your instance
bool HelloWorld::init()
{
//////////////////////////////
// 1. super init first
if ( !Layer::init() )
{
    return false;
}
Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();

/////////////////////////////
// 2. add a menu item with "X" image, which is clicked to quit the program
//    you may modify it.

// add a "close" icon to exit the progress. it's an autorelease object
auto closeItem = MenuItemImage::create(
                                       "CloseNormal.png",
                                       "CloseSelected.png",
                                       CC_CALLBACK_1(HelloWorld::menuCloseCallback,  this));

closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,
                            origin.y + closeItem->getContentSize().height/2));

// create menu, it's an autorelease object
auto menu = Menu::create(closeItem, NULL);
menu->setPosition(Vec2::ZERO);
this->addChild(menu, 1);

/////////////////////////////
// 3. add your codes below...

// add a label shows "Hello World"
// create and initialize a label

auto label = Label::createWithTTF("Hello World", "fonts/Marker Felt.ttf", 24);

// position the label on the center of the screen
label->setPosition(Vec2(origin.x + visibleSize.width/2,
                        origin.y + visibleSize.height - label- >getContentSize().height));
// add the label as a child to this layer
this->addChild(label, 1);
// add "HelloWorld" splash screen"
auto sprite = Sprite::create("HelloWorld.png");
// position the sprite on the center of the screen
sprite->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 +     origin.y));
// add the sprite as a child to this layer
this->addChild(sprite, 0);
this->ObCCall();   //first call
return true;
}
void HelloWorld::ObCCall()  //Definition
{
ObjCCall::objectiveC_Call();  //Final Call  
}
void HelloWorld::menuCloseCallback(Ref* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM ==   CC_PLATFORM_WINRT)
MessageBox("You pressed the close button. Windows Store Apps do not implement a close    button.","Alert");
return;
#endif
Director::getInstance()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
}

आशा है कि यह काम करता है!


9

आपको अपनी C ++ फ़ाइल को Objective-C ++ के रूप में माना जाना चाहिए। आप xoo में foo.cpp का नाम बदलकर foo.mm ((.mm obj-c ++ एक्सटेंशन है) कर सकते हैं। फिर जैसा कि दूसरों ने कहा है कि मानक obj-c संदेश सिंटैक्स काम करेगा।


1

कभी-कभी .cpp to .mm का नाम बदलना अच्छा विचार नहीं है, खासकर तब जब प्रोजेक्ट क्रॉसप्लेक्ट हो। इस मामले में xcode प्रोजेक्ट के लिए मैं एक्सकोड प्रोजेक्ट फ़ाइल को TextTdit के माध्यम से खोलता हूं, पाया गया स्ट्रिंग जिसमें रुचि फ़ाइल है, यह होनी चाहिए:

/* OnlineManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OnlineManager.cpp; sourceTree = "<group>"; };

और फिर से फ़ाइल प्रकार बदलने के sourcecode.cpp.cpp को sourcecode.cpp.objcpp

/* OnlineManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = **sourcecode.cpp.objcpp**; path = OnlineManager.cpp; sourceTree = "<group>"; };

यह नाम .cpp से .mm के बराबर है


1

साथ ही, आप विधि को कॉल करने के लिए ऑब्जेक्टिव-सी रनटाइम में कॉल कर सकते हैं।


1

@ ऊपर DawidDrozd का उत्तर उत्कृष्ट है।

मैं एक बिंदु जोड़ूंगा। क्लैग संकलक के हाल के संस्करणों ने अपने कोड का उपयोग करने का प्रयास करने पर "ब्रिजिंग कास्ट" की आवश्यकता के बारे में शिकायत की।

यह उचित प्रतीत होता है: ट्रम्पोलिन का उपयोग करने से एक संभावित बग बन जाता है: चूंकि ऑब्जेक्टिव-सी क्लास को रेफरेंस काउंट किया जाता है, यदि हम उसका पता एक शून्य के रूप में पास करते हैं *, हम एक हैंगिंग पॉइंटर होने का जोखिम उठाते हैं यदि क्लास में कचरा इकट्ठा होता है जबकि कॉलबैक अभी भी है। सक्रिय।

समाधान 1) कोको CFBridgingRetain और CFBridgingRelease मैक्रो फ़ंक्शंस प्रदान करता है, जो उद्देश्य-सी ऑब्जेक्ट के संदर्भ गणना से संभवतः जोड़ते और घटाते हैं। इसलिए हमें कई कॉलबैक के साथ सावधान रहना चाहिए, जितनी बार हम बनाए रखते हैं उतनी ही बार जारी करें।

// C++ Module
#include <functional>

void cppFnRequiringCallback(std::function<void(void)> callback) {
        callback();
}

//Objective-C Module
#import "CppFnRequiringCallback.h"

@interface MyObj : NSObject
- (void) callCppFunction;
- (void) myCallbackFn;
@end

void cppTrampoline(const void *caller) {
        id callerObjC = CFBridgingRelease(caller);
        [callerObjC myCallbackFn];
}

@implementation MyObj
- (void) callCppFunction {
        auto callback = [self]() {
                const void *caller = CFBridgingRetain(self);
                cppTrampoline(caller);
        };
        cppFnRequiringCallback(callback);
}

- (void) myCallbackFn {
    NSLog(@"Received callback.");
}
@end

समाधान 2) विकल्प किसी भी अतिरिक्त सुरक्षा के बिना, एक कमजोर संदर्भ के बराबर का उपयोग करना है।

ऑब्जेक्टिव-सी लैंग्वेज __bridge कास्ट क्वालीफायर प्रदान करती है ऐसा करने के लिए (CFBridgingRetain और CFBridgingRelease क्रमशः ऑब्जेक्टिव-सी लैंग्वेज __bridge_retain और रिलीज़ के ऊपर थिक कोकोआ रैपर लगते हैं, लेकिन कोको __bridge के बराबर नहीं दिखता है)।

आवश्यक परिवर्तन हैं:

void cppTrampoline(void *caller) {
        id callerObjC = (__bridge id)caller;
        [callerObjC myCallbackFn];
}

- (void) callCppFunction {
        auto callback = [self]() {
                void *caller = (__bridge void *)self;
                cppTrampoline(caller);
        };
        cppFunctionRequiringCallback(callback);
}

मुझे यह स्वीकार करना होगा कि मैं इस बारे में कुछ संदिग्ध हूं कि क्या समाधान 1 सभी बनाए रखने / जारी करने के नाटकीयता के बावजूद कोई अतिरिक्त सुरक्षा प्रदान करता है। एक बिंदु यह है कि हम selfक्लोजर में एक कॉपी पास कर रहे हैं , जो पुरानी हो सकती है। दूसरी बात यह है कि इसकी स्पष्टता नहीं है कि यह स्वचालित संदर्भ गणना के साथ कैसे इंटरैक्ट करता है और क्या कंपाइलर यह पता लगा सकता है कि क्या चल रहा है। व्यवहार में, मैंने एक ऐसी स्थिति बनाने का प्रबंधन नहीं किया जहां या तो संस्करण एक साधारण एक-मॉड्यूल खिलौना उदाहरण में विफल रहा।
QuesterZen

-1

आप C ++ को Objectiv-C (ऑब्जेक्टिव C ++) के साथ मिला सकते हैं। अपने उद्देश्य C ++ वर्ग में एक C ++ विधि लिखिए जो आपके C ++ से केवल कॉल [context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer];और कॉल करती है।

मैंने अपने आप से पहले यह कोशिश नहीं की है, लेकिन इसे एक शॉट दें, और हमारे साथ परिणाम साझा करें।


2
लेकिन समस्या यह है कि मैं इसे कैसे कह सकता हूं ... क्योंकि यदि मैं अपनी C ++ कक्षा में "EAGLview.h" शामिल करता हूं तो मुझे हजारों त्रुटियां मिलती हैं।
किशोर जू
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.