OnLibraryAdded / OnLibraryRemoved
Не думал, что они реализованы так плохо.
Если w1.smx, w2.smx, w3.smx делают RegPluginLibrary("L"), то результат:
Код
// LOAD
] sm plugins load w1.smx
[w1.smx] OnLibraryAdded 'L'
] sm plugins load w2.smx
[w1.smx] OnLibraryAdded 'L'
[w2.smx] OnLibraryAdded 'L'
[w2.smx] OnLibraryAdded 'L'
] sm plugins load w3.smx
[w1.smx] OnLibraryAdded 'L'
[w2.smx] OnLibraryAdded 'L'
[w3.smx] OnLibraryAdded 'L'
[w3.smx] OnLibraryAdded 'L'
[w3.smx] OnLibraryAdded 'L'
// UNLOAD
] sm plugins unload w3.smx
[w1.smx] OnLibraryRemoved 'L' exists: 1
[w2.smx] OnLibraryRemoved 'L' exists: 1
[w3.smx] OnLibraryRemoved 'L' exists: 1
] sm plugins unload w2.smx
[w1.smx] OnLibraryRemoved 'L' exists: 1
[w2.smx] OnLibraryRemoved 'L' exists: 1
] sm plugins unload w1.smx
[w1.smx] OnLibraryRemoved 'L' exists: 0
Один плагин может зарегистрировать кучу библиотек с одинаковым именем. Если учесть, что библиотеки регистрируют и расширения, то в итоге можно легко нарваться на конфликт. Если вы делаете, например, какие-то хуки внутри OnLibraryAdded и удаляете их в OnLibraryRemoved, то т.к. SM не заботится о дубликатах, ваш хук вызовется 'x' раз подряд.
Получается, нужно делать что-то вроде такого для безопасности:
Код
int g_Library_L = 0;
static void OnLibrary(const char[] name, bool added) {
if (strcmp(name, "L") == 0) {
if (added) {
if (++g_Library_L == 1) {
// Библиотека добавлена впервые.
}
} else if (g_Library_L) {
if (--g_Library_L == 0) {
// Библиотека удалена (копий нет).
}
}
}
}
public void OnLibraryAdded(const char[] name) {
OnLibrary(name, true);
}
public void OnLibraryRemoved(const char[] name) {
OnLibrary(name, false);
}