我的问题如下:
我有一个包含这样的函数指针的结构:
typedef void (CALLING_COVNENTION * functionType_t) (/*...*/);
typedef struct myFuncpointerStruc_s
{
/*...*/
functionType_t funcIdentifier;
/*...*/
}myFuncpointerStruc_t;
现在我想为它分配一个完全相同类型的函数指针。
但遗憾的是,dlsym()
正在返回void *
而不是function_poitner_type
所以我的第一次尝试:
functionscope ()
{
myFuncpointerStruc_t structIdentifier;
structIdentifier.funcIdentifier= dlsym (hAndle, "calledName");
}
在警告中结束:
警告:ISO C禁止在函数指针和'void *'
之间进行分配
好吧,这让我感到困惑...... gcc从未对我说过那么严厉。 但好吧让我变得棘手我认为可能会有任何后门保持标准符合。所以我尝试了这个:
functionscope ()
{
myFuncpointerStruc_t structIdentifier;
*(void **) &structIdentifier.funcIdentifier = dlsym (hAndle, "calledName");
}
嗯....显然......
警告:解除引用类型惩罚指针将破坏严格的别名规则
因为我不知道内部会发生什么dlsym()
我不知道我会破坏,因为我返回了一个真正的void *
,它使我的功能别名,或者是一些完全不同的东西,我可以吗?
所以我不知道,现在使用这个函数指针会破坏严格别名规则还是不会呢?
但无论如何:对于我的公司来说,使用compilerflag -fstrict-aliasing
是合法的。
所以这对我来说也不是一个可能的解决方案,即使它符合要求。
所以我试着继续。
我的下一个想法是:如何将char *
dlsym()
版本的functionscope ()
{
myFuncpointerStruc_t structIdentifier;
unsigned char *localTestPtr = ((unsigned char *) dlsym (hAndle, "calledName");
memcpy (g_interfaceSvCheck.pfnPFD_SVCHK_GET_VERSION, localTestPtr, sizeof (localTestPtr));
}
解析为memcopy?
结果:
functionscope ()
{
size_t testIndex;
myFuncpointerStruc_t structIdentifier;
unsigned char *localTestPtr = ((unsigned char *) dlsym (hAndle, "calledName");
for (testIndex = 0; testIndex < sizeof (localTestPtr); testIndex++)
{
((unsigned char *)(structIdentifier.funcIdentifier))[testIndex] = ((unsigned char *)&localTestPtr)[testIndex];
}
}
我现在收到的警告非常具体:
警告:ISO C禁止在函数指针和'void *'之间传递'memcpy'的参数1
所以我的下一个想法是“让我们回到字节”,也许在那里,我会找到一种方法。 (但慢慢地,我的想法已经不多了......)
所以我做了:
functionscope ()
{
size_t testIndex;
myFuncpointerStruc_t structIdentifier;
unsigned char *localTestPtr = ((unsigned char *) dlsym (hAndle, "calledName");
unsigned char * FakeFunctionPointer;
FakeFunctionPointer =
(((unsigned char *)structIdentifier) + offsetof (myFuncpointerStruc_t , funcIdentifier));
for (testIndex = 0; testIndex < sizeof (localTestPtr); testIndex++)
{
FakeFunctionPointer[testIndex] = ((unsigned char *)&localTestPtr)[testIndex];
}
}
这是一个安静的不同警告:
警告:ISO C禁止将函数指针转换为对象指针类型
所以最后我最蠢的尝试是:
offsetoff
即使在这里问题是,void *
的第二个参数也无法转换为-std=c99
,因为它是一个函数指针。
我被困了,不知道怎么走得更远,有人可以帮我找一个解决方案吗?
我只是使用gcc 4.2而不是clang来发出这些警告。
目标C版本为-std=POSIX
,以避免-std=gnu99
和{{1}}
但这个gcc警告听起来并不过时。 我目前在FreeBSD上工作,我真的不知道如何解决这个问题。
答案 0 :(得分:2)
这有点棘手:
#define CALLING_CONVENTION
typedef void (CALLING_CONVENTION * functionType_t) (/*...*/);
typedef struct myFuncpointerStruc_s
{
/*...*/
functionType_t funcIdentifier;
/*...*/
} myFuncpointerStruc_t;
int main()
{
myFuncpointerStruc_t structIdentifier = {0};
{
functionType_t * pfuncIdentifier = &structIdentifier.funcIdentifier;
*(void **) (pfuncIdentifier) = dlsym(handle, "calledName");
}
...
}
上述解决方案只是欺骗编译器。从<{1}}开始,不工作了......: - (
由于确实没有解决方案,唯一的解决方案是冷静编译器。 GNU人员对此表现出了深刻见解并发明了:-O1
我们可以在这里使用它:
__attribute__ ((__may_alias__))
顺便说一下:#define CALLING_CONVENTION
typedef void * __attribute__ ((__may_alias__)) pvoid_may_alias_t;
typedef void (CALLING_CONVENTION * functionType_t) (/*...*/);
typedef struct myFuncpointerStruc_s
{
/*...*/
functionType_t funcIdentifier;
/*...*/
} myFuncpointerStruc_t;
int main()
{
myFuncpointerStruc_t structIdentifier = {0};
*(pvoid_may_alias_t *) (&structIdentifier.funcIdentifier) = dlsym(handle, "calledName");
}
...
}
来自哪里?我只知道ldsym()
。
答案 1 :(得分:0)
使用两种类型转换:
func_type *funptr;
funptr= (func_type *)(intptr_t)dlsym();
如果代码指针和数据指针的大小不相等,类型转换funptr会引起麻烦。