C++ 以其他名称导出符号
我的情况如下:我需要构建一个库,在其中导出一个“包装的”C++ 以其他名称导出符号,c++,c,gcc,shared-libraries,C++,C,Gcc,Shared Libraries,我的情况如下:我需要构建一个库,在其中导出一个“包装的”strcpy(请忽略这对我有多有用),它唯一做的事情就是调用标准(从string.h)strcpy,但返回void,而不是返回char*。这意味着,我需要#包括string.h,但这会立即给我strcpy,而gcc不会让我按照我的意愿重新定义它,并构建一个。因此共享库只导出新的、包装的strcpy。如何实现?如果使用C++,可以定义自己的命名空间EG:< /P> 在我的房间里 namespace strcpy_v2 { void s
strcpy
(请忽略这对我有多有用),它唯一做的事情就是调用标准(从string.h
)strcpy
,但返回void
,而不是返回char*
。这意味着,我需要#包括string.h
,但这会立即给我strcpy
,而gcc
不会让我按照我的意愿重新定义它,并构建一个。因此
共享库只导出新的、包装的strcpy
。如何实现?如果使用C++,可以定义自己的命名空间EG:< /P>
在我的房间里
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
}
而不是
using namespace std;
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);
}
标准strcpy作为弱函数导出,您可以在库中重新定义它
为了正确链接,您必须禁用链接的标准库,并按正确的顺序列出文件:strcpyinteral.o最后需要标准libs和mystring.o。这将阻止.so的递归strcpy调用。gcc的示例如下
gcc -shared -nostdlib -o my.so stringinternal.o -lc mystring.o
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++main.cc-o main-lstrcpy-L./
请注意,如果要使用正确的
void
返回声明,则不能导入任何将定义strcpy
(正确方式)的标题。用户不需要使用strcpy
的返回值。如果他忽略它,则该行为相当于一个无效的返回值。@PaulOgilvie事情更复杂,最好忽略我为什么这样做。事实上,我使用的是强类型的Haskell FFI,此外,还有其他一些函数我想以更复杂的方式包装,而不是简单地忽略它们的返回值。这句话可能不是真的:“我需要构建一个库,在其中导出“包装的”strcpy
…”这让你相信你有这样的需要,特别是它需要与Cstrcpy同名,但类型不同?@EricPostpischil它是一个供内部使用的库,对于我的编译器(用另一种语言Haskell编写),而不是一个公共库。我在这里只感兴趣的是如何完成这个特殊的符号输出属性,而不是如何/为什么我需要这个。。。那将是另一个话题……也许GCC可以让我静态链接,让旧的strcpy消失?然后,不知何故,允许我将一个符号函数“重命名”为另一个名称(因为在C中,显然不能有两个具有相同标识符和相同参数的不同函数,即没有重载)。gcc有这样的选项吗?这似乎不是我想要的,因为我想直接使用共享库中的新包装函数。。。我只是想找到一种完全“隐藏”和“覆盖”标准strcpy的方法,但是在我的包装器上使用它……使用包装函数可以简单地通过以下操作完成:使用名称空间strcpy_v2;它的用途不会出现在C/C++代码中,而是另一种不识别名称空间的语言(或者至少,它不会简单地这么做…),问题是我希望我的。所以文件将strcpy
导出为名称(但实际上是mystrcpy
),而不是mystrcpy
作为名称。你似乎误解了。我为演示制作了main.c,它使用了你的strcpy。所以,不是mystrcpy。哦,我明白了,是的,很抱歉误解了。让我马上试试这一秒。我们如何将这些文件编译成对应的.o
?碰巧我在./stlib.c:1:0:./stlib.h:1:8:错误:字符串常量之前的预期标识符或“(”,它指的是一行:extern“c”void puti(const int32_t n);
,它表明“c”是错误的(?)代码在该行报告之前似乎有错误。太好了!!这也可以通过静态链接实现吗,例如,如果我想生成libstrcpy.a
并嵌入所有内容,而不是依靠dlsym
动态加载strcpy
?如果你想在没有dlsym
的情况下静态加载,你需要使用S.M.的解决方案(您可以将stringinternal.o
放入存档库)。
gcc -shared -nostdlib -o my.so stringinternal.o -lc mystring.o
#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);
}
}
extern "C"{
void strcpy(char *, char *);
}
int main()
{
char a[10] = "test" , b[10] = {};
strcpy(a, b);
}