Есть С API либа (без классов), которая должна подключаться вообще ко всему, то есть к С# прогам, к свифтным прогамина иос, к андроидным прогам, ну и разумеется винда, линукс, мак.
Мне надо изнутри либы в кидать оповещения о происходящем в виде строк с описанием. Не просто коды ошибок. Функции сложные и длинные, иногда несколько-поточные.
Как лучше сделать?
Первое что приходит в голову коллбек — функция со строкой в аргументе. Приложение дает такую функцию и либа ее тянет.
Второе — кидать в файл, но этот кажется кривым. Не хочу через файл.
Как еще можно? Нужно кросс-платформенно и между-языково
Здравствуйте, Hоmunculus, Вы писали:
H>Первое что приходит в голову коллбек — функция со строкой в аргументе. Приложение дает такую функцию и либа ее тянет.
Это типа как в ffmpeg и куче других либ — хороший вариант.
H>Как еще можно? Нужно кросс-платформенно и между-языково
Как в Windows: код ошибки, GetLastError, описание ошибки по её коду.
Здравствуйте, Hоmunculus, Вы писали:
H>Здравствуйте, Nuzhny, Вы писали:
N>>Как в Windows: код ошибки, GetLastError, описание ошибки по её коду.
H>Ну это можно вызвать только после выполнения какой-то функции. А мне надо именно в процессе выполнения функции получать из нее логи
Здравствуйте, Hоmunculus, Вы писали:
H>Здравствуйте, kov_serg, Вы писали:
H>Ну это и есть коллбек. H>Кстати, есть пример как такое из шарпа в либу подсунуть?
Примерно так:
using System;
using System.Text;
using System.Runtime.InteropServices;
class Program {
public delegate void func_t(IntPtr ctx,[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] data,int size);
[DllImport("lib.dll",CallingConvention=CallingConvention.Cdecl)]
public static extern int func(func_t cb, IntPtr ctx);
static Program my(IntPtr ctx) { return GCHandle.FromIntPtr(ctx).Target as Program; }
static void _cb(IntPtr ctx, byte[] data, int size) { my(ctx).cb( Encoding.UTF8.GetString(data) ); }
void cb(string data) {
Console.WriteLine(data);
}
static void Main(string[] args) {
Program p = new Program();
GCHandle pctx=GCHandle.Alloc(p, GCHandleType.Normal);
int r = func(new func_t(_cb), GCHandle.ToIntPtr(pctx) );
pctx.Free();
}
}
extern"C"__declspec(dllexport) int func( void (*write)(void* ctx,char* data,int size), void* ctx) {
if (write) write(ctx,"hello",5);
return 0;
}
Здравствуйте, Hоmunculus, Вы писали:
H>Первое что приходит в голову коллбек — функция со строкой в аргументе. Приложение дает такую функцию и либа ее тянет. H>Второе — кидать в файл, но этот кажется кривым. Не хочу через файл. H>Как еще можно? Нужно кросс-платформенно и между-языково
Можно ещё прямо в сислог кидать. В том виде, как принято на платформе.
Но ИМХО, через калбек лучше всего. Оставляет приложению возможность решать, что делать с этими логами.
Здравствуйте, Hоmunculus, Вы писали:
H>Первое что приходит в голову коллбек — функция со строкой в аргументе. Приложение дает такую функцию и либа ее тянет.
Ну вот. Какие аргументы против коллбека вообще могут быть?
Если приложение ничего не хочет знать про логи, просто не дает коллбек, и либа соответственно их никуда не пишет.
Здравствуйте, graniar, Вы писали:
G>Ну вот. Какие аргументы против коллбека вообще могут быть?
Да никаких. Вот и спросил — может человечество изобрело что-то новенькое, стильное, модное, молодежное, а я не в курсе.
Но у коллбека есть один минус — переводы. Тогда или либо должна знать локаль и содержать в себе все переводы лога, или приложение как-то должно уметь переводить на нужный язык то что либа нагенерит
Здравствуйте, Hоmunculus, Вы писали:
G>>Ну вот. Какие аргументы против коллбека вообще могут быть?
H>Да никаких. Вот и спросил — может человечество изобрело что-то новенькое, стильное, модное, молодежное, а я не в курсе. H>Но у коллбека есть один минус — переводы. Тогда или либо должна знать локаль и содержать в себе все переводы лога, или приложение как-то должно уметь переводить на нужный язык то что либа нагенерит
Это не является минусом колбека, а минусом конкретной реализации, которая кидается текстом.
Можно в колбэк передавать код сообщения и аргументы, а поиск локализованного текста и подстановку аргументов делает приложение. Или даже можно кидать текст сообщения на английском, только не форматировать его внутри функции. В этом случае приложение ищет локализованное сообщение по оригинальному (обычно английскому) тексту, а потом подставляет аргументы. Примерно как кутишный tr работает.
T>Тут главное сделать удобные врапперы над всем этим, дабы каждый вызов функции не превращался в писанину на несколько строк
Если c# может jit-тить callback-и то остальным нужен указатель на контеркст. Или придётся велосипедить переходники на другой стороне.
Удобство можно добиться обычным врапером. И будет вообще не видно что под капотом. Короче компромис есть всегда. И конкретная реализация зависит от требований к задаче.
Но вызов с void fn(void* ctx,const char* data,int size); и меет более общий характер нежели void fn(const char* cstr_utf8); хотя одно всегда можно привести к другому, но это требует дополнительных усилий
по описанию/документированию происходящего и дополнительным накладным расходам для всех сторон.