Страницы

Поиск по вопросам

среда, 25 декабря 2019 г.

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

#c_sharp #c #gcc #net_core


Код на Си:

#include 
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 ();  

    


Ответы

Ответ 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# в теле вашей программы и запустить собранный проект из Терминала.

Комментариев нет:

Отправить комментарий