Первые эксперименты с C#
Поучился обращаться к динамическим библиотекам «Мака» (dylib) из Си-шарпа. Не очень удобно, надо сказать. Вот во что превратилась моя функция macSleepAwake из сишной программы MacGreener:
using System;
using System.Runtime.InteropServices;
using MonoMac;
using MonoMac.CoreFoundation;
using MonoMac.ObjCRuntime;
namespace MacGreenerFragment
{
class SleepAwake
{
[DllImport ("IOKit", CharSet = CharSet.Ansi)]
static extern int IORegistryEntryFromPath (IntPtr masterPort, string path);
[DllImport ("IOKit")]
static extern void IOObjectRelease (int @object);
[DllImport ("IOKit")]
static extern void IORegistryEntrySetCFProperty(int entry, IntPtr propertyName, IntPtr property);
static void macSleepAwake(bool sleep)
{
var handle = Dlfcn.dlopen (Constants.CoreFoundationLibrary, 0);
IntPtr True = Dlfcn.GetIntPtr (handle, "kCFBooleanTrue");
IntPtr False = Dlfcn.GetIntPtr (handle, "kCFBooleanFalse");
int r = IORegistryEntryFromPath(IntPtr.Zero, "IOService:/IOResources/IODisplayWrangler");
if (r != 0) {
IORegistryEntrySetCFProperty(r, ((CFString)"IORequestIdle").Handle, sleep ? True : False);
IOObjectRelease(r);
}
}
}
}
На Си это 11 строк.
Тут 12.
Комментарий для Константин:
Тут 33.
В сишном варианте не посчитаны хидеры, точнее инклюды, да и подключение либы за скобками.
Сами функции примерно равны.
Если делать по-честному, то надо листинг с хидерами, загрузкой dll, поиском функций и т. п.
А так подсчёт нечестный. Тут всё подсчитано, в сишном варианте только тело функции.
Комментарий для Константин:
Подсчитаны. Иклюд там, нужный для этого участка кода, — один, я его посчитал. Давайте добавим сюда и подключение либы, это плюс одна строка (стало 12 строк). Сами функции равны, говорите? Ну да, правда сама функция в Си# на три строки длиннее.
Но кому это интересно? Я на весь код смотрю, функция без этого кода не работает, она без него бесполезна.
Я немного про другое, тут мы видим явное подключение либы — в коде, а в сишном варианте оно «за скобками».
Вместо прототипов в сишном просто инклюд, в шарповом прототипы.
В сишном подключение либы подключение конкретно либы тоже где то прописано. Не в подсчитанных строках, но есть. И это тоже руками задаётся.
В итоге в реале разброс не такой значительный.
Если бы шарповая обёртка использовалась было примерно бы как у СИ.
Комментарий для Константин:
Я понимаю о чём вы. Но в сишном варианте подключение библиотеки это +1 строка.
Посмотрите как легко подключается сишная библиотека в Гоу: https://github.com/bolknote/go-gd/blob/master/gd.go (строки с 4 по 11), потом все типы и функции из Си доступны в псевдомодуле «C» (C.gdImageCreate, например), между тем Гоу от Си отличается сильнее, чем Си# от Си.
В Си, +1 строка, только потому, что хидер уже написан.
При чём тут язык, если поддержкой Сишного легаси занимается не он. В пакет средств разработки Гоу входит импортёр для Си который понимает сишные хидеры. Т. е. это скорее отсутствие кодогенератора для Шарпа из коробки, что конечно несколько огорчает.
С другой стороны Шарп разрабатывался под виртуальную машину, так что не сильно удивительно, что подружить его с полностью unsafe Си трудно.
Комментарий для Константин:
Согласен, но вы объясняете причину, но я её и так знаю. Следствие же из неё — код на Си сильно короче, каким бы не был повод. Когда я говорю «код на Си», я имею ввиду мой код на Си, конечно же, а не совокупный код вообще.
Си-шарп мне тоже немного помогает своим модулем MonoMac, в котором, например, есть тип CFString, который не так уж и прост. CFBoolean только почему-то отсутствует, хотя в проекте на ГитХабе я его вижу, видимо, он в продуктив ещё не вышел. Без MonoMac код был бы в несколько раз больше.
Раздражает, что это «трудно» не в смысле «неподъёмная задача», а скорее «рутинная, долгая».