我正在创建一个包装器类,它包装了特定第 3 方 API 中概述的一堆函数。当我尝试像这样包装非成员函数时:
(AVTcamDllWrapper.h)
typedef VmbErrorType (WINAPI * AVTGETCAMERAS) (CameraPtrVector cameras);
class CAVTcamDllWrapper
{
HMODULE mAVTCamLibrary; //I later have this point to the DLL
public:
void AVTGetCameras (CameraPtrVector cameras);
};
(AVTcamDllWrapper.cpp)
void CAVTcamDllWrapper::AVTGetCameras(AVTNS CameraPtrVector cameras)
{
AVTGETCAMERAS pFunc = NULL;
pFunc = (AVTGETCAMERAS) GetProcAddress(mAVTCamLibrary, "?GetCameras@VimbaSystem@VmbAPI@AVT@@AEAA?AW4VmbErrorType@@PEAV?$shared_ptr@VCamera@VmbAPI@AVT@@@23@AEAI@Z");
DWORD dw = GetLastError();
if(pFunc == NULL)
{
Exlog(L"CAVTcamDllWrapper::AVTGetCameras: Failed to locate AVTGetCameras method in AVTCamera DLL.");
NIERR_SET_AND_THROW_ERROR(NIERR_CAMERA_ERROR, L"Failed to locate AVTGetCameras method in AVTCamera DLL.");
}
VmbErrorType vErr = pFunc(cameras);
if(vErr != VmbErrorSuccess)
{
wstring exLogMsg = Format(exLogMsg, L"CAVTcamDllWrapper::AVTGetCameras(): Failed to get any cameras. VmbErrorType = %d", vErr);
Exlog(exLogMsg.c_str());
NIERR_SET_AND_THROW_ERROR(NIERR_CAMERA_ERROR, L"Failed to get any cameras.");
}
}
上面的代码对非成员函数非常有效。例如,如果我试图包装一个简单地通过以下语句调用的函数:
CallFunction(blah, blaaaaah);
然后包装类工作正常,pFunc 设置正确,VmbErrorType vErr = pFunc();
行没有错误发生;
但是,我的很多函数都是成员函数,并且是这样调用的:
SomeObject.CallMemberFunction(blah, bleh);
// or
SomeObjectPointer->CallMemberFunction(what, ever);
这些是我似乎无法包装的功能。错误发生在行上:
VmbErrorType vErr = pFunc();
因为如果没有特定的对象来调用该函数,则无法调用该函数。在我的示例中,我包装了一个存在于 Camera 内部的函数 GetCameras。在不包装函数的情况下,为了调用它,我只需创建一个相机指针 vector ,然后执行以下操作:
cameras[0]->GetCameras(VmbAccessModeFull);
哪个有效。但我不知道我将如何包装这个函数,因为对 GetCameras 的调用既依赖于 cameras[0]
并且在没有相机调用它的情况下完全无用。
那么如何像上面显示的那样包装成员函数呢?
编辑 1:
我试图传递对特定对象的引用并执行
VmbErrorType vErr = theObject->pFunc();
但显然这行不通,因为它会考虑在 theObject 中寻找一个名为 pFunc 的函数,该函数不存在。
编辑 2:
我觉得我几乎要修改包装函数以将引用对象作为参数或其他东西传入。所以喜欢而不是常规:
cameras[0]->GetCameras(VmbAccessModeFull);
我将不得不修改一些东西并使我的包装函数看起来像这样:
mWrapperObject->WrappedGetCameras(VmbAccessModeFull, cameras[0]);
这样包装的函数将具有充当成员函数所需的上下文。
最佳答案
要调用成员函数,您手头必须有一个对象。要拥有一个对象,你必须从某个地方得到它。一个良好的小函数可以从它的参数列表中获取东西的唯一地方。
所以你的每个函数显然都必须有一个接收对象的参数。
如果您希望可以从 C 调用包装函数,则不能将类类型作为函数参数。因此,您要么将其声明为 void*
并在内部进行强制转换,要么只是作弊并键入它(仅适用于 C!)struct YourClassName*
(无需定义结构).对于 C++,它仍然应该使用 class 关键字。使用预处理器。
简而言之,
foo->bar(moo, roo)
是花哨的 shmancy C++ 表达方式
FooType_bar(foo, moo, roo)
你应该考虑在实际拼写前者的同时包装后者。
那么调用者如何获取对象呢?您的函数之一可以创建对象(使用 new
)并返回指向它们的指针。另一个可以删除。或者您可以返回指向预分配数组元素的指针。管他呢。基本上,您将用于获取指向对象的指针的方式包装为原始的未包装库的用户。
就是这样。
关于c++ - 如何包装作为成员函数的 DLL 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15071977/