Не удалось загрузить DLL 'libdl' при использовании пакета System.Drawing.Common NuGet на AWS Lambda
У нас есть лямбда-функция генератора эскизов, которую я пытаюсь обновить до .NET Core 2.0, но я столкнулся со следующей ошибкой при использовании пакета Microsoft System.Drawing.Common
NuGet:
TypeInitializationException
Инициализатор типа для Gdip выдал исключение. в System.Drawing.SafeNativeMethods.Gdip.GdipCreateBitmapFromScan0 (ширина Int32, высота Int32, шаг Int32, формат Int32, HandleRef scan0, IntPtr & bitmap) в System.Drawing.Bitmap..ctor (ширина Int32, высота Int32, формат PixelFormat) в TestailExEx.Function.FunctionHandler (ввод строки, контекст ILambdaContext) в C:\work\graphics\TestFailExample\Function.cs: строка 25 в lambda_method (закрытие, поток, поток, LambdaContextInternal)
вызванный
DllNotFoundException
Невозможно загрузить DLL 'libdl': указанный модуль или одна из его зависимостей не найдены. \N (Исключение из HRESULT: 0x8007007E) в Interop.Libdl.dlopen (флаг String fileName, Int32) в System.Drawing.SafeNativeMethods. Gdip.LoadNativeLibrary() в System.Drawing.SafeNativeMethods.Gdip..cctor()
Я видел этот вопрос, но не было никакого решения.
Минимальный код для воспроизведения проблемы:
public string FunctionHandler(string input, ILambdaContext context)
{
using (var bmp = new Bitmap(100, 100))
{
return bmp.Width.ToString();
}
}
Просто создайте проект лямбда-функции .NET Core 2.0, добавьте ссылку на пакет NuGet System.Drawing.Common
и замените обработчик функции приведенным выше кодом. Подбрось его на AWS и запусти, чтобы получить ошибку. Я заметил, что ссылка на пакет не вызывает проблем, пока вы не попытаетесь его использовать, но это может быть связано с оптимизацией компилятора.
Я упаковал MCVE в проект и загрузил его на GitHub здесь, чтобы упростить шаги, которые люди должны пройти, чтобы воспроизвести проблему.
Я вижу, что /lib64/libdl.so.2
существует, но /lib64/libdl.so
нет. Поскольку символическая ссылка не представляется возможной (файловая система только для чтения), я не уверен, как решить эту проблему. Я попытался использовать LD_LIBRARY_PATH
окружения LD_LIBRARY_PATH
, создав папку в /tmp
и вставив туда символическую ссылку, как первое, что делает функция. К сожалению, кажется, что здесь ищут все библиотеки, поэтому функция вообще не запускается. Я также попытался установить LD_LIBRARY_PATH
в /var/lang/lib: /lib64: /usr/lib64: /var/runtime: /var/runtime/lib: /var/task: /var/task/lib: /tmp
и, хотя теперь я мог запустить функцию снова, это все равно не помогло, и я просто получаю ту же ошибку Gdip.
Я отметил, что /var/task/lib уже включен в LD_LIBRARY_PATH, поэтому я попытался упаковать libdl.so и libgdiplus.so с моей функцией, но это также не удалось, на этот раз заявив, что точка входа GdiplusStartup
не найдена в libdgiplus.so
Эти файлы были не из экземпляра Amazon Linux, поэтому я попытался установить Mono и получить их из экземпляра Amazon Linux. Это не помогло.
Я пробовал с библиотекой рисования CoreCompat, но это также сообщает о проблемах, связанных с libgdiplus.so
, даже если я пытаюсь связать это с функцией.
С тех пор я пробовал на своем собственном экземпляре Linux и могу подтвердить, что System.Drawing.Common
работает.
Есть ли какое-нибудь умное решение, которое позволит мне использовать System.Drawing.Common
на AWS Lambda? Есть ли другой способ, которым я могу выдумать мою лямбда-функцию, чтобы иметь libdl и работать?
Обновить:
Наша последняя попытка включала использование AWS Lambda Layers и тщательное извлечение всех пакетов, установленных apt в образе Docker Amazon Linux, а затем применение их к их собственному слою. Тем не менее, мы в конечном итоге перешли к проблеме "libdl", поэтому мы сдались.
Многие проблемы с библиотеками, предложенные людьми, заключаются в том, что они неправильно отображают японский текст, что важно для нас. Похоже, что это проблема, которая не улучшится на AWS Lambda, она не помогла, и в конечном итоге было проще переписать нашу функцию в Go, чем продолжать использовать С# для этого.
Поскольку библиотеки, упомянутые в ответах ниже, кажутся подходящими для общего использования - и могут действительно поддерживать текст на японском языке - я решил принять ответ, который, я уверен, будет работать на AWS Lambda.
Ответы
Ответ 1
Для обработки изображений в.NET Core Lambda я использую SixLabors.ImageSharp
Вот код, который я использовал в недавнем отзыве AWS re: Invent, который сделал журнал, если обработка изображений:
var imageBuffer = new MemoryStream();
var resizeOptions = new ResizeOptions
{
Size = new SixLabors.Primitives.Size { Width = this.TileSize, Height = this.TileSize},
Mode = ResizeMode.Stretch
};
image.Mutate(x => x.Resize(resizeOptions));
image.Save(imageBuffer, new SixLabors.ImageSharp.Formats.Jpeg.JpegEncoder());
imageBuffer.Position = 0;
Ответ 2
У меня возникла та же проблема после загрузки приложения на сервер Ubuntu 18 с версией dotnet core 2.1.500. Я решил эту проблему с помощью этого решения https://github.com/dotnet/dotnet-docker/issues/618, используя предложения MichaelSimons.
Я побежал
#sudo apt-get update
#sudo apt-get install -y --allow-unauthenticated \
libc6-dev \
libgdiplus \
libx11-dev \
#sudo rm -rf /var/lib/apt/lists/*
Это решило проблемы.
Ответ 3
Я нашел решение этой проблемы, которое сработало для меня:
Сначала я удалил библиотеку System.Drawing.Common из проекта, затем я установил библиотеку, которую вы можете найти здесь. Он использует те же классы.
using System.Drawing
...
var bmp = new Bitmap(100,100);
Наконец я установил эту другую библиотеку, которая содержит все необходимые библиотеки dll для использования библиотек рисования в Linux и Lambda. Выполняя эти шаги, код может быть загружен в AWS без каких-либо проблем.
Ответ 4
А мне, мне, конечно, есть пример
- sudo apt-get установить libgdiplus
Despues
- cd/usr/lib
- sudo ln -s libgdiplus.so gdiplus.dll
у пор ультимо
- RUN dotnet restore en tu proyecto
- RUN dotnet опубликовать
y demas comando dotnet que hagan falta.