重构遗留C代码 – 使用extern声明来帮助拆分模块(潜在的链接和运行时问题)

重构遗留C代码 – 使用extern声明来帮助拆分模块(潜在的链接和运行时问题),第1张

概述我正在重构一些旧的遗留代码,用C语言编写.代码紧密耦合,我正在努力将其重构为清晰的逻辑,松耦合模块. 在我早期的迭代中,我设法确定了逻辑模块 – 然而紧密耦合导致了我的问题,因为许多函数都对系统的其他部分有深入的了解. 我打算解决这个问题的方法是使用extern声明.希望下面的伪代码解释了这种情况: 假设我有两个逻辑上独立的模块Foo和FooBar.每个模块都要构建到一个单独的库中(FooBar模 我正在重构一些旧的遗留代码,用C语言编写.代码紧密耦合,我正在努力将其重构为清晰的逻辑,松耦合模块.

在我早期的迭代中,我设法确定了逻辑模块 – 然而紧密耦合导致了我的问题,因为许多函数都对系统的其他部分有深入的了解.

我打算解决这个问题的方法是使用extern声明.希望下面的伪代码解释了这种情况:

假设我有两个逻辑上独立的模块Foo和Foobar.每个模块都要构建到一个单独的库中(Foobar模块依赖于Foo模块).

/*######################################*//*             Foo Module               *//*######################################*//*  Foo.h */#ifndef FOO_MODulE_H#define FOO_MODulE_HvoID foo(int ID);int do_something();...#endif /* FOO_MODulE_H *//* Foo.c */#include "Foo.h"extern int foobar();  /* defined in Foobar module (a separate library) */voID foo(int ID){    int var;    switch (ID){        case 1:            var = do_something();            break;        case 2:            /* the module that gets here,has the required functions defined in it */            var = foobar();    }    return var;}/*###############################*//*        FOObar module          *//*###############################*//* Foobar.h */#ifndef FOObar_MODulE_H#define FOObar_MODulE_H#include "Foo.h"int foobar();voID do_something_else();...#endif /* FOObar_MODulE_H *//* source file */int foobar(){    return 42;}voID do_something_else(){   int ret = foo(2);   printf("Function returned: %d",ret);}

这是将现有代码重构为逻辑上独立的模块的有效方法,同时允许链接到libfoo.so和libfoobar.so的可执行文件继续正常工作吗?

我的基本假设是链接到libfoo.so的模块将无法解析foobar() – 但这应该没问题,因为它们不需要该函数,因此它们永远不必调用它.另一方面,对于链接到libfoobar.so的模块,当它们调用foo()时,`foobar()将被解析(函数定义在模块中).

我上面描述的方案是否会像我期望的那样工作,或者是否有一些我失踪的问题?

解决方法 我尝试将你的文件编译成共享库,然后使用它们(我使用cygwin).

这是为了Foo:

cm@Gregor-PC ~/src$gcc -I. -c --shared -o libFoo.so Foo.c

使用bin util nm,你可以检查符号(grep为’foo’来限制输出)

cm@Gregor-PC ~/src$nm libFoo.so | grep foo0000000a T _foo         U _foobar

它给出了一个偏移量并且表示终止的’T’告诉你符号是在lib中定义的.

现在,Foobar lib必须与Foo链接才能拥有foo符号

cm@Gregor-PC ~/src$gcc -I. -L. --shared -o libFoobar.so Foobar.c libFoo.socm@Gregor-PC ~/src$nm libFoobar.so | grep foo61f0111e T _foo61f010e0 T _foobar

有了这个,我只能编译Foobar并将foo作为已知符号:

cm@Gregor-PC ~/src$gcc -I. -o tst1 tst1.c libFoobar.socm@Gregor-PC ~/src$./tst1Function returned: 42

所以似乎工作正常.

您可以通过包含仅包含公共数据类型,导出函数原型(声明为extern)甚至公共全局变量或常量的头文件来改进模块化C代码的方法.这样的头文件声明了模块的接口,并且必须包含在使用模块的地方.

在模块章节中,精彩的书籍‘Functional C’(Hartel,Muller,1997,Addison Wesley,link)对此进行了更详细的解释.

好处是您的依赖关系更清晰(在源文件中包含),并且您不必在Foo源中具有那种难看的extern声明.

对于你的例子:

/*  Foo.h */extern int foo(int ID); /* exported to Foobar *//* Foobar.h */extern int foobar(); /* export to Foo */extern voID do_something_else(); /* export to tst1 *//* Foo.c */#include <Foo.h>#include <Foobar.h>int do_something() {  return 11;}int foo(int ID){    int var;    switch (ID){        case 1:            var = do_something();            break;        case 2:            /* the module that gets here,has the required functions defined in it */            var = foobar();    }    return var;}/* Foobar.c */#include <stdio.h>#include <Foo.h>#include <Foobar.h>int foobar(){    return 42;}voID do_something_else(){   int ret = foo(2);   printf("Function returned: %d",ret);}
总结

以上是内存溢出为你收集整理的重构遗留C代码 – 使用extern声明来帮助拆分模块(潜在的链接和运行时问题)全部内容,希望文章能够帮你解决重构遗留C代码 – 使用extern声明来帮助拆分模块(潜在的链接和运行时问题)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1230742.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存