Добавлен , опубликован
Раздел:
Основы
С выходом двух материалов составленых IceFog'ом (xgm.guru/p/wc3/jass-api (Работа с нативными функциями) и xgm.guru/p/wc3/fast-jass#h1.0.1 (Ускоренная виртуальная машина)) про создание своих нативок в War 3(1.26a). Добавляю свой код для создания нативок на языке C++.
JassApi.h
typedef int LongBool;
typedef LongBool (__stdcall *pRegisterJassNative) (char *Name, char *Signature, void *Address);
<DLL_NAME>.cpp
#include "JassApi.h"

#include <windows.h>
#include <stdio.h>

pRegisterJassNative RegisterJassNative = NULL;
int __stdcall test()
{
	return 3;
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{	
	if (ul_reason_for_call != DLL_PROCESS_ATTACH) return TRUE;
	DisableThreadLibraryCalls(hModule);

	HMODULE hjApi = GetModuleHandle(L"JassApi.dll");
	if(!hjApi) throw("Could not locate JassApi");

	RegisterJassNative = (pRegisterJassNative)GetProcAddress(hjApi, "RegisterJassNative");
	if(!RegisterJassNative) throw("Could not find RegisterJassNative");

	RegisterJassNative("test", "()I",(void *)test);

	return TRUE;
}
Чтобы создать dll которая будет подгружаться в Warcraft'е, нужно отключить поддержку Clr-среды в свойствах проекта.
Собираем dll. Закидываем её в папку с игрой. Переименовываем её с расширением ".mix". Закидываем в папку с игрой Jass.dll и RedirectCalls.dll из указанных статей выше. RedirectCalls.dll переименовываем в RedirectCalls.mix.
Чтобы вызвать нативку в игре пишем:
native test nothing returns integer
Новые нативки работают и в AI скриптах и в ".j" файле.
Для теста создадим два файла common.ai и human.ai в mpq архиве карты и поместим их по пути "Scripts\".
common.ai - предназначен для общих функций для скриптов human.ai, elf.ai, orc.ai, undead.ai. А эти подскрипты предназначены для AI этих рас.
Код файла common.ai:
native test nothing returns integer
Код файла human.ai:
function main takes nothing returns nothing
    call DisplayTextToPlayer( GetLocalPlayer(), 0.0, 0.0, "hello!123" )
    if test() == 3 then
    call DisplayTextToPlayer( GetLocalPlayer(), 0.0, 0.0, "34444444444444" )
    endif
endfunction
Чтобы подгрузить эти скрипты в карте воспользуемся следующим кодом в файле "war3map.j":
call MeleeStartingAI()
Добавим этот код в мейн функцию в файле "war3map.j".
Добавим через ГУИ пару игроков чтобы проверить скрипт. Выберем расу у компьютера "human".
И при за грузке карты мы должны увидеть следующие два сообщения:
"hello!123"
"34444444444444"
Тест закончен.
Карту и dll закидывать не буду. Учимся всё делать сами.
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
0
9
10 месяцев назад
0
IceFog, всё равно будет работать. Я проверял.
0
9
10 месяцев назад
0
Да ты прав GetJassNative, используют соглашение cdecl. Но RegisterJassNative я использую c stdcall.
// Natives variable
HRACE (__cdecl *_ConvertRace) (Integer i);
bool fRegistrNatives()
{
	*((int*)&_ConvertRace) = (int)GetJassNative("ConvertRace");
}

HRACE ConvertRace(Integer i)
{
	return _ConvertRace(i);
}
Могу опубликовать все нативные функции на с++.
0
20
10 месяцев назад
Отредактирован Unryze
0
Да ты прав GetJassNative, используют соглашение cdecl. Но RegisterJassNative я использую c stdcall.
Ну, и толку от этого почти никакого. stdcall используется для импортируемых/экспортируемых функций, как на том же примере Storm.dll, а сама игра использует cdecl/thiscall/fastcall, говоря короче, твой выбор != то как должно быть или же правильно. Вызовы stdcall можно вызывать и через __cdecl, только это чревато прикольными такими утечками хипа, а порой даже и стека, так что ну такое себе.
Загруженные файлы
0
14
10 месяцев назад
0
Использование неправильной конвенции вызова приведет к повреждению памяти стэка.
Хранящиеся в нём локальные переменные и адреса возврата могут быть перезаписаны случайными значениями, что приведет к непредсказуемым последствиям.
Хотя, стоит отметить, что виртуальная машина JASS'а (по крайней мере на 1.26а версии) способна правильно вызывать нативки использующие как cdecl так и stdcall, что используется мемхаком.
Но, если такую неправильную нативку вызовет кто другой, то весьма вероятны баги и краши.
0
20
10 месяцев назад
0
Использование неправильной конвенции вызова приведет к повреждению памяти стэка.
Хранящиеся в нём локальные переменные и адреса возврата могут быть перезаписаны случайными значениями, что приведет к непредсказуемым последствиям.
Хотя, стоит отметить, что виртуальная машина JASS'а (по крайней мере на 1.26а версии) способна правильно вызывать нативки использующие как cdecl так и stdcall, что используется мемхаком.
Но, если такую неправильную нативку вызовет кто другой, то весьма вероятны баги и краши.
JassVM пушит на стэк через alloca и вызывает через cdecl, не знаю откуда ты взял stdcall там. Но опять же, не суть. А Мемхак использует std_call для вызова Storm функций, но опять же, эти нюансы на деле важны лишь паре землекопов, ибо большинство эти нюансы не знает и даже не пытается в них лезть (и слава богу).
0
9
10 месяцев назад
0
Unryze, а если я память не освобожу в функции, то это будет утечка при __cdecl, когда я выйду из варкрафта?
1
20
10 месяцев назад
1
Unryze, а если я память не освобожу в функции, то это будет утечка при __cdecl, когда я выйду из варкрафта?
Утечка памяти высвобождается при уничтожении процесса, ибо вся занятая ею память освобождается системой. (По крайней мере так утверждает Microsoft), ибо как ни как эти утечки stack/heap - часть программы, а у неё выделена память от 0x0 до 2GB (при патчере 4GB) памяти. Я не особо практиковал утечки памяти, потому не могу прямо утверждать, что всё так просто или нет, но думаю Microsoft как-то да и контролируют приложения. :D
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.