LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1655|回复: 23

关于这个宏定义的疑惑

[复制链接]
发表于 2006-2-6 15:15:57 | 显示全部楼层 |阅读模式

  1. #define FORCE_MODULE_LINK(module) \
  2.     extern "C" void RTV_##module##_ForceStaticLink(); \
  3.     extern "C" void LOCAL_RTV_##module##_ForceStaticLink() {  RTV_##module##_ForceStaticLink(); }   //0126 "##" menas that connect

复制代码
发表于 2006-2-6 16:36:02 | 显示全部楼层
有啥疑惑?说
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-2-6 18:36:12 | 显示全部楼层
1:如果在程序中运行:
  1. FORCE_MODULE_LINK("myFoo")
复制代码

时,是不是被:

  1. extern "C" void RTV_myFoo_ForceStaticLink()
复制代码


  1. extern "C" void LOCAL_RTV_myFoo_ForceStaticLink() {                               RTV_myFoo_ForceStaticLink();
  2. }
复制代码

代替。
2。看到过这里的extern "C" 类似使用共享库作为动态加载时的对外接口时用到的: extern C External_module(),不同的只是后者没有用双引号。 举个例子:

  1. include
  2. #include
  3. #include SMSGamePlugin.h
  4. int main(int argc, char** argv)
  5. {
  6.         void *GameLib = dlopen(./Flower.so, RTLD_LAZY);
  7.         const char *dlError = dlerror();
  8.          if (dlError)
  9.         {
  10.                 std::cout << dlopen error! << dlError << std::endl;
  11.                 return(-1);
  12.         }
  13.         CSMSGamePlugin *(*pGetGameObject)(void);
  14.         pGetGameObject = (CSMSGamePlugin *(*)(void))dlsym(GameLib, GetGameObject);
  15.         dlError = dlerror();
  16.         if (dlError)
  17.         {
  18.                 std::cout << dlsym error! << dlError << std::endl;
  19.                 return(-1);
  20.         }
  21.         CSMSGamePlugin *pGame = (*pGetGameObject)();
  22.         pGame->Initialize();
  23.         pGame->Load();
  24.         pGame->Handle();
  25.         delete *pGame;
  26.         dlclose(GameLib);
  27. }
  28. 公用基类部分:SMSGamePlugin.h
  29. #ifndef __SMSGamePlugin_h__
  30. #define __SMSGamePlugin_h
  31. class CSMSGamePlugin
  32. {
  33. public:
  34.         virtual int Initialize(void) = 0;
  35.         virtual int Load(void) = 0;
  36.         virtual int Handle(void) = 0;
  37. };
  38. #endif
  39. 编译:g++ -rdynamic -ldl -s -o Test main.cpp
  40. 共享库头文件:Flower.h
  41. #ifndef __Flower_h__
  42. #define __Flower_h__
  43. #include SMSGamePlugin.h
  44. extern C CSMSGamePlugin *GetGameObject(void);
  45. class CFlower: public CSMSGamePlugin
  46. {
  47. public:
  48.         virtual int Initialize(void);
  49.         virtual int Load(void);
  50.         virtual int Handle(void);
  51. };
  52. #endif
  53. 共享库实现文件:Flower.cpp
  54. #include
  55. #include Flower.h
  56. CSMSGamePlugin *GetGameObject(void)
  57. {
  58.         return(new CFlower());
  59. }
  60. int CFlower::Initialize(void)
  61. {
  62.         std::cout << Initialize() << std::endl;
  63.         return(0);
  64. }
  65. int CFlower::Load(void)
  66. {
  67.         std::cout << Load() << std::endl;
  68.         return(0);
  69. }
  70. int CFlower::Handle(void)
  71. {
  72.         std::cout << Handle() << std::endl;
  73.         return(0);
  74. }
  75. 编译:
  76.     g++ -c Flower.cpp
  77.     g++ -shared -o Flower.so
  78. 注意:
  79. 如果不加extern C编译后运行时就会提示:
  80. dlsym error!./Test: undefined symbol: GetGameObject


复制代码
回复 支持 反对

使用道具 举报

发表于 2006-2-7 09:45:10 | 显示全部楼层
1.是的。你用g++ -E编译程序,就可以看到预处理后的结果了。
2.加上extern "C"是为了避免c++编译器mangling函数名。这样才不至于在动态链接时找不到引用的函数名。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-2-7 13:45:06 | 显示全部楼层
1 :上述所说的宏定义是:extern "C", 而动态加载的对外接口是:extern C (没有双引号,还是忘记加了)
2: extern "C"都是为了动态加载时能找到引用的函数名的吗?
回复 支持 反对

使用道具 举报

发表于 2006-2-8 09:02:40 | 显示全部楼层
1.应该是要加上双引号。
2.在这里应该是起这个作用
回复 支持 反对

使用道具 举报

发表于 2006-2-8 09:59:47 | 显示全部楼层
Post by kj501

2.加上extern "C"是为了避免c++编译器mangling函数名。这样才不至于在动态链接时找不到引用的函数名。

补充一下,C++支持重载,为了区分一个object file里导出的函数名一样但参数不同,命名空间不同的函数,所以C++连接的函数存在function name mangling
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-2-18 17:51:37 | 显示全部楼层
是不是说在某个文件中声明如下:
extern "C" FooDemo()
都是为了C++的重载的需要。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-2-18 17:59:40 | 显示全部楼层
还有当出现
FORCE_MODULE_LINK(module)
时匹配那个函数。
当在arm的交叉编译环境(在Linux将这个文件所在的SDK的Makefile 的编译器用arm的)编译时时总是提示:#语法前错误。
请指教
回复 支持 反对

使用道具 举报

发表于 2006-2-18 18:04:40 | 显示全部楼层
并不是“为了”重载,而是防止编译器对其进行名字分裂
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表