2

我的问题如下:

我有一个包含这样的函数指针的结构:

typedef void (CALLING_COVNENTION * functionType_t) (/*...*/);

typedef struct myFuncpointerStruc_s
{
    /*...*/
    functionType_t funcIdentifier;
    /*...*/
}myFuncpointerStruc_t;

现在我想为它分配一个正是该类型的函数指针。但可悲dlsym()的是返回 avoid *而不是类似的东西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()成 memcopy 怎么样?

结果:

functionscope ()
{
    myFuncpointerStruc_t structIdentifier;

    unsigned char *localTestPtr = ((unsigned char *) dlsym (hAndle, "calledName");  

    memcpy (g_interfaceSvCheck.pfnPFD_SVCHK_GET_VERSION, localTestPtr, sizeof (localTestPtr));
}

我现在收到的警告再次非常具体:

警告:ISO C 禁止在函数指针和 'void *' 之间传递 'memcpy' 的参数 1

所以我的下一个想法是“让我们回到字节”也许我会找到一种方法。(但慢慢地我的想法已经用完了......)

所以我做了:

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 禁止将函数指针转换为对象指针类型

所以最后我最奇怪的尝试是:

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];
    }
}

甚至这里的问题是,它offsetoff的第二个参数不能被转换为,void *因为它是一个函数指针。

我被卡住了,不知道如何走得更远,有人可以帮我找到解决方案吗?

我只是使用gcc 4.2而不是clang来得到这些警告。

目标 C 版本是-std=c99为了避免 is-std=POSIX-std=gnu99

但是这个 gcc 警告对我来说听起来并不过时。我目前正在使用 FreeBSD,我真的不知道如何解决这个问题。

4

2 回答 2

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");
  }

  ...
}

上面的解决方案只是编译器的技巧。不再起作用了... :-(-O1


由于确实没有解决方案,唯一的解决方案是让编译器冷静下来。GNU 人对此表现出了洞察力并发明了:__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()从哪里来?我只知道dlsym()

于 2013-10-01T13:10:00.953 回答
0

使用两种类型转换:

func_type *funptr;
funptr= (func_type *)(intptr_t)dlsym();

如果代码指针和数据指针的大小不相等,类型转换 funptr 将导致麻烦。

于 2016-08-28T16:49:58.237 回答