C 使用动态库获取结构中成员的地址
通过查看这个答案:我可以使用dlsym在C中获取全局变量。是否可以从结构中获取成员 我猜如果我在共享对象中有以下代码: 标题.hC 使用动态库获取结构中成员的地址,c,C,通过查看这个答案:我可以使用dlsym在C中获取全局变量。是否可以从结构中获取成员 我猜如果我在共享对象中有以下代码: 标题.h struct myStruct { int a; int b; }; imp.c 我可以包含相同的header.h文件,并将整个指针强制转换为struct myStruct*结构myStruct*capturedStructure=(结构myStruct*)dlsym(句柄,“结构”) 但是,有没有办法直接将地址发送给会员。我猜我不能做这样的事情:i
struct myStruct
{
int a;
int b;
};
imp.c
我可以包含相同的header.h文件,并将整个指针强制转换为struct myStruct*<代码>结构myStruct*capturedStructure=(结构myStruct*)dlsym(句柄,“结构”)代码>
但是,有没有办法直接将地址发送给会员。我猜我不能做这样的事情:int*c=(int*)dlsym(handle,“structure.b”)代码>
由于dlsym允许一个人自己获取函数或全局函数(不需要标题),我希望我也可以在不需要标题的情况下获取成员
地址直接发给会员
通常的方式如下所示:
struct myStruct *pnt = (struct myStruct*) dlsym(handle, "structure");
int *b = &pnt->b;
现在让我们替换s/pnt/((struct myStruct*)dlsym(handle,“structure”)/
。那就是:
int *b = &((struct myStruct*) dlsym(handle, "structure"))->b;
没有定义结构的编译器?(来自评论)
这可能有点棘手,但我们可以做到。您需要导出另一个符号:
const size_t offsetof_member_b_in_myStruct = offset(struct myStruct, b);
然后在稍后的客户端代码中:
int *b = (int*)(
(uintptr_t)dlsym(handle, "structure") +
*(size_t*)dlsym(handle, "offsetof_member_b_in_myStruct")
);
我想这样的API可能是一致的,但感觉很糟糕。将结构导出到客户机代码更简单。在一般情况下,最好创建一个标准,指定与客户机代码交换的结构的内存布局(从而将提供适当抽象的责任推给客户机)。使用extern struct myStruct structure代码>符号表中将有一个条目指向结构
它将被键入字符串结构
要获取其b成员的地址,只需执行以下操作:
struct myStruct *p = dlsym(handle, "structure");
if(!p) fail();
int *pb = &p->b;
答案肯定是“否”。这是因为成员偏移量计算在代码中处理,而不会出现在符号表中。当然,对于库的所有版本,偏移量都不能保持不变。@user3386109-这是否意味着对于给定的拱门(即x86,x86_64),我不能使用int*b=(int*)(dlsym(handle,“structure”)+4)代码>我想答案是“否”,因为编译器可能会重新排序我的成员以减少成员之间的填充。从长远来看,使用固定偏移量是行不通的。例如,库的版本1有inta;int b代码>然后库的版本2添加了另一个成员inta;INTC;int b代码>。到b
的偏移量将改变。因此,即使您有结构的标题,您也需要为每个版本的库使用正确版本的标题。顺便说一句,尽管编译器可能会在成员之间添加填充,但不允许对成员重新排序。@user3386109-谢谢,我没有意识到这一点。我认为您需要使用\uuuu属性\uuuu((packed))
[在gcc中]来防止重新排序,但该属性实际上只会防止插入填充,您需要承担正确对齐数据的责任。这会起作用,但符号表是否会跟踪偏移,以便我可以访问成员“b”没有定义结构的编译器?我可以手动执行int*b=(int*)(dlsym(句柄,“结构”)+4)代码>编译器没有定义结构吗?
-您可以,但请注意这是错误的。阅读有关结构中填充的内容。您可以在变量中导出偏移量(struct myStruct,b)
,然后再导出偏移量(struct myStruct,b)
(int*)((uintptpttr)dlsym(handle,“structure”)+offsetof(struct myStruct,b))
。假设(struct myStruct,b)
的偏移量等于4是错误的。谢谢。是的,我没有考虑编译器可以重新排序成员以减少元素之间的填充。@有问题的C编译器可能不会重新排序一个结构的成员。对我来说,输出一个返回“<代码> b>代码>”的“吸气剂”似乎更干净。
struct myStruct *p = dlsym(handle, "structure");
if(!p) fail();
int *pb = &p->b;