CppSharp пользовался кто-нибудь? (использование C++ библиотек в C#)

Это дичь если честно … :scream:
Оно не компилится… LLVM какую то хочет …

Да проблема была при попытке создать дебажный вариант. Релиз вроде скомпилился

Как ее пользовать то теперь?? собралась вроде нормально.

хз, я не пробовал, я про LLVM говорил.

В Ultralight думаю тоже нет ключа по умолчанию.

Тоска … ну да ладно. Тут вроде сфинкс наладился. Но надо бы его приклеить к шарпу.
Не могу разобраться с библой CppSharp. Как ее пользовать то?? Я предполагал ей подсунуть либу на сях и она мне обертку сформирует по функциям??
А тут вроде исходники нужны … Или нет. Пользовался ктонидудь?

Да, там ж написано

It consumes C/C++ header and library files and generates the necessary glue code

То есть оно по идее избавляет от ручного написания всяких DllImport, структур и т.д.
https://github.com/mono/CppSharp/blob/master/docs/GeneratingBindings.md

Сча сам пробую колупаться. По идее там надо указать хидеры и сопоставить с .lib’ами откуда берутся импорты для dll. Потом посмотреть какую чехарду генерирует из крестов и править это регулярками и проч. (смотрю на то как сделан ChakraSharp) в итоге выкатывается шарповый класс со всеми обвязками.

В общем почти получилось. Собрал хидеры и либы сфинкса в кучу. Но при сборке ругается что не видил библиотек Windows Kits

C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\ucrt\corecrt_wstdio.h(1348,29): error: no matching function for call to ‘__stdio_common_vswprintf’
C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\ucrt\corecrt_wstdio.h(1366,16): error: no matching function for call to ‘_vscwprintf_l’
C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\ucrt\corecrt_wstdio.h(1381,29): error: no matching function for call to ‘__stdio_common_vswprintf_p’
C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\ucrt\corecrt_wstdio.h(1399,16): error: no matching function for call to ‘_vscwprintf_p_l’
C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\ucrt\corecrt_wstdio.h(1457,19): error: no matching function for call to ‘__vswprintf_l’
C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\ucrt\corecrt_wstdio.h(1477,19): error: no matching function for call to ‘_vswprintf_c_l’
C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\ucrt\corecrt_wstdio.h(1542,23): error: no matching function for call to ‘_vswprintf_s_l’

А как подключить по умолчанию не понял. Неужели все либы надо руками прописывать.

наоборот же вроде, библиотеки ругаются )
Точнее ошибки странные, там после например no matching function for call to ‘__stdio_common_vswprintf’ ничего больше нет в этой ошибке?

таких ошибок куча. Это копия ошибки.
Тут еще вот какая ошибка лезет:

Error parsing ‘C:\Delme\WindowsFormsApp1\src\sphinxbase\yin.h’
C:\Delme\WindowsFormsApp1\src\sphinxbase\yin.h(113,1): error: extraneous closing brace (’}’)
CppSharp has encountered an error while parsing code.

Вот сюда кидает:
image

Где должен этот дефайн определяться?? или не должен. В оригинальном проекте на сях проблем при сборке нету.

В дополнительных зависимостях в оригианльном проекте указана winmm.lib а тут куда ее впихнуть то?

я о том, что после no matching function for call to ‘__stdio_common_vswprintf’ обычно пишется причина, например, передали char вместо wchar_t потому что включен флаг о юникоде и вызывается W версия функции вместо A.

А это где? В VS Linker -> Input в настройках проекта.

Да не. Я так понимаю что я должен в параметры CppSharp задать эти зависимости.

При запуске генерации?

Тут есть пример https://github.com/mono/CppSharp/blob/master/docs/GeneratingBindings.md

void Setup(Driver driver)
{
    var options = driver.Options;
    options.GeneratorKind = GeneratorKind.CSharp;
    var module = options.AddModule("Sample");
    module.IncludeDirs.Add("C:\Sample\include");
    module.Headers.Add("Sample.h");
    module.LibraryDirs.Add("C:\Sample\lib");
    module.Libraries.Add("Sample.lib");
}
    public void Setup(Driver driver)
    {
        var options = driver.Options;
        options.GeneratorKind = GeneratorKind.CSharp;
        var module = options.AddModule("pocketsphinx");

        module.IncludeDirs.Add(@"C:\Delme\WindowsFormsApp1\src");
        module.IncludeDirs.Add(@"C:\Delme\WindowsFormsApp1\src\pocketsphinx");
        module.IncludeDirs.Add(@"C:\Delme\WindowsFormsApp1\src\sphinxbase");
        foreach (var file in Directory.GetFiles(@"C:\Delme\WindowsFormsApp1\src", "*.h", SearchOption.AllDirectories))
        {
            module.Headers.Add(file);
        }

        module.Defines.AddRange(new string[] {
                            "NDEBUG",
                            "_USRDLL",
                            "SPHINX_DLL",
                            "SPHINXBASE_EXPORTS",
                            "HAVE_CONFIG_H",
                            "_CRT_SECURE_NO_DEPRECATE"
        });

        AddLibraries(module, @"C:\Delme\WindowsFormsApp1\src\lib");
        //AddLibraries(module, @"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x86");
        //AddLibraries(module, @"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\um\x86");
        //AddLibraries(module, @"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0");           
    }

