Библиотека оболочек C # вокруг неуправляемой DLL требует, чтобы неуправляемая DLL находилась в одном каталоге во время сборки - PullRequest
0 голосов
/ 06 октября 2018

Обычно при обращении к управляемой DLL, которая оборачивает неуправляемую DLL, с помощью PInvoke, вы должны ссылаться на эти две библиотеки отдельно - управляемую как стандартную <Reference/> в вашем csproj и неуправляемую как связанную <content/> (как обрисовано в общих чертах) здесь ).Однако недавно я наткнулся на управляемую библиотеку-оболочку, которая не только автоматически копирует неуправляемую DLL вместе с ней во время сборки, но фактически выдает ошибку сборки, когда неуправляемая DLL отсутствует в той же директории!Это библиотека Microsoft.Z3 , в которой есть управляемая DLL (Microsoft.Z3.dll), которая оборачивает неуправляемую DLL (libz3.dll) с помощью PInvoke, поэтому вы можете использовать библиотеку в C #.

Если вы поместите две библиотеки DLL Z3 вместе в один каталог, ссылаясь только на Microsoft.Z3.dll, а затем скомпилируете свой проект с помощью msbuild, вы получите обе библиотеки DLL в выходном каталоге, даже не ссылаясь на libz3.dll!Глядя на вывод, выданный msbuild /verbosity:diag, я вижу следующие ссылки на libz3.dll:

Primary reference "Microsoft.Z3, Version=4.7.1.0, Culture=neutral, PublicKeyToken=9c8d792caae602a2". (TaskId:9)
      Resolved file path is "C:\Users\ahelwer\source\test\Framework\lib\z3\Microsoft.Z3.dll". (TaskId:9)
      Reference found at search path location "{HintPathFromItem}". (TaskId:9)
      Found embedded scatter file "libz3.dll". (TaskId:9)
      The ImageRuntimeVersion for this reference is "v4.0.30319". (TaskId:9)

...

Output Item(s): 
      _ReferenceScatterPaths=
          C:\Users\ahelwer\source\test\Framework\lib\z3\libz3.dll
                  CopyLocal=true
                  FusionName=
                  HintPath=lib\z3\Microsoft.Z3.dll
                  OriginalItemSpec=C:\Users\ahelwer\source\test\Framework\lib\z3\Microsoft.Z3.dll
                  ResolvedFrom={HintPathFromItem}
                  Version=4.7.1.0 (TaskId:9)

, что каким-то образом приводит к его копированию:

Task "Copy" (TaskId:22)
  Task Parameter:
      SourceFiles=
          C:\Users\ahelwer\source\test\Framework\lib\z3\Microsoft.Z3.dll
                  CopyLocal=true
                  FusionName=Microsoft.Z3, Version=4.7.1.0, Culture=neutral, PublicKeyToken=9c8d792caae602a2
                  HintPath=lib\z3\Microsoft.Z3.dll
                  ImageRuntime=v4.0.30319
                  OriginalItemSpec=Microsoft.Z3
                  ReferenceSourceTarget=ResolveAssemblyReference
                  ResolvedFrom={HintPathFromItem}
                  Version=4.7.1.0
          C:\Users\ahelwer\source\test\Framework\lib\z3\libz3.dll
                  CopyLocal=true
                  FusionName=
                  HintPath=lib\z3\Microsoft.Z3.dll
                  OriginalItemSpec=C:\Users\ahelwer\source\test\Framework\lib\z3\Microsoft.Z3.dll
                  ResolvedFrom={HintPathFromItem}
                  Version=4.7.1.0 (TaskId:22)
  Task Parameter:
      DestinationFiles=
          bin\Debug\Microsoft.Z3.dll
                  CopyLocal=true
                  FusionName=Microsoft.Z3, Version=4.7.1.0, Culture=neutral, PublicKeyToken=9c8d792caae602a2
                  HintPath=lib\z3\Microsoft.Z3.dll
                  ImageRuntime=v4.0.30319
                  OriginalItemSpec=Microsoft.Z3
                  ReferenceSourceTarget=ResolveAssemblyReference
                  ResolvedFrom={HintPathFromItem}
                  Version=4.7.1.0
          bin\Debug\libz3.dll
                  CopyLocal=true
                  FusionName=
                  HintPath=lib\z3\Microsoft.Z3.dll
                  OriginalItemSpec=C:\Users\ahelwer\source\test\Framework\lib\z3\Microsoft.Z3.dll
                  ResolvedFrom={HintPathFromItem}
                  Version=4.7.1.0 (TaskId:22)

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

"C:\Users\ahelwer\source\test\Framework\FrameworkTest.csproj" (default target) (1) ->
(_CopyFilesMarkedCopyLocal target) ->
  C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\bin\Microsoft.Common.CurrentVersion.targe
ts(4358,5): error MSB3030: Could not copy the file "C:\Users\ahelwer\source\test\Framework\lib\z3\libz3.dll" because it
 was not found. [C:\Users\ahelwer\source\test\Framework\FrameworkTest.csproj]

Даже если я ссылаюсь на libz3.dll встандартный способ с <content/> в моем csproj!

Вопросы:

  1. Что особенного в Microsoft.Z3.dll, что позволяет ему требовать, чтобы libz3.dll находился в том же каталогево время сборки?Был ли он скомпилирован с определенными флагами?
  2. Как добавить этот эффект в собственную библиотеку управляемых оболочек?
  3. Есть ли способ удалить этот эффект из Microsoft.Z3.dll илия должен был бы перекомпилировать это по-другому?

1 Ответ

0 голосов
/ 06 октября 2018

Это то, что CSC (компилятор C #) называет "ресурсом ссылки" .Он работает с любым типом файла.

Так, например, если у вас есть такой код в проекте DLL:

using System.Runtime.InteropServices;

namespace Microsoft.Z3
{
    public static class DoSomething
    {
        [DllImport("libz3.dll")]
        public static extern int ReturnValue(int value);
    }
}

И этот код C, экспортированный из Windows DLL:

#include "stdafx.h"

STDAPI ReturnValue(HRESULT value)
{
    return value;
}

вы можете создать .NET DLL следующим образом:

"<path to csc.exe>\csc.exe" DoSomething.cs -out:Microsoft.Z3.dll -target:library -linkresource:<path to libz3.dll>\libz3.dll

Теперь, когда вы ссылаетесь на этот новый Microsoft.Z3.dll, он будет вести себя так же, как настоящий Z3Дело в том, что он автоматически скопирует libz3.dll в сторону.

Примечание AFAIK. Visual Studio не поддерживает этот материал ссылки.

Плюс еще один недостаток - если вы хотите поддерживать несколько битов,вам нужно будет поставить два .NET DLL, один для x64 и один для x86, каждый из которых встраивает свой собственный аналог (или вам придется дублировать весь материал DllImport и т. д.).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...