সি ++ সদস্য ফাংশন থেকে উদ্দেশ্যমূলক-সি পদ্ধতি কল করা হচ্ছে?


111

আমার একটি ক্লাস রয়েছে ( EAGLView) যা কোনও C++ক্লাসের সদস্য ফাংশনটিকে সমস্যা ছাড়াই কল করে । এখন, সমস্যাটি হ'ল আমাকে সেই C++ক্লাসে এমন একটি কল করা দরকার objective-C function [context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer];যা আমি C++সিনট্যাক্সে করতে পারি না ।

আমি এই Objective-Cকলটি একই Objective-Cক্লাসে C++গুটিয়ে রাখতে পারি যা প্রথমে সি ++ ক্লাস নামে পরিচিত, তবে তার পরে আমাকে কোনও পদ্ধতিতে সেই পদ্ধতিটি কল করা দরকার এবং এটি কীভাবে করব তা আমি বুঝতে পারি না।

আমি EAGLViewসি ++ সদস্য ফাংশনে আপত্তি জানাতে একটি পয়েন্টার দেওয়ার চেষ্টা করেছি EAGLView.hএবং আমার C++শ্রেণির শিরোনামে " " অন্তর্ভুক্ত করেছি কিন্তু আমি 3999 ত্রুটি পেয়েছি ..

সুতরাং .. আমি এই কিভাবে করা উচিত? একটি উদাহরণ সুন্দর হবে .. আমি কেবল এটি করার বিশুদ্ধ Cউদাহরণ পেয়েছি ।

উত্তর:


204

আপনি যদি সাবধানে এটি করেন তবে আপনি সি ++ অবজেক্টিভ-সি এর সাথে মিশতে পারেন। কয়েকটি ক্যাভেট রয়েছে তবে সাধারণভাবে বলতে গেলে এগুলি মিশ্রিত হতে পারে। আপনি যদি এগুলি আলাদা রাখতে চান তবে আপনি একটি স্ট্যান্ডার্ড সি র‍্যাপার ফাংশন সেটআপ করতে পারেন যা অবজেক্টিভ সি-অবজেক্টটিকে অ-অবজেক্টিভ-সি কোড থেকে ব্যবহারযোগ্য সি-স্টাইল ইন্টারফেস দেয় (আপনার ফাইলগুলির জন্য আরও ভাল নাম বাছাই করুন, আমি এই নামগুলি বেছে নিয়েছি) ভার্বোসিটির জন্য):

MyObject-সি-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উদ্দেশ্য সি বর্গ হিসাবে ফাইল কিন্তু যে ফাইলটি তাতে কোন অস্তিত্ব নেই চাহিদা উদ্দেশ্য সি কোড হিসেবে সংকলিত করা । মোড়ক ফাংশন ঘোষণা করে এমন শিরোনাম সিপিপি এবং অবজেক্টিভ-সি কোড উভয়ই অন্তর্ভুক্ত করা দরকার।

(দ্রষ্টব্য: যদি উদ্দেশ্য-সি বাস্তবায়ন ফাইলটিকে ".m" এক্সটেনশন দেওয়া হয় তবে এটি এক্সকোডের অধীনে লিঙ্ক করবে না। "। মিমি" এক্সটেনশানটি এক্সকোডকে অবজেক্টিভ-সি এবং সি ++ এর সংমিশ্রণ আশা করতে বলেছে, অবজেক্টিভ-সি ++)। )


আপনি পিআইএমপিএল আইডিয়ামটি ব্যবহার করে উপরের বিষয়টিকে একটি অবজেক্ট-ওরিয়েন্টেন্ট পদ্ধতিতে প্রয়োগ করতে পারেন । বাস্তবায়নটি কিছুটা আলাদা। সংক্ষেপে, আপনি মাইক্লাসের একটি উদাহরণে (প্রাইভেট) শূন্য পয়েন্টার সহ একটি শ্রেণীর ভিতরে মোড়ক ফাংশন ("মাইবজেক্ট-সি-ইন্টারফেস। H" এ ঘোষণা করেছেন) স্থাপন করেন।

মায়োবজেক্ট-সি-ইন্টারফেস। (পিআইএমপিএল)

#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

লক্ষ্য করুন যে মোড়কের পদ্ধতিগুলির জন্য আর মাই ক্লাসের উদাহরণের জন্য শূন্য পয়েন্টার প্রয়োজন হয় না; এটি এখন মাইক্লাসআইএমপিএলের ব্যক্তিগত সদস্য। Init পদ্ধতিটি মাইক্লাস উদাহরণটি ইনস্ট্যান্ট করতে ব্যবহৃত হয়;

MyObject.h (পিআইএমপিএল)

