【发布时间】:2015-10-03 10:40:57
【问题描述】:
问题
我目前正在开发一个插件库,其中应该不仅可以导入 C-Linkage 符号,还可以导入所有导入的东西。
到目前为止,它可以工作,但问题是 gcc 会调用成员函数。
如果我导出以下内容:
static member_function(Class* c)
{ c->method();}
它工作正常,我可以访问班级成员。但如果我执行以下操作:
void (Class ::*p)() = import("Class::method");
(x.*p)();
我得到了正确的指针,也能够调用函数和传递的参数,但是 this 指针指向涅槃。我认为 gcc 是从堆栈的错误位置或类似位置获取它。
它与 MSVC 配合得很好。
我正在使用 mingw-w64 5.1。
有人知道错误可能是什么吗?
简单示例:
plugin.cpp
#include <iostream>
namespace space {
class __declspec(dllexport) SomeExportThingy
{
int i = 42;
public:
virtual void __declspec(dllexport) Method(int*) const
{
using namespace std;
cout << "Calling Method" << endl;
cout << pi << endl;
cout << *pi << endl;
cout << this << endl;
cout << this->i << endl;
}
}
}
loader.cpp
namespace space {
class SomeExportThingy
{
///dummy to have some data in the address
int dummy[20];
};
int main()
{
auto h = LoadLibrary("plugin.dll");
auto p = GetProcAddress(h, "_ZNK5space16SomeExportThingy6MethodEPi");
typedef void (space::SomeExportThingy::*mptr)(int*) const;
///used because posix passed void*
auto fp = *reinterpret_cast<mptr*>(&p);
space::SomeExportThingy st;
int value = 22;
cout << "ValueLoc: " << &value << endl;
cout << "StLoc: " << &st << endl;
(st.*fp)(&value);
}
结果
现在发生的情况是,函数被调用并且指向 pi 的指针被正确传递。但是,this 指针完全搞砸了。 再次:它与 MSVC 一起工作,它正确地获取了 this 指针,但 gcc 得到了 this 错误。 我不知道为什么会发生这种情况,并且从方法中删除虚拟也不会改变这一点。 我不知道是什么原因造成的,所以也许有人知道 ABI 在这里做了什么。
这是我得到的指针:
- 0x00400000 == GetModuleHandleA(NULL)
- 0x61840000 == GetModuleHandleA("plugin.dll")
- 0x0029fcc4 == _&st
- 0x00ddcd60 == 这个
我无法找到值之间的任何关系
【问题讨论】:
-
不确定,但您是否尝试使用损坏的函数名称调用
import()? -
可能是由于名称修改...一般用途是将独立函数标记为外部,这可以防止它名称修改...使用它来检索对象然后你可以访问它的成员函数...
-
仅将函数标记为
extern不足以防止名称篡改,@basav;它必须标记为extern "C"。 -
如果您尝试将 MSVC 编译的方法导入 GCC (g++) 编译的应用程序,那么您必须通过
extern "C"接口执行此操作。名称修饰算法在不同的 C++ 编译器之间故意不同,因为生成的代码可能具有不同的(未记录且相互不兼容的)内部结构。 -
Mingw(正确大写为 MinGW)5.1 是什么意思? MinGW.org 发布的唯一 MinGW-5.1(拥有 MinGW 商标,以任何大小写形式)是一个(现在是古董)基于 GCC-3.x 的集成包。我猜你不是那个意思,在这种情况下,这不是一个 MinGW 问题;可能是
mingw-w64,这是一个不同的产品,与 MinGW.org 没有任何关联(并且在技术上侵犯了 MinGW 商标)。请澄清,和/或适当地标记。