Subject: dlopen and C++ (NetBSD 1.4.x)
To: None <tech-toolchain@netbsd.org>
From: Michael Cuddy <mcuddy@fensende.com>
List: tech-toolchain
Date: 07/28/2000 01:00:07
I'm using egcs-1.1.1 with NetBSD 1.4, and I'm trying to build a shared
library which uses C++, and declares a class which implements an abstract
base class.  A 'factory method' will be used to create objects of 
various kinds dynamically.

abc.h:
    class abc {
    public:
	virtual void func() = 0;
    }

base.h:
    #include "abc.h"
    class base : public abc {
    public:
	virtual void func();
    }
    extern "C" abc *base_factory();

base.cpp:

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

    using namespace std;
    void abc::func()
    {
	cout << "in abc::func()" << endl;
    }

I compile base.cpp thusly:

    c++ -g3 -fPIC -DPIC -nostdlib -c base.cpp -o base.o

And then turn it into a shared lib:

    c++ -g3 -fPIC -DPIC -nostdlib --shared -Wl,-soname,libbase.so -o \
	libbase.so base.o /usr/lib/c++rt0.o

I then use this 'main' program:

    extern "C" {
    #include <dlfct.h>
    #include <unistd.h>
    #include <string.h>
    };

    void main()
    {
	char buf[1024];
	char *path = getcwd(buf,sizeof(buf));
	strcat(path, "/libbase.so");
	void *base = dlopen(path,DL_LAZY);

	if (base == NULL) {
	    cout << "can't open " << path << ": " << dlerror() << endl;
	    exit(1);
	}

	abc *(factoryFunc)() = (abc *(*)()) dlsym(base,"base_factory");

	if (factoryFunc == NULL) {
	    cout << "can't find factory function: " << dlerror() << endl;
	    exit (1);
	}

	abc *obj = factoryFunc();

	if (obj == NULL) {
	    cout << "faild to make object" << endl;
	    exit (1);
	}

	obj->func();
	exit(0);
    }

I compile the main program thusly:

    c++ -g3 -fPIC -DPIC -nostdlib -c main.cpp -o main.o
    c++ -g3 -fPIC -DPIC -nostdlib -o abc /usr/lib/c++rt0.o main.o

The problem is, if I run this program, I get:

/usr/libexec/ld.so: Undefined symbol "___ti3abc" in abc:/...path.../libbase.so

and the program exits (?!? I would have expected dlopen to fail and return 
NULL?!)

I've tried compiling the .so without the -nostdlib and without the manual
inclusion of /usr/lib/c++rt0.o, but I get a whole passel of 
"RRS text relocation" warnings when I try to turn the .so into a shared
library, and I still get the undefined symbol error.

Any ideas, oh great NetBSD wizards? ;-)  I'm sure it's something stupid
in the way I'm driving the linker... or is it maybe an a.out limitation?

If anyone is interested in my little test cases in a "machine readable" format,
I've put up a .tgz of it at: http://www.fensende.com/~mcuddy/abc.tgz

--
Mike Cuddy (mcuddy@FensEnde.com, MC312), Programmer, Daddy, Human.
Fen's Ende Software, Redwood City, CA, USA, Earth, Sol System, Milky Way.
I remember asking why ... Let it rain, and protect us from this Cruel Sun.

       Join CAUCE: The Coalition Against Unsolicited Commercial E-mail.
                          <http://www.cauce.org/>