我正在尝试在游戏服务器中实现一些我有PDB文件的功能。 所有修改都编码在我挂钩的DLL中。
Finish
当我尝试调用成员函数时发生了问题。我读了一些关于引用成员函数不同的东西。我在Class 1中使用的函数都有效,但是当我尝试从Class 2调用函数时,游戏服务器崩溃了。
为什么Class 1的功能有效?也许是因为Class 1有构造函数Class 2不?所有功能都是公开的。
有人可以帮助我吗? 谢谢,抱歉我的英语。
答案 0 :(得分:3)
C ++非静态成员函数不仅仅是常规函数,因为:
同样在C ++中,您不能声明“指向给定整数的任何类的任何方法返回整数的指针”。所以理论上指向一个方法的指针可能只是一个小整数,描述了你感兴趣的方法(鉴于该类是固定的并且在编译时已知)。
实际上,对于g ++(Linux 64位)中的非虚方法,似乎指向方法的指针只是指向常规函数的指针,该函数在所有其他参数之前接受额外的指针参数,遵循标准x86-64 ABI。
例如在班级
中struct Foo {
int k;
Foo(int k) : k(k) {}
int square(int x) { return k*x*x; }
int cube(int x) { return k*x*x*x; }
};
square
的代码只是:
00000000004006d0 <_ZN3Foo6squareEi>:
4006d0: 8b 07 mov (%rdi),%eax ; get this->k in eax
4006d2: 0f af c6 imul %esi,%eax ; times x
4006d5: 0f af c6 imul %esi,%eax ; times x
4006d8: c3 retq
其中%edi
是隐式this
参数,%esi
是输入x
参数,代码与声明为
int meth(Foo *this_pointer, int x);
使用g ++,方法指针最终实际上是指向函数代码的指针(在特定情况下,值为0x00000000004006d0
)。
当然请注意,这仅适用于Linux 64位上此版本的g ++。调用泛型类的泛型方法在概念上是不可能的,因为类的类型是方法签名的一部分,因此该区域中的所有内容都是依赖于实现的。
我希望其他C ++编译器也采用类似的方法(使用实际代码地址可以提高调用效率),但是您需要检查特定的编译器/环境。
作为一个简单的例子,请考虑这段代码
#include <stdio.h>
struct MyClass {
int x;
MyClass(int x) : x(x) {
}
void dump(int y) {
printf("dump() called: x = %i, y = %i\n", x, y);
}
};
MyClass class1(1111);
MyClass class2(2222);
MyClass *getClass(int x) {
if (x == 1) return &class1;
if (x == 2) return &class2;
return NULL;
}
void (MyClass::*aptr)(int) = &MyClass::dump; // NEEDED
编译为共享库:
g++ -Wall -O3 -fPIC -shared mylib.cpp -o mylib.so
并考虑此计划
#include <stdio.h>
#include <dlfcn.h>
int main(int argc, const char *argv[]) {
void *p = dlopen("./prg.so", RTLD_LAZY);
printf("p = %p\n", p);
if (p) {
void *(*geti)(int);
geti = (void *(*)(int)) dlsym(p, "_Z8getClassi");
void (*dump)(void *, int);
dump = (void (*)(void *, int)) dlsym(p, "_ZN7MyClass4dumpEi");
printf("geti = %p\n", geti);
printf("dump = %p\n", dump);
if (geti) {
for (int i=0; i<4; i++) {
void *q = geti(i);
printf("geti(%i) = %p\n", i, q);
if (q && dump) {
printf(" calling dump on the instance:\n");
dump(q, 33);
}
}
}
}
return 0;
}
通常编译为独立的可执行C程序(gcc,而不是g ++)。
程序将加载C ++库,并在两个实例上调用dump
方法,将它们声明为接受额外this
参数的普通C函数。但请注意
getClass
函数dump
根本就不存在于共享库中(参见“需要”评论)。总结一下......你真的确定要弄脏它吗?