Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 使用动态库获取结构中成员的地址_C - Fatal编程技术网

C 使用动态库获取结构中成员的地址

C 使用动态库获取结构中成员的地址,c,C,通过查看这个答案:我可以使用dlsym在C中获取全局变量。是否可以从结构中获取成员 我猜如果我在共享对象中有以下代码: 标题.h struct myStruct { int a; int b; }; imp.c 我可以包含相同的header.h文件,并将整个指针强制转换为struct myStruct*结构myStruct*capturedStructure=(结构myStruct*)dlsym(句柄,“结构”) 但是,有没有办法直接将地址发送给会员。我猜我不能做这样的事情:i

通过查看这个答案:我可以使用dlsym在C中获取全局变量。是否可以从结构中获取成员

我猜如果我在共享对象中有以下代码:

标题.h

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;