17

How is the way to add a C++ Library in a .NET Core project (Class Library). I tried creating a nuget package but doesn't work. I got this error:

An unhandled exception of type 'System.DllNotFoundException' occurred in "NameOfDll.dll"

When I add the nuget package the project.json add the following reference:

  "dependencies": {
    "Core": "1.0.0-*",
    "NETStandard.Library": "1.6.0",
    "NameOfDll.dll": "1.0.0"
  },
gemr1423
  • 739
  • 2
  • 11
  • 33

2 Answers2

13

dependencies attribute in project.json specifies package dependencies, because of this NuGet handles NameOfDll.dll as a package ID, but not as a dll name.

To add native C++ dlls into you NuGet package for .xproj library you should do the following steps:

  1. Put your NameOfDll.dll in \lib directory near MyClassLibrary.xproj
  2. Open project.json file and add there:

    "packOptions": {
      "files" : {
        "includeFiles" : "lib/NameOfDll.dll"
      }
    }
    
  3. Execute dotnet pack

NameOfDll.dll will be included into NuGet package under the path lib\NameOfDll.dll.

To add native C++ dlls into your NuGet package for .csproj library you should do the following steps:

  1. I assume you have managed project with name MyClassLibrary.csproj.
  2. Create new NuGet package for you class library with nuget spec command.
  3. Create \lib, \build, \content and \tools directories near MyClassLibrary.nuspec.
  4. Copy all your native dlls into the \build folder.
  5. Change extension of copied native dlls to .native.
  6. Create MyClassLibrary.targets with the following content inside \build folder:

    <?xml version="1.0" encoding="utf-8"?>
    <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      <ItemGroup>
        <AvailableItemName Include="NativeBinary" />
      </ItemGroup>
      <ItemGroup>
        <NativeBinary Include="$(MSBuildThisFileDirectory)*">
          <TargetPath></TargetPath>
        </NativeBinary>
      </ItemGroup>
      <PropertyGroup>
        <PrepareForRunDependsOn>
          $(PrepareForRunDependsOn);
          CopyNativeBinaries
        </PrepareForRunDependsOn>
      </PropertyGroup>
      <Target Name="CopyNativeBinaries" DependsOnTargets="CopyFilesToOutputDirectory">
        <Copy SourceFiles="@(NativeBinary)"
              DestinationFiles="@(NativeBinary->'$(OutDir)\%(TargetPath)\%(Filename).dll')"
              Condition="'%(Extension)'=='.native'">
          <Output TaskParameter="DestinationFiles" ItemName="FileWrites" />
        </Copy>
        <Copy SourceFiles="@(NativeBinary)"
              DestinationFiles="@(NativeBinary->'$(OutDir)\%(TargetPath)\%(Filename).%(Extension)')"
              Condition="'%(Extension)'!='.native'">
          <Output TaskParameter="DestinationFiles" ItemName="FileWrites" />
        </Copy>
      </Target>
    </Project>
    

    Hint: The .targets content is taken from this question. The above .targets file will be injected on an installation of the NuGet package into the target project file.

  7. Add the following lines into your MyClassLibrary.nuspec:

    <files>
      <file src="lib\" target="lib" />
      <file src="tools\" target="tools" />
      <file src="content\" target="content" />
      <file src="build\" target="build" />
    </files>
    
  8. Execute nuget pack MyClassLibrary.csproj to build your NuGet package.

Community
  • 1
  • 1
Nikita
  • 6,270
  • 2
  • 24
  • 37
  • Hi @gemr1423! Does it solve your problem or you need more help? – Nikita Sep 12 '16 at 21:24
  • Hi @Nikita I have a question, is the same with .xproj? – gemr1423 Sep 13 '16 at 13:08
  • @gemr1423 Info about packing of native dlls with `xproj` added. – Nikita Sep 13 '16 at 22:10
  • Hi @Nikita, I got the same error trying to execute a method of the C++ DLL in the class library project. I was done the steps that you explain without error. "Unable to load DLL 'TLHDArchive.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)" I calling the method this way: [DllImport("NameOfDll.dll", CallingConvention = CallingConvention.Cdecl)] – gemr1423 Sep 14 '16 at 14:23
  • @gemr1423 I've found an [issue](https://github.com/dotnet/cli/issues/4021) at their bug tracking system about it. `dotnet` doesn't copy included files of installed packages. According to the [release roadmap](https://github.com/dotnet/core/blob/master/roadmap.md) next 1.1 version will be available soon and you will be able to use the second proposed solution. .NET Core will migrate from `project.json` to `.csproj` and `MSBuild`. – Nikita Sep 14 '16 at 15:46
  • @gemr1423 Refer to the [Dotnet/corefxlab](https://github.com/dotnet/corefxlab) project as a sample of right `"packOptions"` usage. Component [`System.Drawing.Graphics`](https://github.com/dotnet/corefxlab/blob/71d1b2220a59d1780aafc04d42a58e15296fc96f/src/System.Drawing.Graphics/project.json#L19) uses the same approach to include `libgd.dll` native library. – Nikita Sep 14 '16 at 16:13
  • 2
    Thanks for your help @Nikita – gemr1423 Sep 14 '16 at 19:00
  • I got "The method or operation is not implemented." when trying .csproj on macOS 10.12 `$ nuget pack MyClassLibrary.csproj Attempting to build package from MyClassLibrary.csproj. System.NotImplementedException: The method or operation is not implemented.` – Anish Jun 22 '17 at 07:05
  • my nuget package maker on macOS was **2.12.0.0** and after upgrading it to **4.1.0.2450** fixed the above error _(However i am not getting a different error)_ – Anish Jun 22 '17 at 07:45
  • if `nuget pack MyClassLibrary.csproj` doesn't work then we can try `dotnet pack MyClassLibrary.csproj` – Anish Jun 22 '17 at 09:43
3

Here is a one-click way to do it in .net core 2. I used it in my website and it works.

Right click your project in Solution Explorer, select Add->Existing Item, browse and choose your dll (select show all extensions). Then your dll will appear in Solution explorer.

In the Solution Explorer, right-click your dll -> Properties. Set build action: Content, and Copy to Output Directory: Copy if newer (or always copy).

It's done. Use your dll in your code staightforward like this:

[DllImport("my_dll.dll", CallingConvention = CallingConvention.Cdecl)]
Serena Yu
  • 117
  • 2
  • 3