Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[Looking for Suggestion] Unable to find assembly: SkiaSharp#2589

Unanswered
chaojian-zhang asked this question inQ&A
Discussion options

(Originally an issue:#2588)

Hi, thanks for the great library! It has been tremendously helpful in both my personal and professional life!

Right now I am encountering a problem that might not be pythonnet specific but is not obvious to solve and encountered when I use Pythonnet. Specifically, when my project references SkiaSharp which contains native dlls, pythonnet will not be able to load everything properly - it locates the entry assembly fine, but the dependencies are not loaded. The initial import is ok but during runtime an exception is thrown.

Would love to hear any suggestions on solving this problem.

Environment

  • Pythonnet version: 3.0.5
  • Python version: 3.11.9 64bit
  • Operating System: Windows 7 64-bit

Below is the entry assembly, which directly references SkiaSharp.

<ProjectSdk="Microsoft.NET.Sdk">  <PropertyGroup>    <OutputType>Exe</OutputType>    <TargetFramework>net8.0</TargetFramework>    <ImplicitUsings>enable</ImplicitUsings>    <Nullable>enable</Nullable>  </PropertyGroup>  <ItemGroup>    <PackageReferenceInclude="SkiaSharp"Version="3.119.0" />  </ItemGroup></Project>
usingSkiaSharp;namespacePythonNetSkiaSharpProblem{publicclassProgram{publicstaticvoidMain(string[]args){try{varinfo=newSKImageInfo(width:64,height:64);usingvarsurface=SKSurface.Create(info);SKCanvascanvas=surface.Canvas;canvas.Clear(newSKColor(red:0,green:200,blue:200,alpha:255));usingSKImageimage=surface.Snapshot();usingSKDatapngData=image.Encode(SKEncodedImageFormat.Png,quality:100);conststringoutputPath="filled64.png";usingvarstream=File.OpenWrite(outputPath);pngData.SaveTo(stream);System.Console.WriteLine($"Saved{outputPath}");}catch(Exceptione){Console.WriteLine(e);}}}}

And this is how I am referencing the entry assembly,from some location outside the published folder (notice the same problem happens even if this script is placed directly inside the published folder).

importsyssys.path.insert(0,r"C:\Users\Charles Zhang\Desktop\Temp\PythonNetSkiaSharpProblem\PythonNetSkiaSharpProblem\bin\Debug\net8.0")importpythonnetpythonnet.load("coreclr")importclrclr.AddReference("PythonNetSkiaSharpProblem")fromPythonNetSkiaSharpProblemimportProgramProgram.Main([])# Exception in stack

Output:

System.TypeInitializationException: The type initializer for 'SkiaSharp.SKImageInfo' threw an exception. ---> System.DllNotFoundException: Unable to load DLL 'libSkiaSharp' or one of its dependencies: The specified module could not be found. (0x8007007E)   at SkiaSharp.SkiaApi.sk_colortype_get_default_8888()   at SkiaSharp.SkiaApi.sk_colortype_get_default_8888()   at SkiaSharp.SKImageInfo..cctor()   --- End of inner exception stack trace ---   at SkiaSharp.SKImageInfo..ctor(Int32 width, Int32 height)   at PythonNetSkiaSharpProblem.Program.Main(String[] args) in C:\Users\Charles Zhang\Desktop\Temp\PythonNetSkiaSharpProblem\PythonNetSkiaSharpProblem\Program.cs:line 11

This is likely due to this folder structure:

└───net8.0    │   PythonNetSkiaSharpProblem.deps.json    │   PythonNetSkiaSharpProblem.dll    │   PythonNetSkiaSharpProblem.exe    │   PythonNetSkiaSharpProblem.pdb    │   PythonNetSkiaSharpProblem.runtimeconfig.json    │   SkiaSharp.dll    │    └───runtimes        ├───osx        │   └───native        │           libSkiaSharp.dylib        │        ├───win-arm64        │   └───native        │           libSkiaSharp.dll        │        ├───win-x64        │   └───native        │           libSkiaSharp.dll        │        └───win-x86            └───native                    libSkiaSharp.dll

See:https://github.com/Charles-Zhang-Python/PythonNetSkiaSharpProblem

This might be related to#468 but is somewhat different since I am not loading the dll directly, and everything is .Net 8 properly.

You must be logged in to vote

Replies: 2 comments 2 replies

Comment options

Notice a workaround is to copylibSkiaSharp.dll directly to the root of the published folder.
But this won't work cross-platform and also if we have many similar libraries that exhibit similar behavior then it's not convenient.

You must be logged in to vote
0 replies
Comment options

  1. Your link is not working
  2. You are creating an executable, not a library
  3. Please try usingdotnet publish
You must be logged in to vote
2 replies
@filmor
Comment options

I tried it, publishing asdotnet publish -r win-x64 -o some_place works fine and publishes the correctlibSkiaSharp.dll along with it. I can't test it further without hassle as there is no Linux version in the nuget.

@chaojian-zhang
Comment options

Hi@filmor, thanks for the reply. I've fixed the repo link.

I am aware that dotnet publish with a target runtime will work. That's because it will copy the specific dlls to the root folder. It's however just workarounded the problem, rather than fixed it. Like I commented out above.
However this will not work with a non-platform dependent publish nor a general build (instead of publishing). To test it, you don't need to have linux version per se: just doBuild All in visual studio and use that output inbin/debug/net8.0-windows as the folder to test against.

Regarding "You are creating an executable, not a library", that shouldn't be a problem since in dotnet all executables are just dlls, the.exe is just a thin shells that calls into the.dll. In python (with pythonnet) we just load the dll.

In the meantime, I did find a more robust way to load the dlls from the python side. One workaround is to add below class and make available to python script:

publicsealedclassPluginLoadContext:AssemblyLoadContext{readonlyAssemblyDependencyResolverresolver;publicPluginLoadContext(stringpluginMainDll)=>resolver=new(pluginMainDll);protectedoverrideAssembly?Load(AssemblyNamename)=>resolver.ResolveAssemblyToPath(name)is{}p?LoadFromAssemblyPath(p):null;protectedoverrideIntPtrLoadUnmanagedDll(stringlibName)=>resolver.ResolveUnmanagedDllToPath(libName)is{}p?LoadUnmanagedDllFromPath(p):IntPtr.Zero;}

Then, instead of loading using clr.AddReference, call below:

ctx=PluginLoadContext(str(dll_path))asm=ctx.LoadFromAssemblyPath(str(dll_path))# Equivalent to clr.AddReference(asm), notice "import" works out of the box due to Pythonnet's hook into the import process
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Category
Q&A
Labels
None yet
2 participants
@chaojian-zhang@filmor
Converted from issue

This discussion was converted from issue #2588 on May 02, 2025 13:13.


[8]ページ先頭

©2009-2025 Movatter.jp