【问题标题】:Compiling gcc .o files with g++ .cpp files使用 g++ .cpp 文件编译 gcc .o 文件
【发布时间】:2015-08-18 14:41:44
【问题描述】:

我有两个文件,print_permu.c 和 gen_permu.cpp。我希望将print_permu.c文件编译成目标文件,然后使用目标文件编译gen_permu.cpp,其中包含对print_permu.c中函数的调用。

print_permu.c

#include<stdlib.h>
#include<stdio.h>

typedef char byte;

char *printable=NULL;
size_t pos,size,*char_cnt;

void __print_permu_recurse()
{
        if( pos==size )
        {
                printf("%s\n",printable);
                return;
        }
        byte iter = 25;
        while( iter>=0 )
        {
                if( char_cnt[iter] )
                {
                        printable[pos] = 'a'+iter;
                        --char_cnt[iter];
                        ++pos;
                        __print_permu_recurse();
                        --pos;
                        ++char_cnt[iter];
                }
                --iter;
        }
}

void print_permu(size_t *char_count)
{
        char_cnt = char_count;
        for(pos = 0,size = 0 ; pos<26 ; ++pos)
                size += char_count[pos];

        printable = (char*)malloc(sizeof(char)*(size+1));
        printable[size] = '\0';
        pos = 0;

        __print_permu_recurse();

        free(printable);
}

gen_permu.cpp

#include<iostream>
#include<string>

extern "C"
{
        #include"print_permu.c"
}

using namespace std;

int main()
{
        string str;
        size_t char_count[26]={},N,iter;

        cout << "string:"; cin >> str;
        N = str.size();

        for(iter=0;iter<N;++iter)
        {
                ++char_count[str[iter]-'a'];
        }

        print_permu(char_count);

        return 0;
}

我尝试了以下命令以上述方式编译代码。

$ gcc -c print_permu.c 
$ g++ print_permu.o gen_permu.cpp 
/tmp/ccQxAEea.o:(.bss+0x0): multiple definition of `printable'
print_permu.o:(.bss+0x0): first defined here
/tmp/ccQxAEea.o: In function `__print_permu_recurse':
gen_permu.cpp:(.text+0x0): multiple definition of `__print_permu_recurse'
print_permu.o:print_permu.c:(.text+0x0): first defined here
/tmp/ccQxAEea.o: In function `print_permu':
gen_permu.cpp:(.text+0xe0): multiple definition of `print_permu'
print_permu.o:print_permu.c:(.text+0xe9): first defined here
collect2: error: ld returned 1 exit status

$ g++ -c print_permu.c 
$ g++ print_permu.o gen_permu.cpp 
/tmp/ccPJA0kU.o:(.bss+0x0): multiple definition of `printable'
print_permu.o:(.bss+0x0): first defined here
/tmp/ccPJA0kU.o:(.bss+0x8): multiple definition of `pos'
print_permu.o:(.bss+0x8): first defined here
/tmp/ccPJA0kU.o:(.bss+0x10): multiple definition of `size'
print_permu.o:(.bss+0x10): first defined here
/tmp/ccPJA0kU.o:(.bss+0x18): multiple definition of `char_cnt'
print_permu.o:(.bss+0x18): first defined here
collect2: error: ld returned 1 exit status

首先,我使用gcc 编译代码,希望目标文件与g++ 编译时兼容。那没有用。因此,我尝试单独使用g++ 编译这两个文件,但无济于事。

如何编译这段代码? '我是否缺少任何选项?

使用 gcc 版本 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04), Ubuntu 14.04, x86_64


另外,

我最初想在print_permu 中声明__print_permu_recurse 函数,这在gcc 中是允许的(尽管C 标准不允许这样做)。我遵循了类似的过程。由于那没有成功,'更改了代码以兼容 C++。

【问题讨论】:

  • 首先,不要使用带有双下划线的名称,它们在所有范围内都是保留的。其次,不要将 source 文件包含到另一个源文件中。而是制作一个 header 文件,其中包含您要调用的函数的函数原型,并将其包含在内。
  • 永远不要 #include .c 文件,因为没有理由这样做。它只适用于创建链接器错误。
  • 您需要为 .c 文件中的函数原型创建一个 .h 文件。该 .h 应该检查正在定义的 cplusplus,如果已定义,则使用 .h 文件中的 extern c {...} 语法。 #在 .c 和 .cpp 文件中包含该 .h 文件

标签: c++ c gcc g++ object-files


【解决方案1】:

你的问题是gen_permu.cpp中的这个构造:

extern "C"
{
        #include"print_permu.c"
}

您有一个源文件 print_permu.c 和一个源文件 gen_permu.cpp,其中包括 print_permu.c。

当您将print_permu.c 编译为目标代码时,它包含来自源文件print_permu.c 的所有内容。

当您将gen_permu.cpp 编译为目标代码时,它包含来自源文件gen_permu.cpp和源文件print_permu.c的所有内容。

当您尝试将它们两个链接在一起时,您会收到“多重定义”错误,因为 print_permu.c 中的所有内容也在 gen_permu.cpp 中定义,并且链接器拒绝做出决定使用哪个定义。


您可能打算做的是包含来自print_permu.c 的声明。这不是通过包含整个源文件来完成的,而是通过编写一个 header 文件print_permu.h:

// This is a "header guard". It avoids problems if the
// header is included more than once in a translation unit.
// The token used (here: PRINT_PERMU_H) is up to you, but
// should be sufficiently unique. All uppercase is a common
// convention.
#ifndef PRINT_PERMU_H
#define PRINT_PERMU_H

// This makes a C++ compiler aware that function declarations
// refer to *C* code, not C++ code. (The two languages generate
// different linker symbols.) A C compiler will just ignore this
// (as it should, since it does not need any special handling).
#ifdef __cplusplus
extern "C" {
#endif

// This just *declares* the *existence* of the function.
// The compiler can use this information (in gen_permu.cpp)
// to create a call-to-placeholder. The linker will then
// turn that into a call-to-function when you link the two
// object files together.
void print_permu(size_t *char_count);

// End of the C++ compatibility construct.    
#ifdef __cplusplus
}
#endif

// End of the header guard.
#endif

然后,而不是顶部的构造,只需编写

#include "print_permu.h"

在您的 C++ 文件(或 C 文件,感谢#ifdef __cplusplus 无关紧要)。


您的源代码还有其他各种问题不会导致立即失败,但如果它们成为编码习惯就会带来问题:

Reserved identifiers.

Global variables.

Magic numbers.

没有 cmets,并且假设为 ASCII。

我很确定你的代码对字符做了一些可疑的事情,假设是 ASCII-7 字符集,并且如果 1) 文本包含像 öéß 这样的国际字符,或者 2) 相关系统具有非连续编码,则会失败用于字符(例如EBCDIC)。

但是我厌倦了试图弄清楚你的代码实际上打算做什么,因为那里有零个 cmets。 (想象一下,我发布了没有 cmets 的标题示例......)所以我不能给你关于如何改进的提示,只是你应该这样做。

我还看到了一个没有大括号的 for 循环 ({})。 ;-)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-28
    • 1970-01-01
    • 2011-03-13
    • 2018-03-10
    • 2010-12-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多