Кроссплатформенный интерфейс для либы
От: Hexxx  
Дата: 25.03.13 19:47
Оценка:
Есть сишная либа, которую мы писали для ring-3 и есть уже некоторый объем ring-3 кода, который юзает эту либу. Сейчас понадобилось использовать либу в ring-0, в драйвере. И принято решение делать код "кроссплатформенным". С самим кодом, в общем сложностей никаких, компиляберность под wdk достигли быстро. Но уперлись в интерфейс. Часть функции в интерфейсе либы юзает wchar_t * (строки путей к файлам), для ring-3 это вполне приемлемо. А вот для ring-0 конечно же удобнее было бы использовать UNICODE_STRING.
И вот тут начинается конфликт между ring-0 и ring-3 пользователями либы. Нужно делать интерфейс, так чтобы он был удобен для всех. А варианты, которые я вижу:
1) заставить ring-3 пользователей страдать: использовать везде UNICODE_STRING
2) заставить страдать ring-0 пользователей: оставить в интерфейсе wchar_t * и заставить их формировать терминированную нулем строку из UNICODE_STRING. Т.е. перевыделять буфер строки UNICODE_STRING.Buffer, копировать оригинальный буфер + L'\0'. А потом очищать выделенную память.
3) как компромисс, сделать два аргумента: первый — строка, второй — размер буфера строки. DoSomething(wchar_t * str, int str size); Сформировать такие два аргумента из UNICODE_STRING.Buffer + UNICODE_STRING.Length легко. А вот для ring-3 аргумент размера буфера строки все равно обуза.
4) делать два разных интерфейса. Для ring-3 набор функций, например, DoSomething(wchar_t *); а для ring-0 — DoSomethingNative(UNICODE_STRING *); Но это тоже не нравится из-за дублирования.

Как вообще кроссплатфоменный принято в таких случаях оформлять?

p.s. Самое интересное, что в ring-0 в итоге строка из либы попадет в NtCreateFile(), т.е. если оставить wchar_t * в интерфейсе, то в ring-0 получается нелепая конверсия: UNICODE_STRING -> wchar_t * -> UNICODE_STRING
Re: Кроссплатформенный интерфейс для либы
От: LaptevVV Россия  
Дата: 25.03.13 19:53
Оценка:
Здравствуйте, Hexxx, Вы писали:

H>Есть сишная либа, которую мы писали для ring-3 и есть уже некоторый объем ring-3 кода, который юзает эту либу. Сейчас понадобилось использовать либу в ring-0, в драйвере. И принято решение делать код "кроссплатформенным". С самим кодом, в общем сложностей никаких, компиляберность под wdk достигли быстро. Но уперлись в интерфейс. Часть функции в интерфейсе либы юзает wchar_t * (строки путей к файлам), для ring-3 это вполне приемлемо. А вот для ring-0 конечно же удобнее было бы использовать UNICODE_STRING.

H>И вот тут начинается конфликт между ring-0 и ring-3 пользователями либы. Нужно делать интерфейс, так чтобы он был удобен для всех. А варианты, которые я вижу:
H>1) заставить ring-3 пользователей страдать: использовать везде UNICODE_STRING
H>2) заставить страдать ring-0 пользователей: оставить в интерфейсе wchar_t * и заставить их формировать терминированную нулем строку из UNICODE_STRING. Т.е. перевыделять буфер строки UNICODE_STRING.Buffer, копировать оригинальный буфер + L'\0'. А потом очищать выделенную память.
H>3) как компромисс, сделать два аргумента: первый — строка, второй — размер буфера строки. DoSomething(wchar_t * str, int str size); Сформировать такие два аргумента из UNICODE_STRING.Buffer + UNICODE_STRING.Length легко. А вот для ring-3 аргумент размера буфера строки все равно обуза.
H>4) делать два разных интерфейса. Для ring-3 набор функций, например, DoSomething(wchar_t *); а для ring-0 — DoSomethingNative(UNICODE_STRING *); Но это тоже не нравится из-за дублирования.

H>Как вообще кроссплатфоменный принято в таких случаях оформлять?

1. Сделать просто две разные функции
2. Сделать две разные библиотеки.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re: Кроссплатформенный интерфейс для либы
От: Кодт Россия  
Дата: 25.03.13 21:13
Оценка:
Здравствуйте, Hexxx, Вы писали:

<>

В порядке безумства: взять С++ и написать обобщённый код на шаблонах, а наружу сделать extern "C" публичных функций.
А уж сделать две версии библиотеки, одна из которых инстанцирована для 0 кольца, а вторая для 3; или же одну библиотеку, где будут обе версии вместе сосуществовать — это дело вкуса и особенностей организации вашей системы сборки.

В принципе, можно поизгаляться и сделать "шаблоны для бедных".
#ifdef USING_WCHAR_T
  #define STRING_TYPE                wchar_t* /* как передавать */
  #define STRING_CONST(name, value)  wchar_t* name = value; /* как определять константы */
  #define STRING_TAKE(name)          name /* как передавать константы */
  /* и т.д., что там ещё может понадобиться */