это откуда? Вроде ж надо module.Libraries.Add.

Моя функция которая добавляет папку и все либы из подпапок

Короче выкинул я эту CppSharp в помойку. Не вижу объективного смысла пользовать ее. Слишком много пытается навесить. С помощью классического DllImport натискал функций из либы, перенес структуры и все нормально заработало. Движок инициализировался успешно.
В чем преимущество CppSharp так и осталось загадкой.

Ну он по идее просто время экономит (и уменьшает риск ошибки при написании импортов), особенно если либа большая и в ней какие-то сложные структуры.
Там в примерах внизу огромные фреймворки типа Qt, запаришься же при каждом релизе искать все изменения и переписывать.

Попробую завтра на нескольких либах.

Попробуйте на сфинксе

Попробовал пока на своей небольшой библиотеке с C API, статически собранной в VS 2017.

Особых проблем с запуском не было: поставил CppSharp из NuGet в проект, адаптировал пример с https://github.com/mono/CppSharp/blob/master/docs/GeneratingBindings.md, получил Sample.cs в bin.

using CppSharp;
using CppSharp.AST;
using CppSharp.Generators;

namespace CppSharpExample
{
    class SimpleCBindingGenerator : ILibrary
    {
        public void Setup(Driver driver)
        {
            var options = driver.Options;
            options.GeneratorKind = GeneratorKind.CSharp;

            var module = options.AddModule("Sample");
            module.IncludeDirs.Add(@"C:\Users\Alex\Downloads\libmy\src\libmy");
            module.Headers.Add("libmy.h");
            module.LibraryDirs.Add(@"C:\Users\Alex\Downloads\libmy\dll\x64");
            module.Libraries.Add("libmy.lib");
        }

        public void SetupPasses(Driver driver)
        {
        }

        public void Preprocess(Driver driver, ASTContext ctx)
        {
        }

        public void Postprocess(Driver driver, ASTContext ctx)
        {
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            ConsoleDriver.Run(new SimpleCBindingGenerator());
        }
    }
}

LLVM там нужен только для сборки CppSharp из исходников или и для использования тоже? У меня он уже был установлен через Chocolatey.

Была небольшая сложность с тем, что оно не понимало uint8_t, uint64_t, но это видимо моя недоработка, заработало после добавления #include <cstdint>.

Сгенерированный код получился сложноватый, например, какой-то большой класс вместо просто struct с [StructLayoutAttribute(LayoutKind.Sequential)].

У всех импортированных функций добавлен EntryPoint. Насколько я знаю, это нужно для C++ классов и т.п., а для обычных C функций можно и не добавлять если имя то же.

Еще сами импорты в __Internal и вызываются в функциях-обертках. Во многих просто вызов, но в некоторых например null колбэки конвертируются в IntPtr.Zero. Я сам так не делал, не знаю нужно ли.

Как я понял, там много возможностей менять вывод через обход дерева (AST) в Passes и т.п. и опции, так что наверно можно упростить если надо.

В целом конечно для просто импорта пары функций в проекте можно не брать CppSharp, а вот если делать и поддерживать полноценные биндинги для какой-то большой библиотеки, то уже есть смысл автоматизировать.
Примерно как со сборкой/деплоем проекта, настройкой серверов. Для экспериментов и т.п. можно и просто в консоли пару раз команды повводить, а вот если нормально делать надолго, то лучше разобраться с системами сборки, деплоя и прочей автоматизацией.

Для маленьких проектов да. а вот для сфинкса и сфинспокет??

Ну его же даже для Qt и других больших проектов используют https://gitlab.com/ddobrev/QtSharp/blob/master/QtSharp/QtSharp.cs

А Сфинкс разве сам не предоставляет биндинги для C#?
https://sourceforge.net/p/cmusphinx/discussion/help/thread/fb985d4d/