Как написать статическую библиотеку C и связать ее с исполняемым файлом с помощью g в Windows 10?

#c #windows #g #static-libraries #static-linking

#c #Windows #g #статические библиотеки #статическое связывание

Вопрос:

main.cpp

 #include <iostream>

int main() {
    std::cout << "main()" << std::endl;
    foo();
    return 0;
}
  

foo.cpp

 #include <iostream>

extern "C" {
  void foo() {
      std::cout << "bar" << std::endl;
  }
}
  

Скомпилировать статическую библиотеку:

 $ g   foo.cpp -static
  

Ошибка:

 undefined reference to `WinMain'
  

Но это компилирует:

 $ g   foo.cpp -shared -o foo.lib
  

Теперь у меня есть статическая библиотека с именем foo.lib (предположительно).

Я пытаюсь скомпилировать исполняемый файл, который ссылается на него:

 $ g   -L -lfoo main.cpp -o main.exe
  

И получите эту ошибку:

 'foo' was not declared in this scope
  

Но foo объявлено в статической библиотеке, с которой я связываюсь. Если ссылка работает, я не думаю, что мне нужно объявлять ее в main.cpp также. Так почему же ссылка не работает?


Обновить.

Я добавил void foo(); в main.cpp так что он не жалуется на то, что foo нужно объявить.

 #include <iostream>

void foo();

int main() {
    std::cout << "main()" << std::endl;
    foo();
    return 0;
}

  

Итак, я пытаюсь скомпилировать снова и получаю эту новую ошибку:

 undefined reference to `foo()'
  

Зачем мне нужно определять foo в main.cpp ? Это уже определено в foo.cpp это статическая библиотека.

Если мне нужно определить foo в main.cpp это сводит на нет всю цель ссылки на библиотеку foo.lib.

Обновления

  • Удаление всех extern "C" { } строки не устраняют ошибки «не foo определено».

Комментарии:

1. Функция должна быть объявлена при вызове этой функции. Вот как работает C . Компилятор должен знать имя функции и типы всех параметров. Связывание происходит после компиляции. Сначала код должен быть скомпилирован.

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

3. @SamVarshavchik Я объявил foo в начале main.cpp (смотрите Мой обновленный пост) но теперь он жалуется, что foo это не определено. Если мне нужно определить foo в main.cpp это сводит на нет цель установления связей.

4. Нет, это не «противоречит цели связывания». Привязка к библиотеке не устраняет необходимости объявлять функции. Вот почему все часто используемые библиотеки поставляются с заголовочными файлами, которые объявляют все функции в библиотеке. Если акт связывания с библиотекой устраняет необходимость объявлять какие-либо функции в библиотеке, тогда не было бы необходимости иметь заголовочные файлы, не так ли? И поскольку в библиотеке foo() определяется с помощью ссылки «C», то объявление, в которое вы добавили main.cpp , тоже должно иметь ссылку «C», верно?

5. Я объявил функцию, как вы предложили в своем первом комментарии. Теперь он жалуется, что он не определен. Я согласен с объявлением его в main.cpp . Я не согласен с ее определением в main.cpp ; определяющий foo в обоих main.cpp и foo.cpp противоречит назначению статической библиотеки foo.cpp .

Ответ №1:

Далее следуют магические заклинания, которые вы ищете:

  • main.cpp
 #include <iostream>
extern void foo();
int main() { 
  std::cout << "main()" << std::endl; 
  foo();
} 
  
  • foo.cpp
 #include <iostream>
void foo() { 
  std::cout << "bar" << std::endl; 
}
  

Консольные команды:

 $ g   -o foo.obj -c foo.cpp
  
 $ ar rcs foo.lib foo.obj
  
 $ g   main.cpp foo.lib -o main.exe
  

Эти заклинания вызывают в воображении статическую библиотеку foo с исполняемым файлом main, статически связанным с ним.