CLR/System.EntryPointNotFoundException при запуске неуправляемого кода на Си из программы на C# в среде Linux

190
20 января 2019, 05:20

Код на Си:

#include <stdio.h>
void main()
{
    printf("Hello world\n");
}

Команда сборки этого кода в модуль main.dll для Терминала Linux:

gcc main.c -o main.dll

Вызывающий код на C# (сборка dllimportc.dll):

using System;
using System.Runtime.InteropServices;  
namespace netcore
{
    class Program
    {
        static void Main()
        {
            Console.WriteLine("Hello World!");
            main();
            Console.ReadLine();
        }
        [DllImport("main.dll", EntryPoint = "main", CallingConvention = CallingConvention.Cdecl)]
        public static extern void main ();
    }
}

На вызове main(); возникает исключение:

Exception has occurred: CLR/System.EntryPointNotFoundExceptionAn unhandled exception of type 'System.EntryPointNotFoundException' occurred in dllimportc.dll: 'Unable to find an entry point named 'main' in shared library 'main.dll'.' at dllimportc.Program.main() at dllimportc.Program.Main()

Как откорректировать программу, чтобы .Net Core в консольном приложении находил точку входа и Hello World выводился два раза без исключений?

ОБНОВЛЕНО В коде выше библиотека в Linux создавалась неправильно. Правильные инструкции можно подсмотреть здесь - Создание библиотеки в Linux. Для Ubuntu 18.04 LTS пришлось добавить возвращаемый тип в функцию на Си и вместо команды

ldconfig -v -n .

использовать

ldconfig -v -n -l main.so.0.0

ОБНОВЛЕНО 06.10.2018

Можно проще: использовать для сборки только команду

gcc -o main.so -s -shared -O2 main.c -m64

Затем подкладываем main.so в bin, и в C# для .Net Core всё просто:

 [DllImport("main.so")]
  public static extern void main ();  
Answer 1

Для подключения через extern внешний код должен быть собран как библиотека. Для этого можно в Linux использовать для сборки команду (предварительно должен быть установлен компилятор GCC, если его не было в системе):

gcc -o main.so -s -shared -O2 main.c -m64

Для библиотеки наличие функции main не обязательно. Исходный файл на чистом Си main.c эта команда скомпилирует в библиотеку (за это отвечает флаг shared) main.so (в Linux рекомендуется называть библиотеки с префиксом lib и давать им расширение so). Флаги s и O2 отвечают за оптимизацию для продуктива, а флаг m64 настраивает принудительную сборку для платформы x64. Затем подкладываем main.so в подпапку папки bin, где лежит собранный файл вашего проекта, и в C# для .Net Core всё просто:

  [DllImport("main.so")]
  public static extern void main (); 

Чтобы увидеть текстовое сообщение из внешней библиотеки, можно собрать проект .Net Core как консольное приложение, сделать вызов main() как обычного метода C# в теле вашей программы и запустить собранный проект из Терминала.

READ ALSO
Как поднять приоритет слоя Ignore Raycast?

Как поднять приоритет слоя Ignore Raycast?

На Terrain стоит rigitbody объект с Mesh RendererПри перемещении его с помощью курсора мыши мы временно меняем его слой на Ignore Raycast и он частично погружается...

181
Отменить remote валидацию для определённого action

Отменить remote валидацию для определённого action

Можно ли как нибудь отменить действие валидации Remote на определённой странице представления?

176
Как отрисовать данную ветку интерфейса WPF

Как отрисовать данную ветку интерфейса WPF

Имеется данный кусочек интерфейса, нужно его отрисовать, но не знаю как, подскажитеБыл бы благодарен если ещё и с объяснением, сфера новая,...

167
PHP Конвертер кукисов с netscape в json

PHP Конвертер кукисов с netscape в json

Нашел скрипт на просторах сети, конвертер cookies файлов формата Netscape в формат JSONНо почему-то у меня вместо JSON Cookies в файл cookies

499