Как вызвать функцию из другого файла c

Обновлено: 04.07.2024

это не испортит имя C_library_function и компоновщик найдет то же имя в своем входе *.lib файлы и проблема решена.

вызов функции C++ из C.

но здесь я расширяю большое приложение, которое является написан на C, и мне нужно использовать библиотеку, которая написана на C++. Имя искажение C++ вызывает проблемы здесь. Линкер жалуется на неразрешенные символы. Ну, я не могу использовать компилятор C++ над моим проектом C, потому что это нарушает много других вещей. Каков же выход?

кстати я использую MSVC

вам нужно создать C API для предоставления функциональности вашего кода на C++. В принципе, вам нужно будет написать код C++, который объявлен extern "C" и который имеет чистый API C (не используя классы, например), который обертывает библиотеку C++. Затем вы используете чистую библиотеку оболочки C, которую вы создали.

ваш API C может дополнительно следовать объектно-ориентированному стилю, даже если C не является объектно-ориентированным. Например:

Я бы сделал это следующим образом:

(при работе с MSVC игнорируйте команды компиляции GCC)

предположим, что у меня есть класс C++ с именем ААА, определенными в файлах ААА.х, ААА.cpp, а то класс ААА есть метод с именем sayHi (const char * name), что я хочу включить для C-кода.

код класса C++ААА - чистый C++, я не изменяю это:

/ / aaa.h

/ / aaa.cpp

компиляция этого класса, как обычно делается для C++. Этот код "не знает", что он будет использоваться код C. С помощью команды:

теперь, также В C++, создание соединителя C. Определение его в файлах aaa_c_connector.h, aaa_c_connector.cpp. Этот соединитель будет определять функцию C с именем AAA_sayHi (cosnt char *name), что будет использовать экземпляр ААА и вызовет свой метод:

/ / aaa_c_connector.h

/ / aaa_c_connector.cpp

компиляция его, опять же, с помощью обычной команды компиляции C++:

теперь у меня есть общая библиотека (libaaa_c_connector.so), что реализует функцию C AAA_sayHi (const char *name). Теперь я могу создать основной файл C и скомпилировать все вместе:

/ / main.c

компиляция с помощью команды компиляции C:

мне нужно будет установить LD_LIBRARY_PATH, чтобы содержать $PWD, и если я запускаю исполняемый файл ./c_aaa, я получу результат, который я ожидаю:

EDIT:

в некоторых дистрибутивах Linux -laaa и -lstdc++ также может потребоваться для последней команды компиляции. Спасибо @AlaaM. за внимание

предполагая, что API C++ совместим с C (без классов, шаблонов и т. д.), вы можете обернуть его в extern "C" < . >, Так же, как вы делали, когда шли в другую сторону.

Если вы хотите выставить объекты и другие милые вещи C++, вам придется написать API-интерфейс оболочки.

вам придется написать обертку для C в C++ , если вы хотите это сделать. C++ является обратная совместимость, но не вперед совместимы.

экспортируйте свои функции C++ как extern " C " (aka C style symbols) или используйте .формат файла def для определения недекорированных символов экспорта для компоновщика C++ при создании библиотеки C++, тогда компоновщик C не должен иметь проблем с его чтением

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

В основном у меня есть несколько файлов cpp со всеми моими функциями, которые я сделал для использования с двоичными деревьями, BST, связанными списками и т. Д.

То, что я хочу сделать, это вместо того, чтобы копировать и вставлять функции по мере необходимости, я хочу просто иметь возможность делать

И быть в состоянии звонить и использовать свои собственные функции.

Какие шаги для этого?
Сделать заголовочный файл со всеми прототипами функций, которые я использовал?
И где разместить файл cpp и header со всеми действующими функциями?
Есть ли способ, которым я могу вызвать каталог файла функций напрямую?

То есть Я больше думаю о том, чтобы поместить его в одну папку с основным исходным cpp-файлом, чтобы поделиться с некоторыми из моих коллег.

Как я могу сделать это?

Редактировать: Windows. Компилятор miniGW

Решение

Объявите функции в заголовке

Реализуйте их в MyFunctions.cpp

Включите заголовок в любой файл, который вы хотите

Другие решения

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

Объектные файлы содержат скомпилированный код, но они часто не завершены. То есть они содержат ссылки на код, который не содержится в них. По сути, они могут сказать: «Теперь вызовите эту функцию, я не знаю, где она и что она делает, но вы должны вызывать ее».

линкер затем используется для связывания объектных файлов, возможно, вместе с библиотеками, в исполняемый файл (или библиотеку). Задача компоновщика состоит в том, чтобы «разрешить» все ссылки на внешний код в каждом объектном файле, найдя соответствующий код в других объектных файлах и библиотеках.

