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