views:

1187

answers:

3

I compiled the following code as a shared library using g++ -shared ...:

class Foo {
public:
  Foo() {}
  virtual ~Foo() = 0;
  virtual int Bar() = 0;
};

class TestFoo : public Foo {
public:
  int Bar() { return 0; }
};

extern "C" {
  Foo* foo;
  void init() {
    // Runtime error: undefined symbol: _ZN3FooD2Ev
    foo = new TestFoo(); // causes error
  }
  void cleanup() { delete(foo); }
  void bar() { foo->Bar(); }
}

The point is to expose the functionality of my classes (here just minimal toy classes as an example) as a simple C API with the three functions init, cleanup, and bar.

When I try to load the shared library (using dyn.load in R) I get an error:

unable to load shared library 'test.so':
test.so: undefined symbol: _ZN3FooD2Ev

So, it seems it cannot find the Foo constructor. What am I doing wrong and how can this be fixed?

UPDATE: Thanks, jbar! So it was the Foo destructor. Could I have known this from the cryptic symbol in the error message: _ZN3FooD2Ev? Does the D in FooD stand for destructor?

+3  A: 

We can't declare pure virtual destructor. Even if a virtual destructor is declared as pure, it will have to implement an empty body (at least) for the destructor.

Oh, an easy fix, thanks!
+4  A: 

UPDATE: So it was the Foo destructor. Could I have known this from the cryptic symbol in the error message: _ZN3FooD2Ev? Does the D in FooD stand for destructor?

You can use the program c++filt.

So c++filt _ZN3FooD2Ev returns "Foo::~Foo()".

Duck
+1 Thank you so much for introducing me to c++filt!
Troubadour
You're very welcome.
Duck
+1  A: 

Regardring your update, "_ZN3FooD2Ev" is "Foo::~Foo()" mangled.

Check out the "demangle" program.

Nick