-1

私が持っている: car.cc

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

using namespace std;


extern "C" Car* create_object()
{
  return new Car;
}


Car::Car() {
    this->maxGear = 2;
    this->currentGear = 1;
    this->speed = 0;
}

void Car::shift(int gear) {
    if (gear < 1 || gear > maxGear) {
        return;
    }
    currentGear = gear;
}


void Car::brake() {
    speed -= (5 * this->getCurrentGear());
    std::cout<<"THE SPEED IS:" <<speed<<std::endl;
}


extern "C" void destroy_object( Car* object )
{
  delete object;
}

car.h

#ifndef VEHICLES_CAR_H
#define VEHICLES_CAR_H

// A very simple car class
class Car {
public:
    Car();
    void shift(int gear);
    void accelerate();
    void brake();

private:
    int maxGear;
    int currentGear;
    int speed;
};

#endif /* VEHICLES_CAR_H */

test.cc

#include "/home/car.h"
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>

using namespace std;

int main()
{
     /* on Linux, use "./myclass.so" */
  void* handle = dlopen("/usr/lib/libCarTest.so", RTLD_LAZY);
  int (*result)(int);
if (!handle)
{

}

/*dlsym(handle,"accelerate");
cout<<"IN HERE: "<<endl;
dlsym(handle,"brake");
dlclose(handle);*/
 Car* (*create)();
  void (*destroy)(Car*);
dlerror();
  create = (Car* (*)())dlsym(handle, "create_object");
  destroy = (void (*)(Car*))dlsym(handle, "destroy_object");

  Car* carr = (Car*)create();
  carr->brake();

  destroy( carr );
  dlclose(handle);

/*
Car carr;
carr.brake();
* compilation g++ test.cpp -o tst /path/libcar.so
*/ 
return 0;   
}

作成libMyLib.soしてインストールした後、/usr/lib 次を使用して test.cc をコンパイルしようとしましたg++ test.cc -o tst -ldl。なぜインクルードする必要があるのですか?-lMyLib?なしでコードをコンパイルする方法はありますlibMyLib.soか? 第二に、なぜ機能しdlsym(handle,"brake")ないのですか?dlsym (Car* (*).... を変更するとdlsym(handle,"brake")、何も得られません。なぜですか?

感謝

4

1 に答える 1

3

-lMyLib を含める必要があるのはなぜですか?

メソッドにリンクする必要があるためですCar::brake

第二に、なぜ dlsym(handle,"brake") が機能しないのですか?

brake記号がないからです。メソッドCar::brakeには、複雑な (実装定義の) 名前が付けられています。これは の出力で確認できますnm -D

AFAIK、あなたはそれを解決することができます

  • 仮想のすべてのメソッドを作成しCarます(それらはポインターを介して呼び出されるため、リンクは必要ありません)
  • 古いCの方法、つまり。.so からメソッドbrake()を呼び出すフリー関数をエクスポートするCar::brake
  • のすべてのパブリック メソッドを作成Car inlineし、ヘッダーで定義します。
  • 仮想テーブル アプローチをエミュレートする (C で行うように)

最後の 2 つのアプローチを組み合わせる:

class Car {
public:
  void brake() { brake_impl(this); }
private:
  void (*brake_impl)(Car*);
  void do_brake(); // this would be the actual implementation
  Car() : brake_impl([] (Car* c){ c->do_brake(); }) { ... }
};

もちろん、実装とインターフェースを分割して、それほど混乱しないようにすることもできます。

于 2011-09-05T12:17:14.113 に答える