LINUX.ORG.RU

Объясните насчет ffi,Rust и C#

 , ,


0

4

Вот хочу я написать «ядро» программы на расте, а GUI на C#, добавил как зависимость discord-rs в Cargo toml и написал такое в lib.rs:

extern crate libc;
extern crate  discord;

use std::os::raw::c_char;
use std::ffi::CString;
use std::ffi::CStr;
use libc::c_char as cchar;

use discord::{Discord, ChannelRef, State};
use discord::model::{Event, ChannelType};
use discord::GetMessages;
use discord::model::ServerId;
#[no_mangle]
pub fn login(email: cchar, password: cchar) {
    let client = Discord::new(email, pass);
}

И в Program.cs
using System;
using System.Runtime.InteropServices;


namespace cs_rust
{



    class Program
    {
        [DllImport("libour_rust.so")]
        public static extern void login(IntPtr email, IntPtr password);
        static void Main(string[] args)
        {
            
            login(Marshal.StringToHGlobalAnsi("email"), Marshal.StringToHGlobalAnsi("pass"));
        }
    }
}

Но после добавления стороннего крейта при выполнении `dotnet run` мне выдает данную ошибочку:

Unhandled Exception: System.DllNotFoundException: Unable to load DLL 'libour_rust.so': The specified module or one of its dependencies could not be found.
 (Exception from HRESULT: 0x8007007E)
   at cs_rust.Program.login(IntPtr email, IntPtr password)
   at cs_rust.Program.Main(String[] args) in /home/aprokurov/Projects/Rust/cs_rust/Program.cs:line 21

С чем это может быть связано и как такое решается? Без крейта discord все работало

★★

The specified module or one of its dependencies could not be found

А всё ли там присутствует, что этому discord надо (что оно вообще такое?)?

anonymous ()
Ответ на: комментарий от anonymous

Это либа для доступа к Discord API, вот гитхаб, в зависимостях у него openssl,libsodium,pkg-config и 3 опциональные, отключены у меня, но и там крейтов тоже дофига hyper, serde и прочее.
.so файл лежит рядом с бинарником:

├── obj
│   ├── cs_rust.csproj.nuget.cache
│   ├── cs_rust.csproj.nuget.g.props
│   ├── cs_rust.csproj.nuget.g.targets
│   ├── Debug
│   │   └── netcoreapp2.0
│   │       ├── cs_rust.AssemblyInfo.cs
│   │       ├── cs_rust.AssemblyInfoInputs.cache
│   │       ├── cs_rust.csproj.CoreCompileInputs.cache
│   │       ├── cs_rust.csproj.FileListAbsolute.txt
│   │       ├── cs_rust.csprojResolveAssemblyReference.cache
│   │       ├── cs_rust.dll
│   │       ├── cs_rust.pdb
│   │       └── libour_rust.so
│   └── project.assets.json
├── Program.cs

playX ★★ ()
Последнее исправление: playX (всего исправлений: 1)

LD_LIBRARY_PATH задал? Библиотеку в правильное место положил? Ты не можешь просто так загрузить .so из текущего рабочего каталога.

intelfx ★★★★★ ()

А ты вообще пробовал компилировать твой проект на расте? Я вот смотрю на твой код и он ну нифига не скомпилится. Discord::new принимает на вход две строки а ты ему два символа даешь. Хотя из сишарпа у тебя там указатели приходят, это никак не будет работать.

pftBest ★★★★ ()
Ответ на: комментарий от pftBest

Да я про это знаю, там у меня конвертация есть через `&format!(«{:?}», email)` и т.д

playX ★★ ()
Ответ на: комментарий от playX

И она нормально грузится если это просто библиотека, без сторонних крейтов(кроме libc)

playX ★★ ()

Сделай общение с гуем через ipc (стандартные потоки, например). Раст тебе будет писать на вход гуя на сs, а гуй будет отвечать расту в стандартный ввод. Там ты парсишь json и делаешь что тебе надо. Извращайся, пока молодой. Не трать время на примитивное формошлепство.

crutch_master ★★★★★ ()
Последнее исправление: crutch_master (всего исправлений: 1)

А не проще просто взять gRPC? Для руста вроде генератор имеется.

Unicode4all ★★★★★ ()
Ответ на: комментарий от playX

Сдается мне, что надо собрать все эти либы и подложить их вместе. Может быть, у карго есть такой режим сборки. Не смотрел?

