Что такое надлежащая конвенция обозначения для MSVC dlls, статических библиотек и библиотек импорта

Что является стандартным или «большинство - популярная» конвенция обозначения для библиотеки MSVC строит.

Например, поскольку следование за библиотекой платформ foo имеет эти конвенции:

Linux/gcc:

shared: libfoo.so
import: ---
static: libfoo.a

Cygwin/gcc:

shared: cygfoo.dll
import: libfoo.dll.a
static: libfoo.a

Windows/MinGW:

shared: libfoo.dll
import: libfoo.dll.a
static: libfoo.a

То, что должно использоваться для MSVC, строит? Насколько я знаю, обычно имена foo.dll и foo.lib, но как Вы обычно различаете библиотеку импорта и статическую?

Примечание: Я спрашиваю потому что CMake создает довольно неприятное столкновение между ними называющий и импорт и статическую библиотеку как foo.lib. См. отчет об ошибках. Ответ помог бы мне убедить разработчиков исправлять эту ошибку.

11
задан Artyom 26 January 2010 в 15:29
поделиться

5 ответов

Вы различаете библиотеку и .dll по расширению. Но вы различаете библиотеку импорта и статическую библиотеку по имени файла , а не по расширению.

Не будет случая, когда библиотека импорта существует для набора кода, который был построен как статическая библиотека, или где статическая библиотека существует для dll. Это разные вещи.

Не существует единого стандартного соглашения об именах файлов MSVC. Как правило, имя библиотеки, оканчивающееся на "D", часто является отладочной сборкой библиотечного кода, msvcrtd.dll vs msvcrt.dll , но кроме этого, стандартов нет. .

6
ответ дан 3 December 2019 в 06:46
поделиться

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

Оба случая (I.e. Static vs. Import, и Debug vs. Выпуск) можно обрабатывать одним из двух способов: разных имен, или разные локации каталогов. Я обычно выбираю использовать разные имена, потому что я чувствую, что он минимизирует шанс ошибаться в библиотеке позже, особенно после установки или других действий движущихся файлов.

Я обычно использую foo.dll и foo.lib для общей библиотеки в Windows и foo_static.lib для статической библиотеки, когда я желаю иметь общие и статические версии. Я видел, как другие используют эту конвенцию, поэтому это может быть «самым популярным».

Итак, я бы порекомендовал следующее дополнение к вашей таблице:

Windows / MSVC:

shared: foo.dll
import: foo.lib
static: foo_static.lib

затем в Cmake, вы можете либо

add_library(foo_static STATIC foo.cpp)

, либо

add_library(FooStatic STATIC foo.cpp)
set_target_properties(FooStatic PROPERTIES OUTPUT_NAME "foo_static") 

, если по какой-то причине вы не хотите использовать » foo_static "как имя символической библиотеки.

5
ответ дан 3 December 2019 в 06:46
поделиться

Не существует стандартной конвенции именования для библиотек. Традиционные имена библиотек префиксеруются с Lib . Многие линкеры имеют варианты для получения lib в название библиотеки в командной строке.

Статические и динамические библиотеки обычно идентифицируются их расширением файла; Хотя это не требуется. Итак libmath.a будет статической библиотекой, тогда как libmath.so или libmath.dll будет динамической библиотекой.

Общее соглашение об именовании состоит в том, чтобы добавить категорию библиотеки на имя. Например, отладка статической библиотеки по математике будет «libmathd.a» или в Windows, «lib_math_debug». Некоторые магазины также добавляют Unicode в качестве атрибута имени файла.

Если вы хотите, вы можете добавить _msvc к имени библиотеки, чтобы указать, что библиотека требует или была создана MSVC (для дифференцирования GCC и других инструментов). Популярная конвенция при работе с несколькими платформами - разместить объекты и библиотеки в платформенных папках. Например, ./ Папка Linux / будет содержать объекты и библиотеки для Linux и аналогично . / MSW / для платформы Microsoft Windows.

Это проблема стиля. Проблемы в стиле часто рассматриваются как религиозные проблемы: никто из них не прав, нет универсального стиля, и они являются индивидуальными предпочтениями. Какую систему вы выберете, просто будете последовательными.

2
ответ дан 3 December 2019 в 06:46
поделиться

Насколько я знаю, нет реального «стандарта», по крайней мере, никакого стандарта большинства программного обеспечения не соответствует.

Моя конвенция - назвать мою динамику и статичный .lib .lib . Например:

