Добавить ссылку из приложения С# в DLL, скомпилированную без /clr?

Я использую Visual Studio 2008 для создания решения с двумя проектами: консольным приложением С# и библиотекой DLL С++. Я хочу, чтобы приложение вызывало функцию из dll с помощью P/Invoke. Поэтому я пытаюсь добавить dll в качестве ссылки на приложение С#. Но когда я пробую команду «Добавить ссылку», Visual Studio не позволяет мне это сделать, пока я не задаю свойство /clr в dll (в разделе «Свойства конфигурации: Общие»). Теперь я подумал, что P/Invoke может работать со старыми библиотеками win32. Действительно, если я соберу свою dll без /clr и просто скопирую ее вручную в bin/Debug, то приложение будет работать нормально. Итак, почему /clr требуется для добавления dll в качестве ссылки? И если VS не позволит мне добавить его, есть ли какой-нибудь (чистый) обходной путь, чтобы мое приложение нашло dll?

Я вижу, что у кого-то была аналогичная проблема (хотя и со сторонней dll): Невозможно добавить ссылку DLL на VS 2008 Он получил ответ, что нужно создать оболочку. Но в этом нет необходимости, так как приложение может прекрасно использовать dll; это просто шаг добавления ссылки, который не работает. И кроме того, не будет ли коду обертки нужна ссылка на dll, поднимая ту же проблему, что и раньше? Мне бы очень хотелось получить ответ, который вообще не требует написания оболочки.


person Paul A Jungwirth    schedule 18.01.2010    source источник


Ответы (4)


Почему бы просто не добавить шаг после сборки, чтобы скопировать неуправляемую DLL в каталог проекта? Вам не нужна «ссылка», чтобы иметь возможность ссылаться на неуправляемую DLL, и похоже, что единственная проблема, с которой вы столкнулись, связана с тем, что файл не копируется автоматически в путь поиска.

person Daniel Pryden    schedule 18.01.2010
comment
Я написал шаг предварительной сборки для приложения C#, используя эту командную строку: скопируйте $(SolutionDir)Debug\MathDll.dll $(TargetDir). Увы, я бы хотел, чтобы функция «Добавить ссылку» работала, потому что теперь я должен ее поддерживать, и я думаю, что для выпускных сборок она будет другой... Я действительно не понимаю, почему «Добавить ссылку» не должна обрабатывать такого рода вещь. - person Paul A Jungwirth; 18.01.2010
comment
Я только что нашел немного более чистый способ сделать это. Вместо того, чтобы использовать команду DOS до/после сборки, я добавил dll в проект C# как существующий элемент. Затем в его свойствах я установил «Копировать в выходной каталог» на «Копировать, если новее». (Его действие сборки — это содержимое.) Это все еще кажется мне немного хакерским, но, по крайней мере, оно устраняет проблему Debug-vs-Release, и его немного легче обнаружить. - person Paul A Jungwirth; 18.01.2010
comment
К сожалению, я понял, что мой второй обходной путь не решает проблему Debug-vs-Release, потому что я ссылался на dll из папки Debug. С другой стороны, первый обходной путь может решить эту проблему, изменив команду на копирование $(SolutionDir)$(Configuration)\MathDll.dll $(TargetDir). - person Paul A Jungwirth; 19.01.2010
comment
@Paul Я использовал копию $(ProjectDir)Resources\* $(TargetDir), так как поместил библиотеки DLL в каталог ресурсов. Где список $... которые распознает VS? - person KyleM; 15.06.2011
comment
внимательно проверяйте уровень ошибки после каждой пакетной команды на этапе после сборки, поскольку MSBuild игнорирует код ошибки для всех команд, кроме последней (подробнее) - person tivadj; 11.08.2011

При использовании PInvoke в C++ DLL добавлять ссылку не нужно. Ссылки нужны только при вызове управляемого кода в другой библиотеке DLL. Просто поместите DLL C++ в тот же каталог и добавьте его имя в атрибут DllImport.

person JaredPar    schedule 18.01.2010

Теоретически вы можете добавить C++-DLL в качестве связанного ресурса с вашей C#-DLL. Это заставит .NET копировать вашу C++-DLL везде, где она копирует C#-DLL, даже в GAC. Теоретически означает, что есть некоторые недостатки:

  • Вы можете указать компилятору С# (csc.exe) через параметры командной строки добавить связанный ресурс, но я так и не нашел способ сделать это через файл .csproj или даже Visual Studio.
  • Если C#-DLL содержит пользовательские элементы управления WinForms, и вы хотите использовать его в дизайнере, он не будет работать, потому что Winforms-Designer копирует C#-DLL во временное место, где он загружает его, но игнорирует связанный ресурс.
  • Я не знаю, сработает ли это, если вы поместите свою C#-DLL в GAC (да, C++-DLL также войдет в качестве ресурса, но я не знаю, будет ли она найдена при запуске вашей C#-DLL!)

Поэтому, если ничего из вышеперечисленного вам не подходит, вы можете вызвать csc.exe следующим образом:

csc.exe ... /linkresource:cpp.dll

Надеюсь, это может помочь!

person mmmmmmmm    schedule 18.01.2010

Аналогичную проблему решил следующим образом:

  1. На всех компьютерах разработки добавлен путь к рассматриваемым dll-файлам в переменную среды PATH. Таким образом, все разработчики могли отлаживать все исполняемые файлы, имеющие ссылку на сборку с неуправляемыми dll, без необходимости писать сценарий после сборки для каждого исполняемого файла.

  2. Для производства ночная задача msbuild собирает все в одну папку, а неуправляемые библиотеки dll, помеченные как «Контент/Всегда копировать», автоматически включаются в сборку той сборки, частью которой они являются.

person Vedran    schedule 30.05.2011