Не удалось загрузить 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.