Итак, вернемся к вашему вопросу.

У вас есть, в общем, три варианта: скомпилировать и связать все ваши cpp файлы непосредственно каждый раз в одном проекте; скомпилировать полезный повторно используемый код в статическую библиотеку, а затем связать ваш проект с ним; или скомпилируйте полезный повторно используемый код в общую библиотеку, свяжите свой проект с ним и убедитесь, что поставили общую библиотеку вместе с результатом, чтобы ее можно было запустить.

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

К сожалению (imho) C ++ как язык не поставляется с единой системой сборки, чтобы организовать все это для вас (более поздние языки часто делают). Есть несколько разных компиляторов / линкеров и много различные системы сборки, которые могут все это делать. К сожалению, конкретные шаги, которые вам необходимо предпринять, очень сильно зависят от вашего выбора компилятора и системы сборки.

Это довольно просто, так как JMAA сказал, что вы должны провести некоторое исследование, чтобы понять эти концепции, но, будучи практичным, вы должны сделать следующее:

Вы определите functionsExample.cpp где вы должны определить все свои функции, а также functionsExample.h где вы будете объявлять свои функции.

Вы будете иметь это как functionsExample.cpp:

Ответ это как functionsExample.h:

Затем в CPP вы хотите запустить пример функцию, просто добавьте:

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

Файл конфигурации, который вы пишете, указывает, какие исходные файлы программы использовать и какие исполняемые файлы для сборки. Используемая цепочка сборки выбирается на этапе настройки, и после этого вы можете собрать исполняемые файлы, выполнив make или ninja (требуется meson, рекомендуется для CMake). Если вы измените исходный код, вам нужно только повторно запустить make или ninja. Конечно, только измененные детали перестраиваются. Только исполняемые файлы, которые затронуты вашими изменениями, также повторно связаны.

Может быть полезно посмотреть несколько подробных сборок, чтобы ознакомиться с процессом сборки в вашей системе.

Я изучаю C, но у меня большой опыт работы с языками программирования более высокого уровня, такими как Java.

у нас есть два файла

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

если у вас есть несколько файлов, важно различие между объявлением и определением функции. Определение, вероятно, является тем, к чему вы привыкли при определении функций: вы записываете содержимое функции, например

декларации, с другой стороны, позволяет объявить компилятору, что вы знаете функция существует, но вы не говорите компилятору, что это такое. Например, вы можете написать

и компилятор ожидал бы, что функция "квадрат" определена в другом месте.

теперь, если у вас есть два разных файла, которые вы хотите взаимодействовать (например, предположим, что функция "квадрат" определена в add.c, и вы хотите вызвать квадрат (10) в main.c), вам нужно сделать и определение и объявление. Во-первых, вы определяете квадрат вдобавок.c. Тогда ты!--25-->объявить это в начале main.c. Это позволяет компилятору знать, когда он компилирует main.c что существует функция "квадрат", которая определена в другом месте. Теперь вам нужно скомпилировать оба main.c и add.C в объектные файлы. Вы можете сделать это, позвонив

это приведет к созданию файлов main.O и добавить.o. Они содержат скомпилированные функции,но не являются полностью исполняемыми. Важно понять, что здесь главное.o "неполный" в некотором смысле. При компиляции основной.o, вы сказали ему, что функция "квадрат" существует, но функция "квадрат" не определена внутри main.o. Таким образом, главный.o имеет своего рода" висячую ссылку "на функцию"квадрат". Он не будет компилироваться в полную программу, если вы не объедините ее с другой .o (или a .так или иначе .а) файл, который содержит определение "квадрат". Если вы просто попытаетесь ссылке main.о в программу, т. е.

вы получите ошибку, потому что компилятор попытается resolve болтающаяся ссылка на функцию "квадрат", но не найдет для нее никакого определения. Однако, если вы включаете add.o при связывании (связывание-это процесс разрешение все эти ссылки на неопределенные функции при преобразовании .o файлы в исполняемые файлы или .so files), то не будет никаких проблем. т. е.

в точности эквивалентно

предполагая, что wtf.txt содержит текст "hello world".

