我读了一段标题代码,我在下面找到了:
#include <dlfcn.h>
#define OBJPTR(X) void* X##Ptr ; \
void* (*X##ObjPtr)() ;
void * CreateObj(void * handler, char* LibName, char* FunctionName);
//...
OBJPTR(DB);
//...
DBObjPtr = CreateObj(DBPtr, "DBTransaction", "Function1");
if ((unsigned long)(DBObjPtr)(csPara1, csPara2) != PD_FOUND)
{
//...
首先,我不明白头文件中定义行的含义。 (为什么定义行中有X ##?它是什么意思?)
其次,在c文件对象中创建而不是直接调用函数。我认为这种设计的目的是为了便于维护和解决方案构建/交付,在对象之间进行隔离;如果我是正确的,或者来自不同开发人员的代码加密。但还有什么?或者这种设计模式是什么样的?
答案 0 :(得分:1)
##
是预处理器的(!)连接。在给定的情况下,使用宏创建两个变量:
OBJPTR(DB);
将解决:
void* DBPtr;
void* (*DBObjPtr)();
实际上,我们在这里找到的并不是有效的C ++(这是你标记的问题):
void* (*DBObjPtr)()
声明一个接受 no 参数的函数指针,但稍后会用其中两个参数调用它。此代码仅在C中有效(void* (*DBObjPtr)()
声明一个函数指针,其中参数列表未定义;无参数函数需要显式void
作为参数:void* (*x)(void)
!),以及C允许从指针隐式转换为void到其他指针类型。
意图可能在C中提供某种多态性:
DBObjPtr = CreateObj
(
// probably used as some kind of handle; as not being passed
// as pointer to pointer, the function cannot re-assign, but
// only use it; so I assume that is has been initialized at
// some point before this function call...
DBPtr,
// some kind of identifier from where to load a function from for
// later use; as the parameter is called "library", it might load
// the address of a function within a SO (*nix) or DLL (windows)
"DBTransaction",
// the name of the function to load
"Function1"
);
在C ++中,你可能会以不同的方式处理它:
class Loader;
Loader* db = createLoader(); // initialization lacking in your sample code;
// alternatively (and probably better!) via constructor
void* (*fptr)(int, int) = db->createObj("L", "F");
这还没有奏效,我们还需要应用一些改变。首先,我们需要更改函数的返回类型,它必须返回一个接受任意参数的函数指针。您可以让它返回任意参数(通过省略号)或只是有一个空参数列表 - 无所谓,您将不得不转换结果(除非使用第二个变量并且加载的函数实际上不接受任何参数。 ..)。但是从C ++ 11开始,有一种更优雅的方式可以实现这些功能,该功能可以实现为可变参数模板功能:
class Loader
{
public:
template <typename ... TT>
auto createObj(char const*, char const*) -> void*(*)(TT ...);
};
然后将演员隐藏在该函数中,你可以简单地将其用作:
auto f = loader->createObj<int, int>("L", "F");
// ^ yeah, let's profit from C++11 again...
只是因为你好奇:前C ++ 11方式:
class Loader
{
public:
void* (*createObj())(...);
// function returning function pointer - ugly syntax, I know
// (a typedef for the function pointer makes reading a little easier...)
};
void*(*f)(int, int) = reinterpret_cast<void*(*)(int, int)>(create());
原始宏的最后一个注释:我个人不会使用它,即使在C中也是如此!它似乎对于懒惰的看起来很好,但实际上只是混淆了变量的声明,并且另外产生了更少类型安全的函数指针。所以我会自己声明变量:
void* db /*= ...*/ ;
void* (*f)(int, int) = createObj(db, "L", "F");
// ^ ^ already with correct parameter list