#else
  #define STRING_TYPE                UNICODE_STRING*
  #define STRING_CONST(name, value)  UNICODE_STRING name = { wcslen(value), wcslen(value), value };
  #define STRING_TAKE(name)          &name
#endif


STRING_TYPE foo(STRING_TYPE arg)
{
  STRING_CONST(bar, L"barbarbar")
  return rand() ? arg : STRING_TAKE(bar);
}

(Знаю, что код адский, и не рекомендую делать именно ТАК — просто как демонстрация подхода).
Перекуём баги на фичи!
Re: Кроссплатформенный интерфейс для либы
От: artem.komisarenko Украина  
Дата: 25.03.13 21:37
Оценка:
Здравствуйте, Hexxx, Вы писали:


// Черновой набросок

void DoSomethingInternal(PWSTR string, USHORT size);

#ifdef ...
inline void DoSomething(UNICODE_STRING const * string)
{
  DoSomethingInternal(string->Buffer, string->Length);
}
#else
inline void DoSomething(PWSTR string)
{
  DoSomethingInternal(string, wcslen(string));
}
#endif


Что-то типа такого?
Re: Кроссплатформенный интерфейс для либы
От: uzhas Ниоткуда  
Дата: 26.03.13 07:33
Оценка:
Здравствуйте, Hexxx, Вы писали:

H>если оставить wchar_t * в интерфейсе, то в ring-0 получается нелепая конверсия: UNICODE_STRING -> wchar_t * -> UNICODE_STRING


в чем сложность провести такую конвертацию?
судя по http://msdn.microsoft.com/ru-RU/library/windows/desktop/aa380518(v=vs.85).aspx там все просто, строки не надо перевыделять или копировать, если они только как Input parameters
если output, то придется копировать из UNICODE_STRING в std::wstring
если конвертация легкая, то я бы заточил интерфейс на wchar_t*, в кишках где надо "конвертировал" бы в UNICODE_STRING
Re[2]: Кроссплатформенный интерфейс для либы
От: Кодт Россия  
Дата: 26.03.13 07:45
Оценка:
Здравствуйте, uzhas, Вы писали:

U>если output, то придется копировать из UNICODE_STRING в std::wstring


Библиотека сишная, а даже если и на плюсах писать, то всё равно, в нулевом кольце доступны ли сишный и плюсовой рантаймы? Придётся развлекаться с самодельными аллокаторами.
Перекуём баги на фичи!
Re[3]: Кроссплатформенный интерфейс для либы
От: uzhas Ниоткуда  
Дата: 26.03.13 09:07
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Библиотека сишная, а даже если и на плюсах писать, то всё равно, в нулевом кольце доступны ли сишный и плюсовой рантаймы? Придётся развлекаться с самодельными аллокаторами.

либо передавать (wchar_t* buffer, bufferSize)
Re[3]: Кроссплатформенный интерфейс для либы
От: saf_e  
Дата: 26.03.13 10:44
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, uzhas, Вы писали:


U>>если output, то придется копировать из UNICODE_STRING в std::wstring


К>Библиотека сишная, а даже если и на плюсах писать, то всё равно, в нулевом кольце доступны ли сишный и плюсовой рантаймы? Придётся развлекаться с самодельными аллокаторами.


С-шный доступен, не полный, но многое есть.

В качестве input параметров делать const wchar_t * и не парится, они легко врапятся.

Остальное должно б/м совпадать, раз интерфейс уже С-шный. Надо только будет определиться если понадобится передавать память ring-0 to ring-3.
Re: Кроссплатформенный интерфейс для либы
От: Alexander G Украина  
Дата: 26.03.13 11:14
Оценка: :)
Здравствуйте, Hexxx, Вы писали:

H>3) как компромисс, сделать два аргумента: первый — строка, второй — размер буфера строки. DoSomething(wchar_t * str, int str size); Сформировать такие два аргумента из UNICODE_STRING.Buffer + UNICODE_STRING.Length легко. А вот для ring-3 аргумент размера буфера строки все равно обуза.


Это, плюс договориться, что размер равный -1 будет означать, что он не задан, и либа должна будет найти его сама через wcslen.
Русский военный корабль идёт ко дну!
Re[2]: Кроссплатформенный интерфейс для либы
От: Hexxx  
Дата: 26.03.13 13:00
Оценка:
Здравствуйте, uzhas, Вы писали:
U>если конвертация легкая, то я бы заточил интерфейс на wchar_t*, в кишках где надо "конвертировал" бы в UNICODE_STRING
всего лишь надо перевыделить буфер ради завершающего нуля, а потом освободить.
Re[3]: Кроссплатформенный интерфейс для либы
От: saf_e  
Дата: 26.03.13 13:06
Оценка:
Здравствуйте, Hexxx, Вы писали:

H>Здравствуйте, uzhas, Вы писали:

U>>если конвертация легкая, то я бы заточил интерфейс на wchar_t*, в кишках где надо "конвертировал" бы в UNICODE_STRING
H>всего лишь надо перевыделить буфер ради завершающего нуля, а потом освободить.

LPCWSTR lpName=L"...";
UNICODE_STRING ustr;
RtlInitUnicodeString(&ustr, lpName);

На сколько я помню перевыделения памяти не происходит, строка просто врапится.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.