none
VS 2019, C&Cpp, построение DLL RRS feed

  • Вопрос

  • Всем привет!

    Продолжение темы.
    Есть библиотека C-исходников, несколько сотен файлов.
    Как из них построить DLL?

    Есть пошаговое руководство,
    но там библиотека строится из
    нескольких модулей в одном файле,
    а мне надо построить библиотеку из
    исходников из многих различных файлов.
    Понятно, что они должны быть в одном namespace,
    но как это реализовать?

    10 апреля 2021 г. 8:53

Ответы

  • "...код совместим с Visual C++" -
    да, в этом я убедился на
    простом подключении отдельных модулей из библиотеки исходников.
    А с dll я что-то по-крупному не доглядел.
    У меня в dll - дебаге только два obj - 
    dllmain.obj, pch.obj.
    Я полагал, что система сама все, что надо, выберет по h-файлу.
    А она, система, не догадалась.
    Ну и кроме того при построении клиента она мне говорит,
    что dll она вообще не нашла - совсем хорошо.
    хотя dll-ка есть и в dll-Debug-е, и в клиентском,
    я же ее туда сам скопировал.

    Требуется включить в проект все файлы исходников .c/cpp. У вас же просто пустая DLL. Я еще удивился что вам ее так быстро построить из случайных исходников... Типично при первой попытке сборки более менее объемного кода будут сотни если не тысячи ошибок. А после их устранения обычно начинаются проблемы с линкером когда какой то объектный код не найден. :)

    DLL при построении клиента вообще не используется, только lib/obj и заголовок. Заголовок декларирует точки вроде в DLL, a lib/obj содержит код для загрузки DLL для доступа к точкам входа. DLL потребуется только при запуске. Конечно, всегда можно загрузить DLL используя вызов LoadLibrary() и получить указатели на нужные функции вызовом GetProcAddress(). Собственно, именно это и делает код загрузчика в lib/obj.



    This posting is provided "AS IS" with no warranties, and confers no rights.

    • Помечено в качестве ответа QazRdx 13 апреля 2021 г. 15:48
    12 апреля 2021 г. 22:02
    Модератор
  • Нельзя, ведь в C нет метаданных.

    И 200 методов (я так понимаю вы именно их "модулями" называйте?) это немного, на час работы может быть. 

    Я в таких случаях обычно копирую C/C++ декларации методов и заменяю типы как надо поиском/заменой. То же самое касается вставления атрибута и public static в каждую строку.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    • Помечено в качестве ответа QazRdx 18 апреля 2021 г. 19:38
    18 апреля 2021 г. 16:32
    Модератор
  • Особой разницы нет, собирать DLL из одного файла или нескольких. Если файлов несколько, просто добавьте в проект несколько файлов, остальные шаги будут теми же. 

    Впрочем, по опыту предыдущей похожей темы (https://social.msdn.microsoft.com/Forums/ru-RU/a24a7b4c-0e44-41db-939b-60c31327a1e5/10571086107310891090107410771085108510721103-dll?forum=fordesktopru) могу сказать, что идея взять некий большой набор исходников на С/С++ и собрать его Visual C++ имеет высокие шансы закончиться ничем. Если проект рассчитан на другую систему сборки, например GCC+Make или использует что-то, неподдерживаемое в Visual C++, он просто не соберется. И даже если он соберется, не факт, что это проект DLL, т.е. он может ничего не экспортировать через decslpec(dllexport). Тут все же надо начинать с руководства от разработчиков библиотеки, что с ней нужно делать.
    • Помечено в качестве ответа QazRdx 13 апреля 2021 г. 15:51
    10 апреля 2021 г. 13:31
  • "Попробовал построение и DLL"

    Вы выполнили все пункты из руководства? В частности:

    1. Убедились что в нужных местах функции помечены _declspec(dllexport) или _declspec(dllimport)

    2. Подключили .lib файл с разделом экспорта библиотеки к проекту, который использует dll (https://docs.microsoft.com/en-us/cpp/build/walkthrough-creating-and-using-a-dynamic-link-library-cpp?view=msvc-160#to-add-the-dll-import-library-to-your-project)

    • Помечено в качестве ответа QazRdx 13 апреля 2021 г. 15:51
    12 апреля 2021 г. 6:11
  • SOFA это http://www.iausofa.org/ ? Глянул, там есть makefile для сборки статической библиотеки под Unix, для Windows и Visual C++ стандартно ничего не предоставляется. Есть какие-то неофициальные решения, попробуйте по запросу "sofa library build for windows" в поисковике. 

    "Хорошо бы почитать что-нибудь с нуля..."

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

    • Помечено в качестве ответа QazRdx 13 апреля 2021 г. 15:47
    13 апреля 2021 г. 3:50
  • Спасибо!
    Разбираюсь...
    В голове полный сумбур...

    Все на деле довольно просто: каждый файл C/C++  в проекте компилируется отдельно, при этом получается объектный модуль .obj который содержит символы (например функцию или переменную) и код для них. Несколько .obj можно при желании поместить в .lib. 

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

    Далее сборщик собирает .obj и .lib исполняемый образ, будь то .exe или .dll Последние на деле практически ничем не отличаются. 

    Утилита dumpbin умеет показывать что сидит внутри все этих файлов.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    • Помечено в качестве ответа QazRdx 13 апреля 2021 г. 15:47
    13 апреля 2021 г. 6:39
    Модератор

Все ответы

  • Особой разницы нет, собирать DLL из одного файла или нескольких. Если файлов несколько, просто добавьте в проект несколько файлов, остальные шаги будут теми же. 

    Впрочем, по опыту предыдущей похожей темы (https://social.msdn.microsoft.com/Forums/ru-RU/a24a7b4c-0e44-41db-939b-60c31327a1e5/10571086107310891090107410771085108510721103-dll?forum=fordesktopru) могу сказать, что идея взять некий большой набор исходников на С/С++ и собрать его Visual C++ имеет высокие шансы закончиться ничем. Если проект рассчитан на другую систему сборки, например GCC+Make или использует что-то, неподдерживаемое в Visual C++, он просто не соберется. И даже если он соберется, не факт, что это проект DLL, т.е. он может ничего не экспортировать через decslpec(dllexport). Тут все же надо начинать с руководства от разработчиков библиотеки, что с ней нужно делать.
    • Помечено в качестве ответа QazRdx 13 апреля 2021 г. 15:51
    10 апреля 2021 г. 13:31
  • Всем привет!

    Продолжение темы.
    Есть библиотека C-исходников, несколько сотен файлов.
    Как из них построить DLL?

    Есть пошаговое руководство,
    но там библиотека строится из
    нескольких модулей в одном файле,
    а мне надо построить библиотеку из
    исходников из многих различных файлов.
    Понятно, что они должны быть в одном namespace,
    но как это реализовать?

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

    Другое дело если исходники разрозненные и/или заточены под другой компилятор и/или ОС. Тут уже потребуется программист с хорошим знанием C и, возможно, месяцы работы чтоб привести все это в рабочее состояние и экспортировать что надо из DLL.

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


    This posting is provided "AS IS" with no warranties, and confers no rights.

    10 апреля 2021 г. 15:41
    Модератор
  • Спасибо, разбираюсь!

    10 апреля 2021 г. 20:38
  • Попробовал построение и DLL,
    и простое подключение отдельных модулей из библиотеки,
    результат один - исходники из библиотеки транслирует, DLL строит,
    в головном модуле библиотечные символы и программы ВИДИТ,
    но при трансляции и в русской и в английской версиях дает сбой -
    LNK2019 ссылка на неразрешенный внешний символ.
    Исходя из ПОЯСНЕНИЙ, причин может быть много,
    может быть дело в форматах?
    Библиотека исходников - в формате ANSI C,
    головной модуль - VS 2019 C++.
    Что делать?
    Всех с праздником, Днем космонавтики!
    12 апреля 2021 г. 4:23
  • ANSI C и С++ интегрируются вполне нормально, но в объявлениях иногда может понадобиться добавить extern "C", либо указать компилятору, что С нужно собирать как С++. Допустим, у нас есть файл test.c (расширение .с по умолчанию собирается как С)

    int CalcSum(int x, int y) {
    	return x + y;
    }

    Тогда в файле main.cpp мы можем вызвать функцию так:

    extern "C" int CalcSum(int x, int y);
    
    void main()
    {
    	int res = CalcSum(1, 2);
    }
    Либо в свойствах проекта "С++ - Дополнительно - Компилировать как" выбрать С++. Тогда не надо будет прописывать  extern "C", но могут вылезти какие-то другие проблемы, учитывая что С и С++ это все же разные языки.


    12 апреля 2021 г. 6:06
  • "Попробовал построение и DLL"

    Вы выполнили все пункты из руководства? В частности:

    1. Убедились что в нужных местах функции помечены _declspec(dllexport) или _declspec(dllimport)

    2. Подключили .lib файл с разделом экспорта библиотеки к проекту, который использует dll (https://docs.microsoft.com/en-us/cpp/build/walkthrough-creating-and-using-a-dynamic-link-library-cpp?view=msvc-160#to-add-the-dll-import-library-to-your-project)

    • Помечено в качестве ответа QazRdx 13 апреля 2021 г. 15:51
    12 апреля 2021 г. 6:11
  • extern "C" не помог, что с ним, что без него.

    "_declspec(dllexport) или _declspec(dllimport)" - 
    это где можно посмотреть?
    Все вроде облазил, но не нашел.

    "lib-файл" - все делал по инструкции,
    но самого 
    lib-файла нигде не увидел.
    dll на месте, я ее и в Debug клиента скопировал.
    Последнее сообщение при построении -
    MSB3073: выход из команды "xcopy /y /d "..\..SofaLibrary\Debug\SofaLibrary.dll" "D:\SOFA\SofaClient\Debug\"
    Это в "Свойства конфигурации -> События сборки -> События перед сборкой -> Командная строка".
    Так было рекомендовано в инструкции, насколько понял.
    Простое подключение отдельных модулей из библиотеки -
    вроде сдвинулось с места, но как-то не очень.
    Все модули система видит и транслирует, но потом выдает ошибку -
    "C3861: идентификатор не найден"
    Не понятно, чем он отличается от остальных.
    При неполном тестировании,
    когда задействованы не все модули,
    все работает, я даже порадовался,
    но когда подключаю все, то затык.

    Разбираюсь.

    • Изменено QazRdx 12 апреля 2021 г. 15:08
    12 апреля 2021 г. 15:05
  • Не понятно при каких обстоятельствах у вас возникает ошибка... При сборке DLL или при попытке ее использования?


    This posting is provided "AS IS" with no warranties, and confers no rights.

    12 апреля 2021 г. 16:22
    Модератор
  • dll строится без сбоев.
    Ошибка возникает при построении клиента.
    12 апреля 2021 г. 16:34
  • dll строится без сбоев.
    Ошибка возникает при построении клиента.

    Для использования DLL требуется заголовок с определениями точек входа в DLL и .obj или .lib с кодом который загружает DLL и обеспечивает вызов точек входа. У вас это имеется? 

    В любом случае покажите ошибку полностью и строку кода в которой она произошла.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    12 апреля 2021 г. 16:45
    Модератор
  • _declspec(dllexport) должно быть прописано у всех функций, которые экспортируются из dll. Альтернативным способом является .def файл. Если у вас нет ни того ни другого, идею сборки DLL придется отбросить, проект не предназначен для этого. 

    "dll строится без сбоев."

    Видимо, потому что компилятор не проверяет наличие атрибута экспорта на хотя бы одной функции. Но если строится это уже хорошо, значит код совместим с Visual C++

    12 апреля 2021 г. 17:27
  • "...код совместим с Visual C++" -
    да, в этом я убедился на
    простом подключении отдельных модулей из библиотеки исходников.
    А с dll я что-то по-крупному не доглядел.
    У меня в dll - дебаге только два obj - 
    dllmain.obj, pch.obj.
    Я полагал, что система сама все, что надо, выберет по h-файлу.
    А она, система, не догадалась.
    Ну и кроме того при построении клиента она мне говорит,
    что dll она вообще не нашла - совсем хорошо.
    хотя dll-ка есть и в dll-Debug-е, и в клиентском,
    я же ее туда сам скопировал.

    12 апреля 2021 г. 18:42
  • "...код совместим с Visual C++" -
    да, в этом я убедился на
    простом подключении отдельных модулей из библиотеки исходников.
    А с dll я что-то по-крупному не доглядел.
    У меня в dll - дебаге только два obj - 
    dllmain.obj, pch.obj.
    Я полагал, что система сама все, что надо, выберет по h-файлу.
    А она, система, не догадалась.
    Ну и кроме того при построении клиента она мне говорит,
    что dll она вообще не нашла - совсем хорошо.
    хотя dll-ка есть и в dll-Debug-е, и в клиентском,
    я же ее туда сам скопировал.

    Требуется включить в проект все файлы исходников .c/cpp. У вас же просто пустая DLL. Я еще удивился что вам ее так быстро построить из случайных исходников... Типично при первой попытке сборки более менее объемного кода будут сотни если не тысячи ошибок. А после их устранения обычно начинаются проблемы с линкером когда какой то объектный код не найден. :)

    DLL при построении клиента вообще не используется, только lib/obj и заголовок. Заголовок декларирует точки вроде в DLL, a lib/obj содержит код для загрузки DLL для доступа к точкам входа. DLL потребуется только при запуске. Конечно, всегда можно загрузить DLL используя вызов LoadLibrary() и получить указатели на нужные функции вызовом GetProcAddress(). Собственно, именно это и делает код загрузчика в lib/obj.



    This posting is provided "AS IS" with no warranties, and confers no rights.

    • Помечено в качестве ответа QazRdx 13 апреля 2021 г. 15:48
    12 апреля 2021 г. 22:02
    Модератор
  • Да, братцы!..
    Это не я такой, это жизнь такая...
    Хорошо бы почитать что-нибудь с нуля...
    13 апреля 2021 г. 3:07
  • SOFA это http://www.iausofa.org/ ? Глянул, там есть makefile для сборки статической библиотеки под Unix, для Windows и Visual C++ стандартно ничего не предоставляется. Есть какие-то неофициальные решения, попробуйте по запросу "sofa library build for windows" в поисковике. 

    "Хорошо бы почитать что-нибудь с нуля..."

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

    • Помечено в качестве ответа QazRdx 13 апреля 2021 г. 15:47
    13 апреля 2021 г. 3:50
  • Спасибо!
    Разбираюсь...
    В голове полный сумбур...
    13 апреля 2021 г. 4:18
  • Спасибо!
    Разбираюсь...
    В голове полный сумбур...

    Все на деле довольно просто: каждый файл C/C++  в проекте компилируется отдельно, при этом получается объектный модуль .obj который содержит символы (например функцию или переменную) и код для них. Несколько .obj можно при желании поместить в .lib. 

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

    Далее сборщик собирает .obj и .lib исполняемый образ, будь то .exe или .dll Последние на деле практически ничем не отличаются. 

    Утилита dumpbin умеет показывать что сидит внутри все этих файлов.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    • Помечено в качестве ответа QazRdx 13 апреля 2021 г. 15:47
    13 апреля 2021 г. 6:39
    Модератор
  • Спасибо, ребята!
    Все стало понятней.
    На нынешний момент мне, видимо,
    диэльэлька не очень-то и нужна.
    Из всего скопища функций SOFA-библиотеки
    нужно всего несколько модулей для 
    определения галактических координат источников чего-то,
    прилетающего откуда-то, 
    и приведения этих координат к общепринятой эпохе
    с учетом некоторых поправок.
    Т.е. других задач ПОКА не просматривается и, соответственно, 
    многомерного использования такой DLL не предполагается.
    Попробую для начала подключать отдельные модули,
    а дальше будет видно.
    С С# было попроще...
    13 апреля 2021 г. 15:46

  • Попробую для начала подключать отдельные модули,
    а дальше будет видно.

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

    Исходников потенциально будет несколько меньше, но придется их "вычленять" из всего набора кода и разбираться с зависимостями. Если код написан без четкой структуры, это может быть сложнее чем сборка всего что есть.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    13 апреля 2021 г. 16:05
    Модератор
  • "На нынешний момент мне, видимо,
    диэльэлька не очень-то и нужна."

    Бывают у меня заносы, я уже говорил об этом.
    А как же я без диэльэльки перейду к C#,
    на котором вся моя система крутится,
    с картинками, с сервисом,
    с которой давно уже люди обрабатывают поступающие данные?

    Бывает - жизнь такая...
    Так что не расслабляемся,
    "...я требую продолжение банкета...".

    Есть и обнадеживающая информация.
    Наконец-то получилось собрать и все построить,
    а это 60 модулей из 200 - не хило!
    Теперь DLL - строго и неотвратимо.





    14 апреля 2021 г. 4:06
  • См. выше, либо помечаете нужные функции __declspec(dllexport), либо добавляете .def файл со списком экспортируемых функций. Если вам нужно только несколько функций, ни то, ни другое не будет очень трудным.
    14 апреля 2021 г. 6:56
  • Скорее всего на практике потребуется отдельный файл с функциями точек входа в DLL.

    Эти функции будут иметь сигнатуры удобные для P/Invoke и будут вызывать что надо из библиотеки. Разумеется, если функции в библиотеке уже удобны для P/Invoke, то тогда надобности в этом нет.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    14 апреля 2021 г. 21:55
    Модератор
  • Всем привет!
    Сорри за задержку.
    В консольном режиме создал DLL -
    C:\Program Files (x86)\Microsoft VisualStudio\2017\Community\VC\Auxiliary\Build>vcvars32.bat
    d:\SOFA\SofaVS2017>cl /LD *.c
    d:\SOFA\SofaVS2017>cl /LD *.obj
    Получился файл SOFA.dll.

    В C#-программе каждую нужную функцию из SOFA.dll
    необходимо предварительно объявлять -
    [DllImport ("SOFA.dll")] public static extern double iauAnpm(double d);
    [DllImport ("SOFA.dll")] public static extern int iauDtf2d(string s, int iy, int im, int id, int ihr, int imn, double sec, out double d1, out double d2);
    ...
    Работает конечно, но не хочется объявлять таким образом 200 библиотечных модулей.

    Вопрос. 
    Можно ли сделать так, как делается с C#-диэлельками,
    объявить Using-ом соответствующий Namespace,
    или, может быть, как-нибудь еще, но покороче?
    • Изменено QazRdx 18 апреля 2021 г. 13:37
    18 апреля 2021 г. 13:33
  • Нельзя, ведь в C нет метаданных.

    И 200 методов (я так понимаю вы именно их "модулями" называйте?) это немного, на час работы может быть. 

    Я в таких случаях обычно копирую C/C++ декларации методов и заменяю типы как надо поиском/заменой. То же самое касается вставления атрибута и public static в каждую строку.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    • Помечено в качестве ответа QazRdx 18 апреля 2021 г. 19:38
    18 апреля 2021 г. 16:32
    Модератор
  • Большое спасибо!
    18 апреля 2021 г. 19:40