Автор Гілка: як в fsharp передати struct by reference?  (Прочитано 7678 раз)

Відсутній lpi3

  • Новачок
  • *
  • дописів: 30
  • Карма: +0/-0
Вітаю!
Чи є тут ті хто пише на c# f# під моно?

Є наступна бібліотека на С:

Код: C
  1. struct Data {
  2.   int a;
  3. };
  4.  
  5. void f(struct Data *p, int i) {
  6.   p->a = i;
  7. }
  8.  
компілюю gcc -shared -fPIC -o libmylib.c mylib.c

І також є наступний код на c#:
Код: C#
  1. using System.Runtime.InteropServices;
  2.  
  3. [StructLayout(LayoutKind.Sequential)]
  4. public struct Data
  5. {
  6.   public int ch;
  7. }
  8.  
  9. public class C {
  10.   [DllImport("libmylib.so")]
  11.   private static extern void f(ref Data a, int i);
  12.  
  13.   public static void Main(string [] args) {
  14.     Data d;
  15.     d.ch = 0;
  16.     f(ref d, 12);
  17.     System.Console.WriteLine(d.ch.ToString());
  18.   }
  19. }
  20.  
тут сворюється структура Data, яку успішно модифікує виклик f(ref d, 12).

Також є код на f#:
Код: F#
  1. open System.Runtime.InteropServices
  2.  
  3. [<StructLayout(LayoutKind.Sequential)>]
  4. type Data = struct
  5.   val mutable ch : int
  6.   new (v) = {ch = v}
  7. end
  8.  
  9. [<DllImport("libmylib.so")>]
  10. extern void f([<MarshalAs(UnmanagedType.LPStruct)>] Data data , int)
  11.  
  12. let () =
  13.   let mutable data = new Data(0) in
  14.   f(data, 12);
  15.   printfn "%d" data.ch
  16.  
який чомусь не працює (data.ch залишається не змінною (хоч не падає :))

Питання:
1. Чи правильно я роблю?
2. Як у f# передати Data by reference?
2. Чому такий код на с# теж не працює (d.ch не змінюється):
Код: C#
  1. ...
  2. [DllImport("libmylib.so")]
  3.   private static extern void f([MarshalAs(UnmanagedType.LPStruct)] Data a, int i); // <-зміни тут
  4.  
  5.   public static void Main(string [] args) {
  6.     Data d;
  7.     d.ch = 0;
  8.     f(d, 12); // <- і тут
  9.     System.Console.WriteLine(d.ch.ToString());
  10.   }
  11. ...
  12.  

Дякую заздалегідь!
« Змінено: 2018-02-16 19:04:01 від lpi3 »

Відсутній lpi3

  • Новачок
  • *
  • дописів: 30
  • Карма: +0/-0
Re: як в fsharp передати struct by reference?
« Відповідей #1 : 2018-02-16 16:48:09 »
Знайшов відповідь сам :) Нібито передавати struct by reference правильно. Можна без атрибутів.

Референси в f# передають так:
Код: F#
  1. open System.Runtime.InteropServices
  2.  
  3. [<StructLayout(LayoutKind.Sequential)>]
  4. type Data = struct
  5.   val mutable ch : int
  6.   new (v) = {ch = v}
  7. end
  8.  
  9. [<DllImport("libmylib.so")>]
  10. extern void f(Data & data, int) (* між Data_&_data мають бути пробіли по обидва боки від оператора & *)
  11.  
  12. let () =
  13.   let mutable data = new Data(0) in
  14.   f(&data, 12);
  15.   printfn "%d" data.ch
  16.  
Я пробіл не писав, робив як у с++ Data &data, тому такий варіант не компілювався взагалі.
От такі справи
« Змінено: 2018-02-16 19:04:43 від lpi3 »

Відсутній xuser13

  • Графоман
  • ****
  • дописів: 480
  • Карма: +0/-0
Re: як в fsharp передати struct by reference?
« Відповідей #2 : 2018-02-27 11:09:06 »
А ящо ви таке під Mono пишите:? Хіба воно не мервто?
чи планетяне щче не подали блакитне свитло?

Відсутній prapor

  • Письменник
  • *****
  • дописів: 518
  • Карма: +0/-0
Re: як в fsharp передати struct by reference?
« Відповідей #3 : 2018-02-27 13:33:08 »
А ящо ви таке під Mono пишите:? Хіба воно не мервто?
Живіше усіх живих. Для Web, до речі, вже пристойно замінює IIS
- I'm afraid your son has the knack.
- The knack?
- The knack. It's a rare condition characterised by an extreme intuition about all things mechanical and electrical. And utter social ineptitude.
- Can he lead a normal life?
- No, he'll be an engineer.

