开发者

@selector implementation in C++

I need to implement similar mechanism like @selector(Objecitive-C) in C++. By googling i have found. It does not help me...

template <class AnyClass> 
class ClassCallback
{
    // pointer to member function
    void (AnyClass::*function)(void);

    // pointer to object
    AnyClass object;  
public:

    ClassCallback()     {  }
    ~ClassCallback()    {  }

    ClassCallback(AnyClass _object, void(AnyClass::*_function)(void))
    : object( _object ), function( _function ) { };

开发者_如何学C    virtual void call(){ 
         (object->*function)();
    };

};

Is there any different approach to implement which is similar to objective-C like

typedef struct objc_selector    *MY_SEL;  

Need to implement objc_selector It is abstract class in objective-C. How to implement objc_selector any idea...


Just a few precisions on the Objective-C messaging system, with the selectors.

A selector (SEL) is an opaque type, but it's only something like a char *, containing only the name of the method (so many classes can share the same selector).

An Obj-C method is a struct containing:

  1. A SEL field
  2. A char * containing infos about the return type and arguments.
  3. An IMP field

Something like:

struct objc_method
{
    SEL    method_name;
    char * method_types;
    IMP    method_imp;
};
typedef objc_method Method;

An IMP is just a C function pointer.


Objective-C and C++ are very different languages, and as far as I know C++ doesn't have anything equivalent or even similar to Objective-C's selectors. If you explain the problem you're trying to solve, I'm sure someone here will be happy to discuss the way that problem might be dealt with from a C++ perspective.


If you're happy with using a custom preprocessor before compiling C++ files, you can use Qt's signal and slot mechanism, which is an implementation of message-passing system in a slightly-extended C++. See here.


You might want to do something like this :

// We use something to define what "identifies" a
class selector {
private:
   std::string name;
public:
    selector(std::string const& n) : name(n) {}
    selector(const char* n) : name(n) {}
};
typedef const selector* SEL;

Use it like this :

typedef void* (*method) (object&, ...);
struct object {
private:
   std::hash<SEL,method>* methods;
public:
   object(std::map<SEL,method>* m)  : methods(m) {};
};

selector cloneSelector = selector("clone");
typedef void* cloneImplementation(object&, ...) {
  ....
};

Use it like this :

std::map<SEL,method> fooMethods;
fooMethods[cloneSelector]=&cloneImplementation;

class foo : public object {
public:
  foo()  : object(&fooMethods) {};
};

There are several problems however (typing, function signature …). You probably do not want to do this.

Ohterwise, look at the code. Gobjc is open source, it is quite simple to see how it is done. Looking at objc/deprecated/struct_objc_selector.h of (GNU) gobjc I find:

struct objc_selector
{
  void *sel_id;
  const char *sel_types;
};

AFAIK sel_id is a pointer to a string made of the method name and the (encoded) argument types.

You might want to group methods in interfaces and have a slightly more "COM-ish" way of doing it :

 struct interface_id {};

 class object {
 protected:
    virtual void* getVtable_(interface_id const&) = 0;
 public:
    template<class X> X* getVtable() {
        return getVtable(X::interface_id);
    }
    virtual ~object();
 };

 // Exemple interface

 struct FooInterface {
 public:
   class vtable {
     void (*fooMethod2)(void* self, int n);
     std::vector<int> (*fooMethod2)(void* self, double x);
   };
   static interface_id ID;
   static std::string NAME; // = "FooInterface"
 private:
    void* self;
    FooVtable* vtable;
 public:
    void fooMethod1(int n) {
      return vtable->fooMethod1(self,n);
    };
    void fooMethod2(double x) {
      return vtable->fooMethod2(self,double x);
    };
 };

// Exemple object

class foo_object : public bar_object {
private:
   static std::map<interface_id, void*> INTERFACES;
public:
   virtual void* getVtable_(interface_id const& id) {
     void* res = INTERFACES[&id];
     if(res!=null)
        return res;
     else
        return bar_object::getVtable(id);
   };
};

It gives an an idea of how to enforce function signatures. You should be able to use the same kind of thing for the selector-based approach (using some boring template-meta-programming code …).


I had a similar problem when using Cocos2d-x, and in my case I used callfunc_selector to get the selector:

Suppose a class Foo and a method Bar() inside it, just call callfunc_selector(Foo::Bar); and it will return a CCObject* to the method.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