dynload framework complete. Reloads DLL every game start, temporarily copies to prevent write protection.

This commit is contained in:
jaynus 2015-05-10 12:02:35 -07:00
parent b1d509236e
commit a21391fc7d
7 changed files with 55 additions and 15 deletions

Binary file not shown.

View File

@ -1,7 +1,7 @@
#include "script_component.hpp"
#ifdef ACE_EXTENSION_DYNLOAD
"ace_dynload" callExtension format["ace_dynload:call:%1,%1", GVAR(extensionLibrary), _this];
#ifdef DEBUG_EXTENSION_DYNLOAD
"ace_dynload" callExtension format["call:%1,%2", GVAR(extensionLibrary), _this];
#else
"ace_vd" callExtension _this;
#endif

View File

@ -1,11 +1,14 @@
#define DEBUG_MODE_FULL
#include "script_component.hpp"
// Initialize our event handlers
GVAR(ready) = false;
#ifdef ACE_EXTENSION_DYNLOAD
#ifdef DEBUG_EXTENSION_DYNLOAD
"ace_dynload" callExtension format["unload:%1", GVAR(extensionLibrary)];
"ace_dynload" callExtension format["load:%1", GVAR(extensionLibrary)];
diag_log text format["[ACE] - DEBUG - Dynamic extension loaded for Vehicle Damage"];
#endif
if(GVAR(async)) then {
@ -17,12 +20,15 @@ diag_log text format["[ACE] - Vehicle damage extension caching..."];
#ifdef ACE_VEHICLEDAMAGE_RENDER_DEBUG
"debug_render:" call FUNC(callExtension);
diag_log text format["[ACE] - DEBUG - DirectX11 Debug Rendering initialized"];
#endif
[{
private["_result"];
// Wait until the extension is ready
_result = "ready" call FUNC(callExtension);
TRACE_1("ready check", _result);
if(!isNil "_result" && {_result == "0" } ) then {
[(_this select 1)] call CBA_fnc_removePerFrameHandler;

View File

@ -14,3 +14,5 @@
#define CALL_EXT(x) "ace_vd" callExtension x
#define VECTOR_TEXT(x) ([(x)] call FUNC(_textVector))
#define RELATIVE_VECTOR_TEXT(o,x) ([(o worldToModelVisual ((x) call EFUNC(common,ASLToPosition)))] call FUNC(_textVector))
#define DEBUG_EXTENSION_DYNLOAD

View File

@ -76,7 +76,11 @@ namespace ace {
_message_id = _message_id + 1;
} else {
#ifdef _DEBUG
if (_messages.front().command != "fetch_result") {
LOG(TRACE) << "dispatch[immediate]:\t[" << name_ << "] { " << args_.get() << " }";
}
#endif
return dispatcher::call(name_, args_, result_);
}

View File

@ -58,7 +58,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) {
/*************************/
// Real functionality goes here
result = ace::dispatch::get().call(command, _args, result);
ace::dispatch::get().call(command, _args, result);
sprintf_s(output, outputSize, "%s", result.c_str());

View File

@ -4,16 +4,17 @@
#include "dispatch.hpp"
#include "arguments.hpp"
typedef void (*__stdcall RVExtension)(char *output, int outputSize, const char *function);
typedef void (__stdcall *RVExtension)(char *output, int outputSize, const char *function);
namespace ace {
class module {
public:
module() : handle(nullptr), function(nullptr), name("") {}
module(std::string name_, HANDLE handle_, RVExtension function_) : handle(nullptr), function(function_), name(name_) {}
module(const std::string & name_, HANDLE handle_, RVExtension function_, const std::string & file_) : handle(nullptr), function(function_), name(name_), temp_filename(file_) {}
std::string name;
std::string temp_filename;
HINSTANCE handle;
RVExtension function;
};
@ -41,7 +42,31 @@ namespace ace {
return true;
}
dllHandle = LoadLibrary(args_.as_string(0).c_str());
#ifdef _WINDOWS
// Make a copy of the file to temp, and load it from there, referencing the current path name
char tmpPath[MAX_PATH +1], buffer[MAX_PATH + 1];
if(!GetTempPathA(MAX_PATH, tmpPath)) {
LOG(ERROR) << "GetTempPath() failed, e=" << GetLastError();
return false;
}
if(!GetTempFileNameA(tmpPath, "ace_dynload", TRUE, buffer)) {
LOG(ERROR) << "GetTempFileName() failed, e=" << GetLastError();
return false;
}
std::string temp_filename = buffer;
if (!CopyFileA(args_.as_string(0).c_str(), temp_filename.c_str(), TRUE)) {
DeleteFile(temp_filename.c_str());
if (!CopyFileA(args_.as_string(0).c_str(), temp_filename.c_str(), TRUE)) {
LOG(ERROR) << "CopyFile() , e=" << GetLastError();
return false;
}
}
#else
std::string temp_filename = args_.as_string(0);
#endif
dllHandle = LoadLibrary(temp_filename.c_str());
if (!dllHandle) {
LOG(ERROR) << "LoadLibrary() failed, e=" << GetLastError() << " [" << args_.as_string(0) << "]";
return false;
@ -56,7 +81,7 @@ namespace ace {
LOG(INFO) << "Load completed [" << args_.as_string(0) << "]";
_modules[args_.as_string(0)] = module(args_.as_string(0), dllHandle, function);
_modules[args_.as_string(0)] = module(args_.as_string(0), dllHandle, function, temp_filename);
return false;
}
@ -79,7 +104,7 @@ namespace ace {
#endif
bool call(const arguments & args_, std::string & result) {
LOG(INFO) << "Calling [" << args_.as_string(0) << "]";
//LOG(INFO) << "Calling [" << args_.as_string(0) << "]";
if (_modules.find(args_.as_string(0)) == _modules.end()) {
return false;
@ -91,13 +116,16 @@ namespace ace {
std::string function_str;
std::vector<std::string> temp = ace::split(args_.get(), ',');
for (int x = 1; x < temp.size(); x++)
function_str = temp[1] + ":";
for (int x = 2; x < temp.size(); x++)
function_str = function_str + temp[x] + ",";
_modules[args_.as_string(0)].function((char *)result.c_str(), 4096, (const char *)function_str.c_str());
LOG(INFO) << "Called [" << args_.as_string(0) << "], result={" << result << "}";
#ifdef _DEBUG
//if (args_.as_string(0) != "fetch_result" && args_.as_string(0) != "ready") {
// LOG(INFO) << "Called [" << args_.as_string(0) << "], with {" << function_str << "} result={" << result << "}";
//}
#endif
return true;
}