Итак, если мы поместим все объявления add.c in add.h (т. е.

, а затем в верхней части Главного.c, пишем

это функционально то же самое, как если бы мы только что вручную объявили функцию "квадрат" в верхней части главный.c.

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

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

почему вы может использовать функцию, не объявляя ее

Заголовок Охранники

еще одна распространенная практика-использование "защитников заголовка". Чтобы объяснить это, давайте рассмотрим возможную проблему. Допустим, у нас есть два файла: herp.c и derp.C, и они и хотите используйте функции, содержащиеся друг в друге. Следуя приведенным выше рекомендациям, у вас может быть герпес.h с линией

и баттхерт.h с линией

чтобы использовать функцию в другом файле, вам нужно ее объявить. Обычно, каждый .C файл (кроме main.c)имеет связанный заголовок (.h) файл, который правильно объявляет все функции, определенные в .файл c. Ты можешь!--11-->объявить столько раз, сколько вы хотите (пока все объявления идентичны), но может быть только один определение.

затем main.c имеет заявление add и может использовать функцию, но определение of add довольно твердо только в add.C файл, и поэтому он существует только один раз, и поэтому он будет компилироваться правильно.

вот простой пример вызова функции из другой программы C

позвольте мне назвать основную программу как основную.c и программа, которая содержит функцию как функцию.c для функции.c я создаю файл заголовка, называемый function.h

Для компиляции используйте приведенную ниже команду

G++ main.функция c.c-o главный

Вот подробное объяснение. В основной программе я вызвал функцию для суммирования 2 чисел. Значения 1 и 2 в основной программе были поданы в функцию в функции.c через функцию заголовка.h, который содержит точку доступа или мост к функции.с

для получения более подробной информации вы можете проверить ссылки, приведенные ниже

добавить инструкцию печати, чтобы проверить результат или использовать echo $? после выполнения файла main

вы можете вызвать его, потому что объявление не требуется для вызова в C. тип возврата, однако, неизвестен, и поэтому по умолчанию будет int . Это возможно отчасти из-за соглашения о вызовах по умолчанию в C и продвижения типов по умолчанию по крайней мере int точности.

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

если вы включаете определения функций, они будут экспортированы, если вы не укажете их хранение с помощью static . Поскольку вы также компилируете и связываете add.c , вы не можете добавить это с тех пор ни один или оба ваших объектных файла затем будут экспортировать add .

если вы хотите просто включить все свои функции, лучше всего поместить их определения в заголовки и посыпать их спецификаторами хранения.

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

Как вы перемещаете функции C в отдельный файл? FYI: Я использую gcc.

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

Перемещение этих функций во внешний файл не работает, потому что они должны ссылаться на эту глобальную переменную:

Как я могу обойти эту проблему?

ОТВЕТЫ

Ответ 1

Ваш файл main.c

Ваш файл functions.h

Ваш файл functions.c

Скомпилируйте это с:

Ответ 2

Самый распространенный способ - разместить прототипы функций в файле заголовка и реализации вашей функции в исходном файле. Например:

Затем вы скомпилируете, используя следующее:

Я только поместил одну функцию в каждую пару источник/заголовок для иллюстрации. Вы можете создать только один заголовок, который включает прототипы для всех исходных файлов, или вы можете создать несколько файлов заголовков для каждого исходного файла. Ключ в том, что любой исходный файл, который будет вызывать функцию, должен включать заголовочный файл, который включает прототип функции.

Ответ 3

Сначала вам нужно узнать разницу между декларацией и определением. Объявление сообщает компилятору, что существует что-то вроде функции. Определение - для случая функций - реализация фактической функции.

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

Ответ 4

Вы можете сделать два файла: один с основной функцией, а другой с остальными.

Если ваша функция в другом файле использует глобальную переменную из другого модуля/файла, вам нужно добавить "extern" перед объявлением глобальной переменной в модуле вместе с определением функции. Это говорит компилятору, что вы обращаетесь к глобальной переменной из другого файла.

Ниже приведен пример, в котором определяется глобальная переменная "x" и вызывается функция "myfunction" в файле main.c. "Myfunction" определяется в файле functions.c. "X" также необходимо быть объявленным в файле functions.c, но так как он будет обращаться к "x" из другого файла, перед ним должен быть "extern". "myfunction" принимает внешнюю глобальную переменную "x", увеличивая ее на один и распечатывает его. Рассмотрим следующий код:

main.c будет выглядеть примерно так:

functions.c будет выглядеть примерно так:

Обратите внимание, что main.c использует "int x;" объявить x, тогда как functions.c использует "extern int x" для объявления x.

Чтобы скомпилировать код, убедитесь, что оба файла находятся в одной папке, и скомпилируйте, как если бы у вас был только один файл. Например, если вы используете gcc в системе linux и gcc, ваш ввод командной строки будет выглядеть так:

Первая строка компилирует код, а вторая строка запускает его. Вывод должен выглядеть так:

Значение x в myfunction равно: 2 Значение x в main равно: 2

Обратите внимание, что значение "x" также изменяется в основном, так как "x" является глобальной переменной.

Читайте также: