我有一个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。
编辑:谢谢大家的帮助。你的提示真的让我解决了这个问题。我已经创建了一个单例,对于某事物的经理而言,这不是一个糟糕的方法。现在我有静态功能,一切都很完美。谢谢!答案 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种可能的解决方法。
如果MyFunc标记为static
,它的行为与stdcall相同,但是你不能在方法中使用this
,而是必须使用CI_Struct* str
。
当方法标记为静态时,您可以将其转换为常规c函数
_func ( (CI_AFunction) &MyClass::MyFunc )
你必须“桥梁”。它们之间。 C接口在某种程度上需要调用一个能够在对象上运行调用的函数(C ++ ish)。 像
这样的东西int adapter( int (MyClass::*pMethod)(CI_Struct*), MyClass *obj )
{
return obj->pMethod(obj->GetCInterface()); /* or 3rd param that is the struct */
}
选项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
,但它不会很漂亮。