У меня не было проблем с поставляемой версией MinGW, которая поставляется с CodeBlocks 12.11. Но теперь я попытался скомпилировать SyncSys. Компиляция enet не была проблемой, но компиляция самого SyncSys с помощью gcc / MinGW приводит к ошибкам, что я не могу использовать функцию _InterlockedOr8, потому что она не объявлена. Исследования приводят к тому, что _InterlockedOr8 определен в intrin.h. intrin.h не включен, и я искал эквивалент для него в MinGW / gcc: x86intrin.h. Но это все еще не работает. InterlockedOr8 будет «реальной» функцией для вызова, но это не может быть найдено компилятором, хотя включены winbase.h и windows.h.
Исследуя эту проблему там, где очень мало хитов, я не мог учиться. Как я могу это исправить?
_InterlockedOr8 — это встроенная функция компилятора, уникальная для компилятора Microsoft. Это означает, что компилятор автоматически внедряет реализацию в код, а не связывается с библиотекой. <intr.h>
файл заголовка, распространяемый вместе с Visual Studio, отдельно от Windows SDK
Если вы не можете переключиться на Visual Studio (скачать бесплатно, кстати), тогда вы можете определить свою собственную заменяющую версию этой функции:
void InterlockedOr8(char* dst, char src)
{
__asm
{
mov eax, dst ; EAX = dst
mov cl, src ; ECX = src
lock or [eax], cl ; *dst = src | *dst; // this is the actual interlocked-or op
}
}
Обратите внимание, что эта функция отличается от _InterlockedOr8 тем, что она не возвращает исходное значение * dst. Реализация становится более сложной, если вам нужно возвращаемое значение. Я быстро взглянул на источник SyncSys. Два места, которые нуждаются в этой функции, не нуждаются в возвращаемом значении. Поэтому все, что вам нужно сделать, — это преобразовать приведенный выше код в стиль gcc встроенной сборки.
Обновить
Вот версия, которая правильно возвращает исходное значение в адресе назначения перед операцией ИЛИ. Вероятно, он мог бы использовать небольшую проверку кода …
char MyInterlockedOr8(char* dst, char src)
{
char result = 0;
const size_t ptr_size = sizeof(dst);
_asm
{
mov esi, dst ; esi = dst
mov cl, src ; cl = src // keep "src" cached in a register
mov al, [esi] ; al = *dst
start:
mov bl, cl ; bl = src
or bl, al ; bl = src | *dst
lock cmpxchg [esi], bl; // if (*dst == eax) { *dst=bl ;} else {al = *dst};
jne start
mov result, al ; result = al
}
return result;
}
Других решений пока нет …