我正在尝试从 Angel 脚本中的脚本中调用 DLL 中的函数。 现在我已经写了一个库类,它有两个函数load和unload。缺少的是一个电话。 现在,为了让图片更完整,让我们展示引擎的签名->RegisterObjectMethod(“library”, “dictionary@ call(const string&in, ? &in=null, ?&in=null, ?&in=null, ?&in= null, ?&in=null, ?&in=null, ?&in=null, ?&in=null, ?&in=null, ?&in=null)const", asFUNCTION(library_call), asCALL_GENERIC); 第一个参数是DLL期望的函数签名,其余是未定义类型的参数。 这就是我使用 asIScriptGeneric 的原因!要循环参数列表并调用函数,但要正确调用它,我需要返回类型并将函数参数转换为正确的类型,以及为指针分配内存(例如,如果签名为 int*)。 最后,我想调用该函数并在键 0 下传递给 CScriptDictionary,即函数返回的内容,以及从 1 到 10 的指针变量(如果有)。
#undef GetObject//For WinAPI
asIScriptContext* ctx = asGetActiveContext();
library* lib_obj = (library*)gen->GetObject();
void* ref = gen->GetArgAddress(0);
typedef void* (*func)(...);
std::string func_name= *static_cast<string*>(ref);
//Function signature parser:
std::vector<std::string> tokens;
std::string token;
for (char c : func_name) {
if (c == ' ' || c == '(' || c == ')' || c == ',' || c == ';') {
if (!token.empty()) {
tokens.push_back(token);
token.clear();
}
}
else {
token += c;
}
}
// First array: Return type and function name
std::vector<std::string> first;
first.push_back(tokens[0]); // Return type
first.push_back(tokens[1]); // Function name
// Second array: Parameters
std::vector<std::string> last;
for (size_t i = 2; i < tokens.size(); ++i) {
if (!tokens[i].empty()) {
last.push_back(tokens[i]);
}
}
FARPROC address = GetProcAddress(lib_obj->lib, first[1].c_str());
if (address == NULL) {
const char* name = first[1].c_str();
std::string message = "Signature parse error: GetProcAddress failed for '" + std::string(name) + "'";
ctx->SetException(message.c_str());
return;
}
func function = reinterpret_cast<func>(address);
如何将参数转换为所需类型并为指针分配内存(如果有)?
例如,我如何从字符串中获取?
你不知道。 AngelScript 绑定了预定的功能,这意味着您需要在使用它之前注册
MessageBoxW
。 AngelScript 不会根据签名神奇地调用世界上的任何函数。它需要提前了解它。
r = engine->RegisterGlobalFunction("int MessageBoxW(int, wchar_t*, wchar_t*, int);", asFUNCTIONPR(MessageBoxW, (int, wchar_t*, wchar_t*), int), asCALL_CDECL);
因为
wchar_t
是它的一个特殊情况
beingused作为字符串而不是being字符串,上面的方法可能是错误的,你需要一个使用
asCString
的包装器(如果我记得的话)正确 - 抱歉,自从我测试 AngelScript 以来已经有一段时间了)或 ::std::wstring
。当然,这是假设您使用 UNICODE 构建的。这可能更接近您所需要的,但正如所说,您需要重新阅读文档并正确调整它:
#include <string>
int MyMessageBox(::std::wstring Text, ::std::wstring Caption)
{
MessageBoxW(g_hWnd, Text, Caption);
}
r = engine->RegisterGlobalFunction("int MyMessageBox(string, string, int);", asFUNCTIONPR(MyMessageBox, (wstring, wstring), int), asCALL_CDECL);
请注意,我没有包含窗口句柄。为什么?那么,为什么要将特定于操作系统的内容暴露给游戏内的脚本呢?脚本在沙箱内运行,这是有原因的。您需要缓存窗口(无论如何应该是游戏本身)并在包装器内使用它。
如果你不使用 UNICODE,当然你会使用
::std::string
和
MessageBoxA()
。至于typedef,你可以将它传递给asFUNCTIONPR()
。我建议您不要将其命名为与函数名称本身相同,可以在其前面加上
t:
tMyMessageBox()