#import "MyObject-C-Interface.h"

@interface MyObject : NSObject
{
    int someVar;
}

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

@end

মায়োবজেক্ট.এমএম (পিআইএমপিএল)

#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

লক্ষ্য করুন যে মাইক্লাস মাইক্লাসআইএমপিএল :: init এ একটি কল দিয়ে ইনস্ট্যান্টেশনযুক্ত। আপনি মাইক্লাসআইএমপিএল এর কনস্ট্রাক্টরে মাইক্লাস ইনস্ট্যান্ট করতে পারেন, তবে এটি সাধারণত ভাল ধারণা নয়। মাই ক্লাস উদাহরণটি মাইক্লাসআইএমপিএল এর ডেস্ট্রাক্টর থেকে ধ্বংস করা হয়েছে। সি-স্টাইল প্রয়োগের মতো, মোড়কের পদ্ধতিগুলি মাইক্লাসের সম্পর্কিত পদ্ধতিগুলিতে কেবল মুলতবি করে।

MyCPPClass.h (পিআইএমপিএল)

#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 (পিআইএমপিএল)

#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." );
    }
}

আপনি এখন মাইক্লাসআইএমপিএলের ব্যক্তিগত প্রয়োগের মাধ্যমে মাই ক্লাসে কলগুলি অ্যাক্সেস করতে পারেন। আপনি যদি কোনও বহনযোগ্য অ্যাপ্লিকেশন বিকাশ করছিলেন তবে এই পদ্ধতির সুবিধাজনক হতে পারে; আপনি অন্য প্ল্যাটফর্মের সাথে নির্দিষ্ট একটি দিয়ে মাইক্লাসের প্রয়োগটি খুব সহজেই বদলাতে পারেন ... তবে সত্যি বলতে কী, এটি আরও ভাল বাস্তবায়ন কিনা আরও স্বাদ এবং প্রয়োজনের বিষয়।


6
হাই, আমি এটি চেষ্টা করেছি কিন্তু প্রতীক (গুলি) পাওয়া যায়নি বলে লিংকেজ ত্রুটি পেয়েছি। যেমন এটি মাইবজেক্টডোসোমথিংথথ সহ খুঁজে পাচ্ছে না। কোন ধারনা?

3
আপনি যোগ করতে হবে পারে extern "C"আগেint MyObjectDoSomethingWith
dreamlax

2
ইতিমধ্যে চেষ্টা করা হয়েছে, এটি কাজ করে না এবং এটি বোধগম্য কারণ বাহ্যিক "সি" ব্যবহার করা হয় যখন আমরা সি থেকে সি ++ ফাংশন কল করতে চাই, এই ক্ষেত্রে আমরা সি ++ থেকে কোনও সি ফাংশন কল করছি, না?

6
এছাড়াও, কীভাবে উদ্দেশ্যকোবজেক্টটি MyCPPClass.cpp এ ইনস্ট্যান্টেটেড হয়?
রাফি খাচ্চডৌরিয়ান

2
অদ্ভুত @ ড্রিমলাক্স, এটি এখন সংকলন করছে তবে আমি "সামথমেডোদ" কল করতে জানি না। কোনটি প্যারামিটার যুক্ত করা উচিত যা যুক্ত করতে হবে: int মাইসিপিসিপি ক্লাস :: কিছু ম্যাথোদ (শূন্য * উদ্দেশ্যকোবজেক্ট, অকার্য * * একটি প্যারামিটার) ???
the_ মুন

15

আপনি আপনার কোডটি অবজেক্টিভ-সি ++ হিসাবে সংকলন করতে পারেন - সবচেয়ে সহজ উপায় হল আপনার .cpp এর নাম পরিবর্তন .mm। এটি যথাযথভাবে সংকলন করবে যদি আপনি অন্তর্ভুক্ত করেন EAGLView.h(আপনি এতগুলি ত্রুটি পেয়েছিলেন কারণ সি ++ সংকলকটি উদ্দেশ্য-সি নির্দিষ্ট কীওয়ার্ডগুলির কোনও বুঝতে পারে না) এবং আপনি (বেশিরভাগ অংশে) উদ্দেশ্য-সি এবং সি ++ মিশ্রিত করতে পারেন মত।


আপনি কি এই সি ++ ফাইলে সেই সমস্ত সংকলক ত্রুটি পেয়ে যাচ্ছেন বা অন্য কোনও সি ++ ফাইলের মধ্যে রয়েছে যা এই সি ++ শিরোলেখ অন্তর্ভুক্ত করে?
জেসি বেডার

