gpt4 book ai didi

c++ - 当我将 void 指针导入到具有指向共享对象中函数的指针的结构时,我没有收到警告

转载 作者:可可西里 更新时间:2023-11-01 18:33:25 27 4
gpt4 key购买 nike

昨天我正在研究共享对象的动态加载和获取函数指针。

我多次被告知,通过 void 指针共享指向函数的指针是 ISO C++ 标准禁止的,并且仍然是一个有待解决的问题。

看完Johan Petterson’s artitle “about the problem with dlsym”我更明白其中的原因,我也明白被标准禁止并不意味着你绝对不能使用它。否则,所有 C++ 程序员如何使用正确的 ISO C++ 代码使用来自共享对象的函数?只是猜测,我可能是错的,我不是 C++ 专家。

在试验我的代码时,我发现通过共享指向包含对我要调用的函数的引用的结构的指针,我的编译器不会报错。我在编译时使用 -Wall 和 -pedantic。

我的代码如下所示:

myclass.hpp

class myclass
{
public:
virtual void dosomething (void)=0;
}

api.hpp

#include <myclass.hpp>
struct API
{
myclass* (* func)(void);
};

so.hpp

#include <iostream>
#include "myclass.cpp"
#include "api.hpp"

class childclass : public myclass
{
void dosomething (void)
{
std::cout << "Did it.\n";
}
}

/* function to return a new instance of childclass */

extern "C" myclass* make (void)
{
return new childclass;
}

/* struct that contains a pointer to the function */

extern "C" API interface;
API interface
{
make
};

host.cpp

#include <iostream>
#include <dlfcn.h>
#include "myclass.hpp"
#include "api.hpp"
int main (void)
{
void * th = dlopen("./so.so", RTLD_LAZY);
/* error checking was here */

#ifndef usefunction

API* api = static_cast<API*>( dlsym(th, "interface") );
myclass * inst = api->make();
inst->dosomething();

#else

myclass* (*func)(void) = reinterpret_cast<myclass* (*)(void)>( dlsym(th, "make") );
/* will never get to this point */

#endif

return 0;
}

已经编译了 so.so,然后我编译了我的 host.cpp 文件。

g++ -ldl -Wall -pedantic host.cpp -o host编译正常,程序正确打印 Did it. 运行时。

g++ -ldl -Wall -pedantic host.cpp -o host -Dusefunction提示

In function ‘int main(int, char**)’:
warning: ISO C++ forbids casting between pointer-to-function
and pointer-to-object [enabled by default]

我知道这只是一个警告,但为什么在第一种情况下不打印警告,当使用结构时,如果最终我能够间接引用指向驻留在共享对象中的函数的指针?

说到这里,有人知道以完全正确的 ISO C++ 方式实现所有这些的方法吗?它甚至存在吗?

最佳答案

完全符合标准的解决方案:

extern "C" typedef int (func_t)(char, double); // desired API function signature

int main()
{
static_assert(sizeof(void *) == sizeof(func_t *), "pointer cast impossible");

void * p = dlsym(handle, "magic_function");
char const * cp = reinterpret_cast<char const *>(&p);

func_t * fp;

std::copy(cp, cp + sizeof p, reinterpret_cast<char *>(&fp));

return fp('a', 1.25);
}

一种更简单但更可疑的写法,使用了一些类型双关语:

static_assert(sizeof(void *) == sizeof(func_t *), "pointer cast impossible");

void * vp = dlsym(handle, "magic_function");
func_t * fp;

*reinterpret_cast<void **>(&fp) = vp; // this is type-punning

关于c++ - 当我将 void 指针导入到具有指向共享对象中函数的指针的结构时,我没有收到警告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12585030/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com