dave ★★★★★ ()
Ответ на: комментарий от playX

И когда я последний раз бегло изучал вопрос, то обнаружил, что у cargo есть 5-7 разных режимов сборки либ, если не больше. Для разных случаев

dave ★★★★★ ()
Ответ на: комментарий от dave

Вот как раз и собираю динамическую библиотеку:


[lib]
name="our_rust"
crate-type = ["dylib"]

playX ★★ ()

Как минимум передать строки в функцию, принимающую c_char (один байт) у тебя не получится.

mersinvald ★★★★★ ()
Ответ на: комментарий от dave

staticlib тоже не сработал:

Unable to load DLL 'libour_rust.a': The specified module or one of its dependencies could not be found.


mersinvald у меня все конвертируется данным образом:
let client = Discord::new(&format!("{:?}",email), &format!("{:?}",password));

Если надо в C# обратно получить текст то просто вызываю Marshal.PtrToStringAnsi

playX ★★ ()
Ответ на: комментарий от dave

Посмотрел я еще раз эту страничку и наткнулся на cdylib, с этим все заработало, правда оказывается я не много не так переносил строки C# и в итоге сделал так:

pub fn login(email: *const cchar, password: *const cchar) {
    let format_email: &CStr = unsafe {
        CStr::from_ptr(email)
    };
    let stri = std::str::from_utf8(format_email.to_bytes()).unwrap();
    println!("{}", stri);
    let format_pass: &CStr = unsafe {
        CStr::from_ptr(password)
    };

    let stri2 = std::str::from_utf8(format_pass.to_bytes()).unwrap();
    println!("{}", stri2);
    let client = Discord::new(&format!("{}",stri), &format!("{}",stri2)).expect("Error happened");
    
}

public static extern void login(string email,string password);

playX ★★ ()

Кастани, когда «опакетишь» это под nixos, я хочу это увидеть.

t184256 ★★★★★ ()
Ответ на: комментарий от t184256

А в чем прикол? Я сильно много пакетов не пилил под Nix, да и на Федору уже съехал

playX ★★ ()
Ответ на: комментарий от playX

В том, что там нормальный код тяжело пакетить, а тут уж с ежом.

t184256 ★★★★★ ()
Ответ на: комментарий от t184256

Юзай дебиан, там легко пакетить.

anonymous ()
Ответ на: комментарий от anonymous

Я наоборот, с дебиана мигрирую на nixos.

И да, в дебиане легко пакетить только когда плевать на качество результата. Нормально пакетить в дебиане не проще.

«пакетить» в моем том комменте стоит в кавычках, потому что там подразумевалось хотя бы все зависимости в один derivation собрать

t184256 ★★★★★ ()
Последнее исправление: t184256 (всего исправлений: 1)
Ответ на: комментарий от t184256

Че там сложного? Каких-то 10-15 служебных файликов на пакет, debuild, pbuilder, git-buildpackage, lintian, debdiff, interdiff, килотонна-другая хелперов из говна и баша. Ето ж елементарно.

anonymous ()
Ответ на: комментарий от anonymous

«сложно» - не антоним «легко», «сложно» - антоним «просто», а для «легко» антонимом будет «трудно».

t184256 ★★★★★ ()
Ответ на: комментарий от anonymous

Спросил насчет раста и си шарпа, а срачь устроили насчет Debian и NixOS

playX ★★ ()
Ответ на: комментарий от playX

Для растишки есть carnix, он из Cargo.lock генерирует готовое nix-выражение, руками вообще ничего писать не надо. Далее просто юзаешь его как зависимость для сисярп-части.

anonymous ()
Ответ на: комментарий от playX

Я прочитал тред, я тебе говорю о том что это бред: ты не можешь запихать указатель в один байт.

mersinvald ★★★★★ ()
Ответ на: комментарий от mersinvald

Но ведь это все работает,тогда в чем проблема? Сейчас вообще переключился на использование serde и Json.NET

playX ★★ ()
Ответ на: комментарий от playX

Проблема в том что это UB и загадка тут скорее в том какого черта у тебя это вообще работает со вторым аргументом.

mersinvald ★★★★★ ()
Ответ на: комментарий от mersinvald

Я насчет этого еще и в gitter/ru_rust поспрашивал, тов.Pzixel кинул пример где используется callback(): link и как я понял это самый верный вариант?

playX ★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.