C 重写函数指针的实现并用于共享库
这在C 重写函数指针的实现并用于共享库,c,pointers,dll,C,Pointers,Dll,这在C中是一种独特的情况 假设我们有一个名为libfoo.so和libbar.so的库,在这两个库中,我们使用相同的函数名,Get_a,假设系统调用了Get_a 假设加载了libbar,然后使用参数G调用其Get\u AG是一个带有一些函数指针的结构,其中一个是: (*G)->寄存器baz 因此,在libbar调用Get_A时,我们希望变异指向该RegisterBaz函数的指针,然后通过dlopen+dlsym调用libfoo版本的Get_A 我尝试过的一件事是直接赋值,但后来我得到了一个编译器
C
中是一种独特的情况
假设我们有一个名为libfoo.so
和libbar.so
的库,在这两个库中,我们使用相同的函数名,Get_a
,假设系统调用了Get_a
假设加载了libbar
,然后使用参数G
调用其Get\u A
G
是一个带有一些函数指针的结构,其中一个是:
(*G)->寄存器baz
因此,在libbar
调用Get_A
时,我们希望变异指向该RegisterBaz函数的指针,然后通过dlopen+dlsym调用libfoo
版本的Get_A
我尝试过的一件事是直接赋值,但后来我得到了一个编译器错误,只读变量是不可赋值的,所以我尝试通过指针:
// not void * but actually some function signature typedefed.
void *f_ptr = (*G)->RegisterBaz;
*&f_ptr = r_n;
其中,r\u n
是一个普通的C函数,其签名与RegisterBaz
在r\u n
中,我调用了RegisterBaz
因此,虽然这并没有seg错误,但它也不会最终调用我的包装函数 因此,当您执行直接赋值时,您可能试图将函数赋值给常量函数指针;这显然不是你能做的 此外,在守则中:
void *f_ptr = (*G)->RegisterBaz;
*&f_ptr = r_n;
实际上,f_ptr
指向的是与(*G)->RegisterBaz
指向的相同的东西,因此当您使用*&
更改f_ptr
时(基本上是一个无操作),您根本没有修改(*G)->RegisterBaz
此外,不能将函数指针分配给对象指针;void*
类型的东西只能保证能够保存对象指针。(INCITS-ISO-IEC 9899-2011)
因此,无论出于何种原因,如果您执意要直接更改(*G)->RegisterBaz
,您可以执行以下操作:
void (**f_ptr)(void) = (void (**)(void))&((*G)->RegisterBaz);
*f_ptr = r_n;
但由于您将通过(*G)->RegisterBaz
调用,因此需要确保替换函数签名与(*G)->RegisterBaz
恰好指向的函数签名匹配
除非f_ptr
类型为指针指向“在此处插入被调用函数的签名”
,否则您还会收到警告
我需要重申这不是你通常想要做的事情,所以我不能保证这会起作用。但是,如果你一意孤行,你会这么做(基本上你是将常量函数指针别名为非常量指针。)Hmm,这样做会给我一个seg错误。你100%确定你要替换的函数提供了所有相同的功能吗?你不能仅仅用你自己的函数替换一个库函数,并且仅仅因为签名匹配就期望它是漂亮的。签名是正确的,有什么可能是错误的,我可以从哪里开始寻找线索或查找。很抱歉,我忘记了一个&,所以请尝试使用我编辑的代码。不幸的是,仍然是seg错误,我在Android上这样做,所以也在寻找在命令行上查找lldb到应用程序的方法。