মনে হচ্ছে আমি সি ++ শিরোলেখ ফাইলটিতে EAGLView.h অন্তর্ভুক্ত করতে পারি না কারণ এরপরে এটি কোনও কারণে প্রত্যাশা করে যে উদ্দেশ্য উদ্দেশ্য সিটি সি ++, এবং @ + অন্যান্য চিহ্নগুলি বুঝতে পারে না
জুনিয়ন

12

সহজ সমাধান হ'ল এক্সকোডকে সবকিছুকে উদ্দেশ্য সি ++ হিসাবে সংকলন করতে বলা tell

উদ্দেশ্য প্রকল্প হিসাবে সিগন্যাল সোর্সগুলির জন্য আপনার প্রকল্প বা লক্ষ্য সেটিংস সেট করুন এবং পুনরায় কম্পাইল করুন।

তারপরে আপনি সর্বত্র সি ++ বা উদ্দেশ্য সি ব্যবহার করতে পারেন, উদাহরণস্বরূপ:

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

এটি আপনার সমস্ত উত্স ফাইলগুলি .cpp বা .m থেকে .mm থেকে নাম পরিবর্তন করার মতোই প্রভাব ফেলে affect

এর দুটি ছোট ছোট ডাউনসাইড রয়েছে: ঝনঝন সি ++ উত্স কোড বিশ্লেষণ করতে পারে না; কিছু অপেক্ষাকৃত অদ্ভুত সি কোড সি ++ এর অধীনে সংকলন করে না।


আমি কেবল কিছুটা কৌতূহলী, যখন আপনি উদ্দেশ্য-সি ++ হিসাবে সবকিছু সংকলন করেন আপনি কি সি-স্টাইলের ক্যাসেট এবং / অথবা অন্যান্য সি ++ ব্যবহারের বিষয়ে সতর্কতা পেয়েছেন - বৈধ সি-স্টাইল কোড সম্পর্কে নির্দিষ্ট সতর্কতা?
ড্রিমলাক্স

অবশ্যই, আপনি সি ++ এ প্রোগ্রামিং করছেন তাই আপনার কাছ থেকে যথাযথ আচরণ করার প্রত্যাশা করা হবে - তবে সাধারণ নিয়ম হিসাবে, আপনি কখনও ক্লাস তৈরি না করলেও সি ++ সি এর চেয়ে ভাল সি। এটি আপনাকে বোকা জিনিস করতে দেয় না এবং এটি আপনাকে সুন্দর জিনিসগুলি করতে দেয় (যেমন ভাল ধ্রুবক এবং এনামগুলি এবং এ জাতীয়)। আপনি এখনও ঠিক একই (যেমন (সিএফফ্লোট) এক্স) কাস্ট করতে পারেন।
পিটার এন লুইস

10

ধাপ 1

একটি উদ্দেশ্য সি ফাইল (.m ফাইল) তৈরি করুন এবং এটি সম্পর্কিত শিরোনাম ফাইল।

// শিরোনাম ফাইল (আমরা এটিকে "ObjCFunc.h" বলি)

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

// সম্পর্কিত উদ্দেশ্য সি ফাইল (আমরা এটিকে "ObjCFunc.m" বলি)

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

ধাপ ২

এখন আমরা স্রেফ তৈরি করা অবজেক্টিভ সি ফাংশনটি কল করতে একটি সি ++ ফাংশন বাস্তবায়ন করব! সুতরাং এর জন্য আমরা একটি। মিমি ফাইল এবং এর সাথে সম্পর্কিত শিরোনাম ফাইলটি সংজ্ঞায়িত করব ("। মিমি" ফাইলটি এখানে ব্যবহার করতে হবে কারণ আমরা ফাইলটিতে উদ্দেশ্য সি এবং সি ++ কোডিং উভয়ই ব্যবহার করতে সক্ষম হব)

// শিরোনাম ফাইল (আমরা এটিকে "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__) */

// সম্পর্কিত উদ্দেশ্য সি ++ ফাইল (আমরা এটিকে "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

সি ++ ফাংশন কল করা (যা আসলে উদ্দেশ্য সি পদ্ধতিতে কল করে)

#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

আপনাকে আপনার সি ++ ফাইলটিকে উদ্দেশ্য-সি ++ হিসাবে বিবেচনা করা দরকার। আপনি xoo কোড এ foo.cpp এর নাম পরিবর্তন করে foo.mm করতে পারেন (। মিমি অবজেক্ট-সি ++ এক্সটেনশন)। তারপরে অন্যরা যেমন বলেছে স্ট্যান্ডার্ড অজেক্ট-সি মেসেজিং সিনট্যাক্স কাজ করবে।


1