foo-static
   foo.lib

foo
   foo.lib
   foo.dll

Библиотека для связи с зависит от выбора каталогов библиотеки, поэтому он почти полностью отделен от остальной части процесса сборки (он не появится в источнике, если вы используете MSVC #Pragma Комментарий (lib, "foo.lib") учреждение, и он не отображается в списке библиотек импорта для линкера).

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

Короче говоря: Windows / MSVC

shared: foo.dll
import: foo.lib
static: foo.lib

Вы должны быть в состоянии использовать этот шаблон на основе каталога с Cmake (никогда не использовал его). Кроме того, я не думаю, что это «ошибка». Это просто отсутствие стандартизации. Cmake делает (ИМХО) правильно не , чтобы установить псевдо-стандарт, если все это нравится по-разному.

2
ответ дан 3 December 2019 в 06:46
поделиться

Проблема заключается в том, что все, что вы делаете в течение worker.RunWorureAsync () , так и не будет завершено. Возможно, в событии DoWork есть какой-то бесконечный цикл или нечто подобное.

Вот рабочий пример, который выбирает следующего свободного работника:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading;

namespace ConsoleApplication1
{
    class Program
    {
        private static List<MyWorker> _Workers;

        static void Main(string[] args)
        {
            _Workers = new List<MyWorker>();

            for (int i = 0; i < 5; i++)
            {
                _Workers.Add(CreateDefaultWorker(i));
            }

            StartJobs(20000);
            Console.ReadKey();
        }

        private static void StartJobs(int runtime)
        {
            Random rand = new Random();
            DateTime startTime = DateTime.Now;

            while (DateTime.Now - startTime < TimeSpan.FromMilliseconds(runtime))
            {
                var freeWorker = GetFreeWorker();

                if (freeWorker != null)
                {
                    freeWorker.Worker.RunWorkerAsync(new Action(() => DoSomething(freeWorker.Index, rand.Next(500, 2000))));
                }
                else
                {
                    Console.WriteLine("No free worker available!");
                    Console.WriteLine("Waiting for free one...");
                    WaitForFreeOne();
                }
            }
        }

        private static MyWorker GetFreeWorker()
        {
            foreach (var worker in _Workers)
            {
                if (!worker.Worker.IsBusy)
                    return worker;
            }

            return null;
        }

        private static void WaitForFreeOne()
        {
            while (true)
            {
                foreach (var worker in _Workers)
                {
                    if (!worker.Worker.IsBusy)
                        return;
                }
                Thread.Sleep(1);
            }
        }

        private static MyWorker CreateDefaultWorker(int index)
        {
            var worker = new MyWorker(index);

            worker.Worker.DoWork += (sender, e) => ((Action)e.Argument).Invoke();
            worker.Worker.RunWorkerCompleted += (sender, e) => Console.WriteLine("Job finished in worker " + worker.Index);

            return worker;
        }

        static void DoSomething(int index, int timeout)
        {
            Console.WriteLine("Worker {1} starts to work for {0} ms", timeout, index);
            Thread.Sleep(timeout);
        }
    }

    public class MyWorker
    {
        public int Index { get; private set; }
        public BackgroundWorker Worker { get; private set; }

        public MyWorker(int index)
        {
            Index = index;
            Worker = new BackgroundWorker();
        }
    }
}
-121--3525859-

Я верю, что предмет списка включен или нет является частью этого состояния предмета, поэтому полагаю, что вы должны управлять им в ListAdapter . При подклассе адаптера можно переопределить isEnabled (position) . Для любой позиции, возвращаемой здесь true, ListView пометит этот предмет как отключенный.

Так что вы хотите сделать примерно так:

class MenuAdapter extends ArrayAdapter<String> {

    public boolean isEnabled(int position) {
       // return false if position == positionYouWantToDisable
    }

}

Это, вероятно, требует, например, Map для управления включенным состоянием каждого предмета, если вы хотите иметь возможность включать/отключать предмет с помощью установщика.

Затем установите пользовательский адаптер в ListView.

-121--2179113-

Как говорили другие, нет единого стандарта для именования файлов в окнах.

Для нашей полной базы продуктов, которая охватывает 100's exes, dlls и статических libs, мы успешно использовали следующее в течение многих лет, и это спасло много путаницы. В основном это смешение нескольких методов, которые я видел использованными на протяжении многих лет.

В двух словах все наши файлы имеют префикс и суффикс (не включая само расширение). Все они начинаются с «ома» (на основе названия нашей компании), а затем имеют комбинацию из 1 или 2 символов, которая примерно идентифицирует область кода.

Суффикс объясняет тип их встроенного файла и включает в себя до трех букв, используемых в комбинации, в зависимости от сборки, которая включает Юникод, Статик, Отладка (сборки DLL по умолчанию и не имеют явного идентификатора суффикса). Когда мы начали эту систему Юникод был не так распространен и мы должны были поддерживать и Юникод и не Юникод сборки (до Windows 2000 os), теперь все исключительно построен Юникод, но мы по-прежнему использовать одну и ту же номенклатуру.

Так типичный .lib «набор» файлов может выглядеть как

omfThreadud.lib (Unicode/Debug/Dll)
omfThreadusd.lib (Unicode/Static/Debug)
omfThreadu.lib (Unicode/Release/Dll)
omfThreadus.lib (Unicode/static)

Все файлы встроены в общую папку bin, что устраняет множество проблем dll-hell для разработчиков, а также упрощает настройку параметров настройки компилятора/компоновщика - все они указывают на одно и то же местоположение, используя относительные пути, и нет необходимости в ручном (или автоматическом) копировании библиотек, необходимых проекту. Наличие этих суффиксов также устраняет любые путаницу в отношении того, какой тип файла у вас может быть, и гарантирует, что у вас не может быть смешанного сценария, когда вы помещаете DLL отладки в комплект выпуска или наоборот. Все бывшие также используют аналогичный суффикс (Unicode/Debug) и встраиваются в одну папку bin.

Аналогичным образом существует одна папка «include», каждая библиотека имеет один файл заголовка в папке «include», который совпадает с именем библиотеки/dll (например, omfthread.h) Этот файл сам по себе # включает все остальные предметы, которые доступны этой библиотеке. Это сохраняет свою простоту, если вы хотите функциональность, которая находится в foo.dll вы только что # include «foo.h»; наши библиотеки сильно сегментированы по областям функциональности - фактически у нас нет никаких «швейцарско-армейских ножей», поэтому, включая всю функциональность библиотек, имеет смысл. (Каждый из этих заголовков также включает в себя другие необходимые заголовки независимо от того, являются ли они нашими внутренними библиотеками или другими SDK поставщика)

Каждый из этих включенных файлов использует макросы, которые используют # pramga's для добавления соответствующего имени библиотеки к строке компоновщика, поэтому отдельные проекты не должны иметь к этому отношение. Большинство наших библиотек могут быть построены статически или как DLL и # define OM_LINK_STATIC (если определено) используется для определения того, какой отдельный проект требуется (обычно мы используем DLL, но в некоторых случаях статические библиотеки, встроенные в .exe, имеют больше смысла для развертывания или по другим причинам)

#if defined(OM_LINK_STATIC)
 #pragma comment (lib, OMLIBNAMESTATIC("OMFTHREAD"))
#else
 #pragma comment (lib, OMLIBNAME("OMFTHREAD"))
#endif

Эти макросы (OMLIBNAMESTATIC & OMLIBNAME) используются _DEBUG определения типа сборки и создания соответствующего имени библиотеки для добавления к строке компоновщика.

Мы используем общее определение в статических & dll-версиях библиотеки, чтобы управлять правильным экспортом класса/функций в dll-сборках. Каждый класс или функция, экспортированные из библиотеки, декорированы этим макросом (имя которого соответствует базовому имени библиотеки, хотя это в значительной степени не важно)

class OMUTHREAD_DECLARE CThread : public CThreadBase

В DLL-версии параметров проекта мы определяем OMFTHREAD_DECLARE=__declspec (dllexport), в статической библиотечной версии библиотеки мы определяем OMFTHREAD_DECLARE как пустой .

В файле заголовка библиотек мы определяем его на основе того, как клиент пытается связать с ним

#if defined(OM_LINK_STATIC)
 #define OMFTHREAD_DECLARE
#else
 #define OMFTHREAD_DECLARE __declspec(dllimport)
#endif

Типичный проект, который хочет использовать одну из наших внутренних библиотек, просто добавил бы соответствующее включение в их stdafx.h (обычно) и это просто работает, если им нужно связать со статической версией, они просто добавляют OM_LINK_STATIC в свои настройки компилятора (или определите его в stdafx.h) и снова он просто работает.

2
ответ дан 3 December 2019 в 06:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: