C++:如何从 std::string 解析函数签名以从 DLL 调用函数?

问题描述 投票:0回答:1

我正在尝试从 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);

如何将参数转换为所需类型并为指针分配内存(如果有)?

c++ string function
1个回答
1
投票

例如,我如何从字符串中获取?

你不知道。 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()
    

© www.soinside.com 2019 - 2024. All rights reserved.