Відсутній xuser13

  • Графоман
  • ****
  • дописів: 480
  • Карма: +0/-0
Re: як в fsharp передати struct by reference?
« Відповідей #4 : 2018-02-27 19:41:03 »
Немає інтеграції з GTK+ 3.x нових версій. Файлів створених в Glade з описом GUI не завантажує. Програми написані на Mono особливо не підтримують або їх переписують на щось інше (наприклад Tomboy).
чи планетяне щче не подали блакитне свитло?

Відсутній prapor

  • Письменник
  • *****
  • дописів: 518
  • Карма: +0/-0
Re: як в fsharp передати struct by reference?
« Відповідей #5 : 2018-02-27 19:47:13 »
Ну так, після офіційного релізу .Net for Linux воно має проблеми, але все ще живе.
- I'm afraid your son has the knack.
- The knack?
- The knack. It's a rare condition characterised by an extreme intuition about all things mechanical and electrical. And utter social ineptitude.
- Can he lead a normal life?
- No, he'll be an engineer.

Відсутній lpi3

  • Новачок
  • *
  • дописів: 30
  • Карма: +0/-0
Re: як в fsharp передати struct by reference?
« Відповідей #6 : 2018-03-12 18:36:12 »
А ящо ви таке під Mono пишите:? Хіба воно не мервто?
Ну як сказати, мені аби працювало. І працює ніби добре :)

Взагалі то мені цікавий ocaml, але f#, здається, більш розвинутий в плані батарейок.

Відсутній Володимир Лісівка

  • Адміністратор ЩОДО
  • Видавець
  • *****
  • дописів: 3739
  • Карма: +9/-0
  • Програміст
Re: як в fsharp передати struct by reference?
« Відповідей #7 : 2018-03-28 14:53:29 »
А ящо ви таке під Mono пишите:? Хіба воно не мервто?
Ну як сказати, мені аби працювало. І працює ніби добре :)

Взагалі то мені цікавий ocaml, але f#, здається, більш розвинутий в плані батарейок.

Я вважаю, що варто дивитися у сторону Rust - по популярності він вже обігнав F# і догнав OCaml.
[Fedora Linux]

Відсутній lpi3

  • Новачок
  • *
  • дописів: 30
  • Карма: +0/-0
Re: як в fsharp передати struct by reference?
« Відповідей #8 : 2018-04-19 13:11:38 »
А ящо ви таке під Mono пишите:? Хіба воно не мервто?
Ну як сказати, мені аби працювало. І працює ніби добре :)

Взагалі то мені цікавий ocaml, але f#, здається, більш розвинутий в плані батарейок.

Я вважаю, що варто дивитися у сторону Rust - по популярності він вже обігнав F# і догнав OCaml.

Цікавить саме ml подібна мова. Раст якось не пішов у мене, не сподобався.

Відсутній Володимир Лісівка

  • Адміністратор ЩОДО
  • Видавець
  • *****
  • дописів: 3739
  • Карма: +9/-0
  • Програміст
Re: як в fsharp передати struct by reference?
« Відповідей #9 : 2018-04-20 18:39:17 »
Цікавить саме ml подібна мова. Раст якось не пішов у мене, не сподобався.

Раст дуже багато чого позичив з Хаскеля, так що там з ML більш-менш нормально. :-/

Що саме можна написати в ML мові такого, чого не може Раст?
[Fedora Linux]

Відсутній lpi3

  • Новачок
  • *
  • дописів: 30
  • Карма: +0/-0
Re: як в fsharp передати struct by reference?
« Відповідей #10 : 2018-04-23 11:46:34 »
Цікавить саме ml подібна мова. Раст якось не пішов у мене, не сподобався.

Раст дуже багато чого позичив з Хаскеля, так що там з ML більш-менш нормально. :-/

Що саме можна написати в ML мові такого, чого не може Раст?

тут
якщо коротко - type inferencе, higher-order module system, немає tail call optimization. Друге для мене не дуже важливе, до того ж воно в ocaml є, а в f# теж немає. Заради адаптації для .net його викинули, оскільки там своя система модулів. А перше і третє - це для мене основна причина чому саме ml. Отже раст для мене в прольоті :)

