Связывание в нескольких объектных файлах C, содержащих функции с эквивалентной подписью - PullRequest
1 голос
/ 07 августа 2010

Допустим, у меня есть программа на C ++, и я хочу вызывать функции из файла объектов C в ней.Ограничение состоит в том, что мне не разрешено вносить какие-либо изменения в исходные файлы языка C.

В этом случае я бы включил заголовок C как extern "C" в мой файл C ++,вызовите функцию, скомпилируйте объект C, используя gcc -c , и передайте результат в g ++ вместе с фактическими источниками C ++.

Я думаю, что я бы тожеДля этого нужно поместить C-заголовок # include в именованный блок namespace в файле C ++, чтобы поддерживать чистоту локального пространства имен (кто знает, какие еще причудливые вещи есть в .h file).

Что теперь, если мне нужно вызывать функции из двух объектных файлов на языке C.Допустим, у них разные подписи.Но в объектных файлах также есть несколько дублирующих функций.Не взорвется ли мой компоновщик в этот момент, если я попытаюсь передать оба объекта в g ++ одновременно?То же самое для глобалов.

Опять же: мне не разрешено изменять ЛЮБОЙ источников Си.В противном случае я бы просто переименовал файлы .c в .cxx, обернул их содержимое и содержимое соответствующих заголовков внутри namespace bla {} и передал все в g ++ .

(Да, C не является подмножеством C ++, как уже упоминалось в одном из комментариев)

Ответы [ 4 ]

2 голосов
/ 07 августа 2010

Ваш последний абзац имеет хорошее решение - почему бы не сделать файл C ++ примерно таким:

namespace c_namespace_1 {
    #include "CFile1.c"
}

namespace c_namespace_2 {
    #include "CFile2.c"
}

И так далее ... тогда вы можете скомпилировать этот файл как C ++ и не нужно изменять исходные коды.

1 голос
/ 07 августа 2010

Вы можете ввести исполняемые коды C в виде отдельных двоичных файлов данных и обрабатывать указатель функции, самостоятельно - в основном, делать работу компоновщика за него. Если двоичный файл не будет работать напрямую, получите вывод ассемблера файлов C и оберните их в функции, аналогичные приведенному выше предложению о пространствах имен.

0 голосов
/ 07 августа 2010

Это довольно странно, но одним из решений является переименование рассматриваемой функции (ей) с помощью макросов, чтобы они имели разные имена в отношении компоновщика.

Например, если у вас тоже есть функции с именем foo, одна из которых принимает int, а другая - double, в файлах IntFoo.c и DoubleFoo.c вы можете скомпилировать их следующим образом: это:

cc -Dfoo=IntFoo -o IntFoo.o IntFoo.c
cc -Dfoo=DoubleFoo -o DoubleFoo.o DoubleFoo.c

Тогда в вашем C ++ вы можете сделать это:

#define foo IntFoo
extern "C" {
    #include "IntFoo.h"
}

#define foo DoubleFoo
extern "C" {
    #include "DoubleFoo.h"
}

#undef foo

Здесь есть много предостережений: вы должны убедиться, что символ foo используется только в качестве имени нужной вам функции, вы должны убедиться, что вы правильно задаете макросы везде, где находится символ foo. используемый. Если есть повторяющиеся символы, вы также должны определить макросы для них.

Вероятно, это гораздо лучшее решение - просто исправить файлы C.

0 голосов
/ 07 августа 2010

Как насчет того, чтобы скомпилировать каждую подсистему C в свой собственный файл LIB, а затем скомпилировать отдельный файл C ++ LIB, который включает в себя соответствующую C LIB и обеспечивает вызовы функций в оболочке только для функций C в своей .LIB

, то есть:

file1.c => file1.lib
file2.c => file2.lib

Wrapper1.cpp + file1.lib => Wrapper1.lib
Wrapper2.cpp + file2.lib => Wrapper2.lib

Application.cpp + Wrapper1.lib + wrapper2.lib => Application.exe

Обратите внимание, что это не в моей голове, и я понятия не имею, будет ли компоновщик продолжать бум

Конечно, вы можете скомпилировать Wrapper1 и Wrapper2 в dll вместо Lib иэто гарантирует, что компоновщик не станет бумом!

...