কখনও কখনও .cpp। .Mm এর নাম পরিবর্তন করা ভাল ধারণা নয়, বিশেষত যখন প্রকল্পটি ক্রসপ্ল্যাটফর্ম হয়। এক্সকোড প্রকল্পের ক্ষেত্রে আমি টেক্সটএডিটের মাধ্যমে এক্সকোড প্রকল্প ফাইলটি খুলি, স্ট্রিংটি পাওয়া যায় যা সামগ্রীগুলির আগ্রহের ফাইলের মতো, এটির মতো হওয়া উচিত:

/* 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

@ দাভিডড্রজডের উপরের উত্তরটি দুর্দান্ত।

আমি একটি পয়েন্ট যোগ করতে হবে। ক্ল্যাং সংকলকের সাম্প্রতিক সংস্করণগুলি যদি তার কোডটি ব্যবহার করার চেষ্টা করে তবে একটি "ব্রিজিং কাস্ট" লাগানোর বিষয়ে অভিযোগ করে।

এটি যুক্তিসঙ্গত বলে মনে হচ্ছে: ট্রামপোলিন ব্যবহার করে একটি সম্ভাব্য ত্রুটি তৈরি হয়: যেহেতু উদ্দেশ্য-সি ক্লাসগুলি রেফারেন্স গণনা করা হয়, যদি আমরা তাদের ঠিকানাটি অকার্যকর * হিসাবে পাস করি তবে ক্লাসব্যাকটি এখনও ক্লাসব্যাক সংগ্রহের সময় ক্লাস আবর্জনা সংগ্রহ করা থাকলে আমাদের ঝুলন্ত পয়েন্টার থাকার ঝুঁকি রয়েছে risk সক্রিয়।

সমাধান 1) কোকো সিএফবিড্রিজিং রিটেন এবং সিএফবিড্রিজিং রিলেজ ম্যাক্রো ফাংশন সরবরাহ করে যা সম্ভবত উদ্দেশ্য ও সি অবজেক্টের রেফারেন্স গণনা থেকে একটি যুক্ত এবং বিয়োগ করে। সুতরাং আমাদের একাধিক কলব্যাকের সাথে সাবধান হওয়া উচিত, আমরা যতটা সময় ধরে রেখেছি তেমন সংখ্যক সময় মুক্তি দিতে।

// 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) বিকল্পটি হ'ল কোনও অতিরিক্ত সুরক্ষা ছাড়াই দুর্বল রেফারেন্সের সমতুল্য (যেমন ধরে রাখার গণিতে কোনও পরিবর্তন করা হয়নি) ব্যবহার করা।

অবজেক্টিভ-সি ভাষা এটি করার জন্য __ ব্রিজের castালাই বাছাইয়ের যোগ্যতা সরবরাহ করে (সিএফবিড্রিজিং রিটেন এবং সিএফব্রিডিং রিলিজ মনে হয় যথাক্রমে অবজেক্টি-সি ভাষার রচনাগুলি __bridge_retained এবং রিলিজ হয়েছে, তবে কোকো __ব্রীজের সমতুল্য বলে মনে হয় না)।

প্রয়োজনীয় পরিবর্তনগুলি হ'ল:

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বন্ধের অনুলিপিটি যাচ্ছি , যা পুরানো হয়ে যেতে পারে। অন্যটি বিষয় হ'ল এটি কীভাবে স্বয়ংক্রিয় রেফারেন্স গণনার সাথে ইন্টারঅ্যাক্ট করে তা পরিষ্কার নয় এবং সংকলকটি কী চলছে তা নির্ধারণ করতে পারে কিনা। অনুশীলনে আমি এমন পরিস্থিতি তৈরি করতে পরিচালনা করি নি যেখানে দুটি সংস্করণ সাধারণ এক-মডিউল খেলনার উদাহরণে ব্যর্থ হয়েছিল failed
কয়েস্টারজেন

-1

আপনি ওজেক্টিভ-সি (উদ্দেশ্য সি ++) এর সাথে সি ++ মিশিয়ে নিতে পারেন mix আপনার উদ্দেশ্য সি ++ শ্রেণিতে একটি সি ++ পদ্ধতি লিখুন যা কেবল [context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer];আপনার সি ++ থেকে কল করে এবং কল করে and

আমি এটি আমার নিজের আগে চেষ্টা করে দেখিনি, তবে একটি শট দিন এবং ফলাফলগুলি আমাদের সাথে ভাগ করুন।


2
তবে সমস্যাটি হ'ল আমি কীভাবে এটি কল করতে পারি ... কারণ যদি আমি আমার সি ++ শ্রেণিতে "EAGLview.h" অন্তর্ভুক্ত করি তবে আমি কয়েক হাজার ত্রুটি পাই।
কিশোর
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.