c ++使用指针调用对象方法

时间:2017-11-24 01:30:42

标签: c++ dlopen dlsym

我创建了一个共享库,在其中我定义了一个类Foo。在类Foo中,有一个名为sayHi()的函数。我的问题是,一旦我创建了一个Foo对象foo,我怎么能调用它的sayHi()。我把我的代码放在这里。

mylib.h

#ifndef FUNTEST_MYLIB_H
#define FUNTEST_MYLIB_H


class Foo {
public:
    int id = 0;
    void sayHi();
};


#endif //FUNTEST_MYLIB_H

mylib.cpp

#include <iostream>
#include "mylib.h"

using namespace std;

void Foo::sayHi()
{
    cout << "Implemented by lib" << endl;
    cout << "id is: " << id << endl;
}

Foo* create()
{
    return new Foo();
}

然后我使用以下命令编译共享库:

g++ -c -std=gnu++11 -fPIC mylib.cpp
g++ -shared -fPIC -o mylib.so mylib.o

在客户端,我写了两个文件:

mylib2.cpp

#include <iostream>
#include "mylib.h"

using namespace std;

void Foo::sayHi() {
    cout << "Implemented by caller" << endl;
    cout << "id is: " << id << endl;
}

的main.cpp

#include <iostream>
#include <dlfcn.h>
#include "mylib.h"

using namespace std;

Foo* (*create)();
void (*sayHi)();
int main() {
    void* lib = dlopen("./mylib.so", RTLD_LAZY);
    create = (Foo* (*)())dlsym(lib, "_Z6createv");
    sayHi = (void (*)())dlsym(lib, "_ZN3Foo5sayHiEv");

    Foo* foo = create();

    sayHi();
    foo->sayHi();

    foo->id = 100;
    cout << "Set id to " << foo->id << endl;

    /*
     *
     * how can I make the follow statement 'sayHi();'
     * output the following content:
     * Implemented by lib
     * id is: 100
     */
    sayHi(); // line 29, FIXME
    foo->sayHi();

    return 0;
}

使用以下命令编译客户端:

g++ -std=gnu++11 main.cpp mylib.h mylib2.cpp -ldl

最后运行客户端: ./a.out

输出是:

Implemented by lib
id is: 0
Implemented by caller
id is: 0
Set id to 100
Implemented by lib
id is: -1407102376 // FIXME
Implemented by caller
id is: 100

如何制作声明'sayHi();'在第29行输出以下内容:

Implemented by lib 
id is: 100

我知道如果我直接调用sayHi()函数,没有foo对象,输出就会出错。但我该如何解决呢?

1 个答案:

答案 0 :(得分:0)

main.cpp中sayHi全局变量的声明是错误的。您将其声明为函数指针。但是,由于它指向成员函数,因此它需要是成员函数指针。

void (Foo::*sayHi)();

然后当你调用它时,你需要一个Foo对象:

(foo->*sayHi)();

或者,如果您使用sayHi方法virtual,则根本不需要为其加载符号,因为vtable会有效地处理该符号。