Linux是否可以通过共享对象的序数或索引检索函数地址?
我问,因为我正在编写一个OpenGL包装器,我必须为所有300多个函数执行以下操作:
module->AddressOf(funcs[0],"glAccum");
module->AddressOf(funcs[1],"glAlphaFunc");
module->AddressOf(funcs[2],"glAreTexturesResident");
module->AddressOf(funcs[3],"glArrayElement");
module->AddressOf(funcs[4],"glBegin");
module->AddressOf(funcs[5],"glBindTexture");
module->AddressOf(funcs[6],"glBitmap");
module->AddressOf(funcs[7],"glBlendFunc");
module->AddressOf(funcs[8],"glCallList");
module->AddressOf(funcs[9],"glCallLists");
module->AddressOf(funcs[10],"glClear");
module->AddressOf(funcs[11],"glClearAccum");
module->AddressOf(funcs[12],"glClearColor");
module->AddressOf(funcs[13],"glClearDepth");
module->AddressOf(funcs[14],"glClearIndex");
module->AddressOf(funcs[16],"glClearStencil");
module->AddressOf(funcs[17],"glClipPlane");
module->AddressOf(funcs[18],"glColor3b");
module->AddressOf(funcs[19],"glColor3bv");
module->AddressOf(funcs[20],"glColor3d");
依此类推......在Windows上,我可以做到:
for (int i = 0; i < 385; ++i)
module->AddressOf(funcs[i], (const char*)i);
就是这样!每个函数的地址存储在funcs[I]
中。
Linux有与上面类似的内容吗?
注意:
Module->AddressOf
相当于:
bool Module::AddressOf(void* &func, const char* name)
{
#if defined _WIN32 || defined _WIN64
func = (void*)GetProcAddress(handle, name);
#else
func = dlsym(handle, name);
#endif
return func != nullptr;
}
是的,我通过迭代func数组并查看其中是否有NULL
来检查错误。
Windows上的序数值示例:
答案 0 :(得分:1)
在Linux上,您可以使用dlopen(3)和dlsym
函数。链接主程序时不要忘记传递-rdynamic
。
当然,您需要知道函数的名称,以便使用dlsym
请注意,您可以通过dlopen
在主程序中获取符号 - 将其作为NULL
害怕C ++ name mangling。使用extern "C"
将其停用。
BTW,如果你的意思是
for (int i = 0; i < 385; ++i)
module->AddressOf(funcs[i], (const char*)i);
(我猜你有一个错字:你的代码混合了I
和i
)我很惊讶它甚至可以在Windows上可靠地工作:当i
为50时,{{1}是(const char*)i
,它不太可能是有效的字符串。在Linux上肯定不是(因为地址空间的第一个4K页面没有映射,我想在Windows上也是如此,我不知道。)
但是,GetProcAddress被记录为处理
函数的序数值。如果此参数是序数值,则它必须在低位字中;高阶词必须为零。
我不知道函数的序数值是什么(在某些共享库中),而AFAIK Linux没有这样的概念。即使您的代码在Windows上运行,它如何知道(const char*)50
对应funcs[5]
?您需要在某处将代码提供给您的代码!
在Linux上如果要从其地址获取函数名称,可以使用glBindTexture
如果您需要获取OpenGL函数的地址,您需要处理它们的每个名称!
也许你可以在某些数组中收集许多OpenGL函数的名称。您可以使用一些脚本(可能是一些dladdr
脚本处理某些OpenGL标头,或者可能使用GCC自定义MELT编译器来收集它们。
您可能会使用某些ELF读取库(如awk
)并扫描ELF符号表。您可以libelf
使用popen
...
阅读Drepper's paper: How To Write Shared Libraries;它详细解释了这一切!