Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 以其他名称导出符号_C++_C_Gcc_Shared Libraries - Fatal编程技术网

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
…”这让你相信你有这样的需要,特别是它需要与C
strcpy同名,但类型不同?@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);
}