如何将方法指针传递给结构(在C / C ++中)?

时间:2014-04-22 08:20:19

标签: c++ c function pointers

我有一个C ++类,它有一个指针,表示类似这个类的C接口。实际上一切都运行良好,除了一件事:我无法在MyClass构造函数中将方法指针传递给此结构。示例实现如下所示:

//pure C code
typedef int CI_AFunction(CI_Struct*);

typedef struct CI_MyClass //C Interface of MyClass
{
   CI_AFunction* func;
}CI_MyClass;



//C++ code 
class MyClass
{
  private:
      CI_AFunction* _func;
      CI_MyClass* ptrCI_MyClass;

  public:
     MyClass(): _func(**WHAT TO PUT IN HERE TO MAKE IT POINT TO MyFunc?**)
     {
       ptrCI_MyClass= new CI_MyClass;
       ptrCI_MyClass->func=_func;
     }

     int MyFunc(CI_Struct* str)
     {
       // do something
       return 0;
     }

     CI_MyClass* GetCInterface()
     {
        return ptrCI_MyClass;
     }
};


//more or less usage looks somewhat like this:
CI_ptr->func(CI_StructInstancePtr); //in different C file

如何解决这个问题?我不确定这种方法是否可行,但是以这种方式解决即使不优雅也会是最方便的。这个“C接口”只是为了向C代码揭示这一个功能,因此我并不是想制作整个良好的编程实践C API。

编辑:谢谢大家的帮助。你的提示真的让我解决了这个问题。我已经创建了一个单例,对于某事物的经理而言,这不是一个糟糕的方法。现在我有静态功能,一切都很完美。谢谢!

4 个答案:

答案 0 :(得分:1)

typedef int CI_AFunction(CI_Struct*);

此语句不为函数指针创建typedef。如果要为函数指针创建typedef,请使用此格式

typedef int (*CI_AFunction)(CI_Struct*);

答案 1 :(得分:1)

typedef int (MyClass::*ptrType)(CIStruct* str)

现在

ptrType realPtr = &MyClass::MyFunc

即,_func(realPtr)

将realPtr传递给构造函数

答案 2 :(得分:1)

指针不兼容,您可能能够存储指针,但无法调用它 你想要做的是将stdcall转换为thiscall,它们的工作方式不同。 我在这里看到了2种可能的解决方法。

  1. 如果MyFunc标记为static,它的行为与stdcall相同,但是你不能在方法中使用this,而是必须使用CI_Struct* str

    当方法标记为静态时,您可以将其转换为常规c函数

    _func ( (CI_AFunction) &MyClass::MyFunc )
    
  2. 你必须“桥梁”。它们之间。 C接口在某种程度上需要调用一个能够在对象上运行调用的函数(C ++ ish)。 像

    这样的东西
    int adapter( int (MyClass::*pMethod)(CI_Struct*), MyClass *obj )
    {
        return obj->pMethod(obj->GetCInterface()); /* or 3rd param that is the struct */
    }
    
  3. 选项1似乎是您正在寻找的,因为您已经通过了我理解应该包含所有数据的结构。

答案 3 :(得分:1)

常规函数指针只能指向非成员函数或静态成员函数。

如果您的函数不需要访问MyClass的(非静态)成员,那么您可以简单地将其设置为静态(或使其成为非成员)。

如果确实需要,那么你需要一个静态的“trampoline”函数来调用某个对象上的成员函数。如果您可以更改C接口,则可以将对象指针作为额外参数传递:

typedef int CI_AFunction(CI_Struct*, void* user_data);

struct CI_MyClass
{
    CI_AFunction* func;
    void* user_data;
};

定义一个静态(或非成员)函数,将该指针解释为调用成员函数的对象:

int MyFunc_wrapper(CI_Struct* s, void* user_data) {
    static_cast<MyClass*>(user_data)->MyFunc(s);
}

然后提供一个指针来调用它:

ptrCI_MyClass->func=MyFunc_wrapper; // or &MyClass::MyFunc_wrapper for static member
ptrCI_MyClass->user_data = this;

如果您无法更改C接口以将任意用户数据传递给回调,那么您就会陷入困境。您可以将一个或多个全局变量拼凑在一起,以指示要使用哪个MyClass,但它不会很漂亮。