C ++,将函数指针参数转换

3
我将尝试编写一个C++程序,包括一个头文件和一个cpp文件,并且我正在使用SimConnect dll。假设我有一个名为“MyClass”的类,其中包含一些函数。在我的某个函数内部,我调用了这个SimConnect函数:
SIMCONNECTAPI SimConnect_CallDispatch(HANDLE hSimConnect, DispatchProc pfcnDispatch, void * pContext);

另外,我写了这个函数:

void __stdcall MyClass::myDispatchProc(SIMCONNECT_RECV* pData, DWORD cbData, void *pContext)

据我所理解,我应该将这个函数作为第二个参数发送给我之前提到的SimConnect函数SimConnect_CallDispatch
我阅读了SimConnect SDK中附带的一个示例,他们正在做与我相同的事情,但是我遇到了错误,而他们没有。唯一不同的是,他们把整个代码写在一个页面中,而我试图将代码分成头文件和主体。
当我尝试按照上述方法编写时,写入以下内容:
SimConnect_CallDispatch(hSimConnect, myDispatchProc, NULL);

我收到了这个错误(编译器在myDispatchProc部分出现了问题):

argument of type "void (__stdcall TransmitData::*)(SIMCONNECT_RECV *pData, DWORD cbData, void *pContext)" is incompatible with parameter of type "DispatchProc"

很明显,这是一个类似于类型转换的错误。正如我所说,如果我没有将程序拆分为两个单独的文件,这段代码本来可以正常工作的。现在为什么它不起作用呢?


1
什么是 DispatchProc - melpomene
7
指向成员函数的指针并不是指向普通函数的指针。你不能将成员函数传递给期望接受C风格函数指针的C风格接口。 - Pete Becker
@daragua..或者一个静态函数也可以。 - london-deveoper
@ccpgh - 从技术上讲,不行;静态成员函数具有C++链接,而C代码需要C链接。但在实践中,这是可行的。 - Pete Becker
谢谢大家,我会试一试! - Nir
显示剩余4条评论
1个回答

1

注意:此问题针对用于Microsoft Flight Simulator 2020的SimConnect SDK

虽然这个问题不是最近的问题,但我会提供一个参考,以防其他人遇到类似情况。

SimConnect_CallDispatch函数需要一个与特定接口相符的静态回调函数的引用,即(SIMCONNECT_RECV* pData, DWORD cbData, void* pContext)

静态函数的特性是它不能访问实例的变量。为了解决这个问题,所有的示例都不涉及.h和.cpp文件的复杂性,而是将所有内容放在一个文件中。

假设我有一个名为"MyClass"的类,有单独的.h和.cpp文件。以下是我解决这个问题的方法:

1. 在头文件中定义静态回调函数

在.h文件中定义SimConnect的默认/标准静态回调函数,例如:

void static CALLBACK MyDispatchProcRD(SIMCONNECT_RECV *pData, DWORD cbData, void *pContext);
2. 在头文件中定义自定义实例函数

为了处理回调的实际实例而不是通过静态函数,可以在.h文件中定义一个自定义实例函数,例如:

void DispatchProc(SIMCONNECT_RECV* pData, DWORD cbData);
3.在Cpp文件中实现静态实例函数

通常在这里你会实现所有的SimConnect回调处理,但在本例中,我们只是将上下文引用强制转换为您的类,并传递给我们的自定义实例函数以进行进一步处理,例如。

void CALLBACK MyClass::MyDispatchProcRD(SIMCONNECT_RECV* pData, DWORD cbData, void* pContext) {
    MyClass* procThis = reinterpret_cast<MyClass*>(pContext);
    procThis->DispatchProc(pData, cbData); 
}
4. 在Cpp文件中实现自定义实例函数

这是你将要实现所有SimConnect处理的地方。由于这是一个实例函数,你可以访问实例的变量。

void MyClass::DispatchProc(SIMCONNECT_RECV* pData, DWORD cbData) {
    switch (pData->dwID) {
    
    case SIMCONNECT_RECV_ID_SIMOBJECT_DATA: {
        SIMCONNECT_RECV_SIMOBJECT_DATA* pObjData = (SIMCONNECT_RECV_SIMOBJECT_DATA*)pData;
        ...
5. 调用静态函数

只需记住在调用SimConnect分发时,将实例的引用(即this)传递给它。

SimConnect_CallDispatch(hSimConnect, MyDispatchProcRD, this);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接