c++ - 如何调用一个带有多个整数和一个整数 vector 的函数?

标签 c++ windows assembly

问题

我正在尝试为一种玩具语言编写解释器,我希望它能够调用位于 DLL 中的函数。在一些external.dll我有:

#include <cstdio>

extern "C" {

__declspec(dllexport) void print(int val) { printf("%i\n", val); }
__declspec(dllexport) int add(int a, int b) { return a + b; }

... more functions **that I don't know then names of**

}

假设我有一个 std::string func;这是 DLL 中过程的名称,可能是 "print""add" , 和一个 std::vector<int> args;其大小是目标函数的参数个数。我将如何相应地调用正确的 DLL 函数?理想情况下,我希望能够调用任何可以使用 GetProcAddress 加载的函数。 .

我的解决方法

我目前正在使用 MSVC 的内联汇编器来做我想做的事。大致是这样的:

int WorkaroundCall(const std::string& func, const std::vector<int>& args) {
    void* proc = GetProcAddress(hmod, func.c_str()); // hmod is the DLL's HMODULE
    void* spsave, * argframe;
    size_t argsize = sizeof(int) * args.size();
    const int* argdata = args.data();

    __asm {
            mov eax, esp
            sub eax, argsize
            mov argframe, eax
    }

    memcpy(argframe, argdata, argsize);

    __asm {
            mov spsave, esp
            mov esp, argframe
            xor edx, edx
            call proc
            mov esp, spsave
    }
}

但是,这显然不是一个好的解决方案,因为它使用 Assembly 并依赖于系统(有人告诉我这在 64 位上不起作用)。我怎样才能做得更好?

最佳答案

类似于:

#define EXTERNAL_API __declspec(dllimport)
typedef void (EXTERNAL_API* LPPRINTFN)( int );
typedef int (EXTERNAL_API* LPADDFN)( int, int );

// After loading the module you get the functions.
LPPRINTFN pfnPrint = (LPPRINTFN) GetProcAddress( hmod, "print" );
LPADDFN pfnAdd = (LPADDFN) GetProcAddress( hmod, "add" );

现在,由于您有这些字符串,您可能希望将它们映射到一个唯一值(假设映射是全局的):

typedef enum FuncType {
    Nothing = 0,
    PrintFunc = 1,
    AddFunc = 2
} EFuncType;

typedef map< string, EFuncType > TFuncNameMap;
TFuncNameMap funcNameMap;

if( pfnPrint != NULL ) funcNameMap["print"] = PrintFunc;
if( pfnAdd != NULL ) funcNameMap["add"] = AddFunc;

最后,调用(不包括对参数 vector 的任何边界检查):

int SlightlyBetterCall( const std::string& func, const std::vector<int>& args )
{
    TFuncNameMap::iterator iFuncId = funcNameMap.find(func);
    if( iFuncId == funcNameMap.end() )
        return -1; // return some error?

    int result = 0;

    switch( iFuncId->second ) {
        case PrintFunc:
            pfnPrint( args[0] );
            break;
        case AddFunc:
            result = pfnAdd( args[0], args[1] );
            break;
    }

    return result;
}

你真的不需要那张 map ......没有什么能阻止你去:

if( func == "print" && pfnPrint != NULL ) {
    pfnPrint( args[0] );
}
else if( func == "add" && pfnAdd != NULL ) {
    result = pfnAdd( args[0], args[1] );
}

这整件事对我来说似乎有点可疑,但我希望在任何情况下都能对您有所帮助 =)

关于c++ - 如何调用一个带有多个整数和一个整数 vector 的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12066064/

相关文章:

c++ - 最佳C++ move 构造函数实现实践

c++ - 模板变量是否可以用作模板参数(类似于类模板)?

c++ - QT - QAction::eventFilter:不明确的快捷方式重载

windows - 为什么 COM+ 忽略单元线程模型?

c++ - RDTSC 在 Ubuntu 中运行缓慢

c++ - Boost::Log 使用具有多个接收器的相同后端的安全性

C- 在 Windows 中使用 exec()

windows - IWebBrowser2对象使用IE7版本,而不是机器上安装的IE版本

linux - 比较 nasm 中的 16 位数字会产生错误的结果

c++ - 奇怪的编译代码