以其他名称导出符号

时间:2020-04-12 15:04:30

标签: c++ c gcc shared-libraries

我的情况如下:我需要构建一个库,在该库中导出“包装的” strcpy(请忽略这对我有什么用),它唯一要做的就是调用标准(从{ {1}})string.h,但返回strcpy,而不是返回void。这意味着,我需要char *,但这会立即给我#include string.h,而strcpy不会让我根据自己的意愿重新定义它,并建立一个gcc共享库仅导出新包装的.so。我该怎么办?

3 个答案:

答案 0 :(得分:2)

mystring.h

extern "C" void strcpy(char* dst, const char* src);

stringinternal.h

void mystrcpy(char* dst, const char* src);

mystring.c

#include "mystring.h"
#include "stringinternal.h" 
extern "C" void strcpy(char* dst, const char* src) {
  mystrcpy(dst, src);
}

stringinternal.c

#include "stringinternal.h" 
#include <string.h>
void  mystrcpy(char* dst, const char* src) {
  strcpy(dst, src);
}

main.c

#include "mystring.h" 
int main() {
  char dst[3];
  strcpy(dst, "ab");
  return 0;
}

标准strcpy作为弱函数导出,您可以在库中重新定义它。

要正确链接.so,必须禁用标准库进行链接,并以适当的顺序列出文件:strcpyinternal.o,然后最后需要标准库和mystring.o。这样可以防止您的.so进行递归strcpy调用。 gcc的示例可以像

gcc -shared -nostdlib -o my.so stringinternal.o -lc mystring.o

答案 1 :(得分:1)

strcpy是带有“ C”链接的弱符号,因此可以无错误覆盖

libstrcpy.cc:

#include <dlfcn.h>

extern "C" {
void strcpy(char *dest, char *src)
{
    auto real_strcpy = (char*(*)(char*,char*)) dlsym(RTLD_NEXT, "strcpy");
    real_strcpy(dest, src);
}
}

编译为:g++ libstrcpy.cc -std=c++11 -shared -fPIC -ldl -o libstrcpy.so

验证strcpy导出:readelf --dyn-syms libstrcpy.so

要使用(main.cc):

extern "C"{
void strcpy(char *, char *);
}
int main()
{
    char a[10] = "test" , b[10] = {};
    strcpy(a, b);
}

编译为:g++ main.cc -o main -lstrcpy -L./

请注意,如果要使用正确的void返回声明,则不能导入将定义strcpy的任何标头(正确的方式)。

答案 2 :(得分:0)

如果使用c ++,则可以定义自己的名称空间,例如:

在一个my.h

namespace strcpy_v2
{
    void strcpy( char *dest, const char *src ); 
}

在关联的my.cpp中

#include <string>
#include "my.h"

void strcpy_v2::strcpy( char *dest, const char *src )
{

    auto val = std::strcpy(dest,src);

   // you should test val to ensure every thing is ok

}

将链接您的代码中的.so。您可以这样做:

using namespace strcpy_v2;

代替

 using namespace std;