Наскільки я розумію, раст позиціюється як заміна с++ (принаймні мозила його розробляє саме як заміну с++ в файрфоксі). А оскільки с++ я знаю досить добре (основний інструмент для мене вже досить давно), то шукати йому заміну виглядає трохи по дитячому. Більш логічніше освоїти мову для створення великих систем, в якої достатньо батарейок (в спп з цим повний алес). Щось тіпа jvm, або .net. jvm якось мені взагалі не зайшло. Після с++ йава виглядає занадто примітивно. net і mono теж мають свої недоліки, але розвиток на місці не стоїть.

erlang дуже сподобався, але після першого більш менш великого проекту і спроби зробити щось тіпа рефакторингу динамічну типізацію вважаю суттєвим недоліком ;)

Такі справи :)

Відсутній Володимир Лісівка

  • Адміністратор ЩОДО
  • Видавець
  • *****
  • дописів: 3739
  • Карма: +9/-0
  • Програміст
Re: як в fsharp передати struct by reference?
« Відповідей #11 : 2018-04-23 14:35:25 »
тут
якщо коротко - type inferencе, higher-order module system, немає tail call optimization. Друге для мене не дуже важливе, до того ж воно в ocaml є, а в f# теж немає. Заради адаптації для .net його викинули, оскільки там своя система модулів. А перше і третє - це для мене основна причина чому саме ml. Отже раст для мене в прольоті :)

Автоматичне виведення типів присутнє в Расті, але в межах окремої функції. На межах функцій треба використовувати генерики. Це зробили щоб компілятор не тупив на великих проектах. Зараз час компіляції росте лінійно від кількості функцій, що з практичної точки зору є плюсом.

Високорівневу система типів у Раст дуже важко реалізувати (потрібно довести компілятору що у всіх можливих випадках посилання на дані у пам'яті не переживуть самі дані, що часто можна досягти тільки зробивши копію даних). Але це цікаво тим, у кого сотні типів в одній програмі. Коли типів всього пару десятків, то гратися у абстракції над типами немає сенсу.

Оптимізації хвостів немає через підтримку платформи Віндовз. :-( Програмний інтерфейс викликів функцій у Віндовз не підтримує оптимізацію хвостів. Як варіянт, можна написати стандартну функцію loop для реалізації рекурсії через цикл, але тоді функція має сигналізувати коли припиняти цикл, а це змінює її сигнатуру, що змушує розбивати функцію на дві — зовнішній інтерфейс з нормальною сигнатурою і з сигнатурою спеціально для loop. Звичайний цикл тоді простіший.

Наскільки я розумію, раст позиціюється як заміна с++ (принаймні мозила його розробляє саме як заміну с++ в файрфоксі). А оскільки с++ я знаю досить добре (основний інструмент для мене вже досить давно), то шукати йому заміну виглядає трохи по дитячому. Більш логічніше освоїти мову для створення великих систем, в якої достатньо батарейок (в спп з цим повний алес). Щось тіпа jvm, або .net. jvm якось мені взагалі не зайшло. Після с++ йава виглядає занадто примітивно. net і mono теж мають свої недоліки, але розвиток на місці не стоїть.

Я теж знаю Сі і Сі++ досить добре, і я викинув їх обох на смітник після того як вивчив Раст. Користуватися окремо Сі++ і окремо МЛ мовою я не бачу сенсу коли є Раст. По низькорівневим можливостям, Сі, Сі++, і Раст на однаковій висоті (можете подивитися мій приклад на дошці Розробка як Сі, Сі++ і Раст компілюються разом в одній програмі), по об'єктно-орієнтованим можливостям Раст близький до Сі++ (як на мене, Раст кращий), по функціональним можливостям, Раст стоїть трохи нижче за Хаскель.

До речі, десята Ява вже має міксіни. Я пробував писати код на сучасній Яві — значно простіше і компактніше ніж на старіших версіях. Якби ще всі старі ліби хтось переписав на новий лад. :-)
[Fedora Linux]

Відсутній Володимир Лісівка

  • Адміністратор ЩОДО
  • Видавець
  • *****
  • дописів: 3739
  • Карма: +9/-0
  • Програміст
Re: як в fsharp передати struct by reference?
« Відповідей #12 : 2018-04-23 14:43:29 »
Для прикладу: трансляція високорівневих типів Ocaml у Haskel: https://mail.haskell.org/pipermail/haskell/2004-August/014463.html (у Раст має бути подібно).
Монади в Раст: https://users.rust-lang.org/t/monads-and-functors-and-applicatives-explained-badly-in-rust/15187 (деяких речей все ще не вистачає).
[Fedora Linux]