Извикване на обективен c метод с помощта на указател на функция от c++ метод

Имам c++ клас, който трябва да извика обективен c метод, използвайки указател към този метод. Този метод връща void и приема аргумент от тип 'status', където status е просто интегрално изброяване.

 enum status
 {
       status_valid = 0,
       status_invalid,
       status_unknown
 };

Имам указателя към метода obj-c, настроен така. Указателят към метода също се предава на класа c++ и

typedef void (*FuncPtr) (status);
FuncPtr myObjCSelectorPointer = (void (*)(status))[self methodForSelector:@selector(statusChanged: )];
cppClassInstance->setFuncPointer(myObjCSelectorPointer)

myObjCSelectorPointer се задържа от cppClass по този начин:

void cppClass::setFuncPointer(FunctPtr *ptr)
{
     this->funcPtr = ptr;
}

Сега някъде другаде, когато се опитам да извикам метода, към който сочи този указател, като това:

status s;
funcPtr(s);

Методът се извиква правилно, но стойността, предадена в метода, се губи. Методът obj-c получава напълно произволна стойност. Когато се опитам да извикам метод в класа cpp по същия начин, той преминава и получава правилната стойност.

какво правя грешно Не можеш ли да извикаш обективен c метод по този начин?


person halfwaythru    schedule 14.05.2013    source източник
comment
Публикувайте дефиницията на състоянието, предполагам, но опитайте да предадете състоянието чрез препратка   -  person makc    schedule 14.05.2013
comment
Добавих дефиницията на състоянието към публикацията. Освен това се опитах да го предам чрез препратка, но и това не проработи. И аз имах същия проблем с това.   -  person halfwaythru    schedule 14.05.2013
comment
@halfwaythru Прототипът на вашата функция е грешен - вижте отговора ми.   -  person    schedule 14.05.2013


Отговори (1)


Проблемът е, че функционалният подпис на методите на Objective-C не е толкова прост, колкото си мислите.

За да бъде възможно обектно-ориентираното програмиране, методите на Objective-C приемат два неявни аргумента: id self, SEL _cmd, извикващият обект и изпратеният селектор - те трябва да бъдат предадени. Ще трябва да получите обект, на който да извикате метода, и трябва да съхраните и селектора. След това променете дефиницията на вашия тип функция на правилната:

typedef void (*FuncPtr) (id, SEL, status);

За четене: [1], [2] (близо до частта typedef id (*IMP)(id, SEL, ...))

person Community    schedule 14.05.2013
comment
Това звучи полезно, но две неща: 1.) Ако прототипът на функцията е неправилен, тогава не трябва ли да доведе до това, че функцията не се извиква? Моят obj-c метод се извиква добре с този прототип. 2.) Когато се опитвам да променя прототипа на функцията ptr, трябва да го включа в C++ хедър, където 'id' е недеклариран идентификатор. Как да го заобиколя? - person halfwaythru; 14.05.2013
comment
@halfwaythru 1. Защо трябва да доведе до това, че функцията не се извиква? Инструкцията CALL се излъчва от компилатора съвсем добре... 2. Компилирайте като Objective-C++. - person ; 14.05.2013
comment
@halfwaythru 1) не. той все още ще бъде извикан и може да доведе до недефинирано поведение. 2) времето за изпълнение на objc е C -- #include <objc/objc.h> или както H2CO3 каза малко по-рано, можете също да го компилирате като objc++. - person justin; 14.05.2013
comment
@justin (и дори не споменах случая с функциите fpret и stret, където конвенцията за извикване е отново нещо друго... Имам ‹3 несъответствия...) - person ; 14.05.2013
comment
@H2CO3 да. лично аз просто бих компилирал този файл като objc++ и бих оставил компилатора да свърши работата вместо мен. - person justin; 14.05.2013
comment
Така че направих малка структура с обекта, селектора и указателя и го предадох на класа cpp вместо само указателя. И това работи чудесно! Благодаря ти.! - person halfwaythru; 14.05.2013
comment
@halfwaythru Няма за какво - не забравяйте да проучите малко времето за изпълнение на Objective-C, ще бъде много полезно. - person ; 14.05.2013
comment
Още нещо обаче, моят cpp файл вече е .mm. Това е заглавният файл за класа cpp, който не разпознава идентификатора. Как да компилирам конкретен заглавен файл като goal-c++? Освен това моите файлове са част от много по-голям проект, който вече има много смесен objc/cpp код. - person halfwaythru; 14.05.2013
comment
@halfwaythru Винаги можете да предадете на компилатора флага -x obj-c++, за да компилира изрично като Objective-C++. Този аргумент работи както за GCC, така и за Clang. - person ; 14.05.2013
comment
Благодаря много! Аз наистина го оценявам! - person halfwaythru; 14.05.2013
comment
@halfwaythru: Заглавните файлове не се компилират. Изходните файлове се компилират и могат да включват заглавни файлове. Ако вашият заглавен файл има C++ неща, тогава ВСИЧКИ изходни файлове, които го включват, също трябва да бъдат Objective-C++ изходни файлове. Ето защо трябва да избягвате C++ в заглавните файлове, доколкото е възможно. - person newacct; 15.05.2013