Subject: Re: dlopen and C++ (NetBSD 1.4.x)
To: None <mcuddy@fensende.com>
From: Martin Husemann <martin@rumolt.teuto.de>
List: tech-toolchain
Date: 07/28/2000 22:04:10
> 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.

Ok, there are two problems in here. The attached shar builds without
a warning on 1.5C (-current) and probably 1.5_Alpha. It actually works
as expected. On 1.4.3_Alpha it results in lots of RRS text relocation warnings
and fails on i386/a.out: the symbol you look up in the shared library needs
an underscore prepended: "_base_factory". With this, it works there too.

So: check for the underscores (is there a "portable" way to do this besides
autoconf?) and ignore the RSS relocations.

If you don't link in the necessary libs, how do you supposed your module
would be loadable? One could argue that the linker should fail when creating
the .so file...


Martin

# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	Makefile
#	abc.h
#	base.cpp
#	base.h
#	main.cpp
#
echo x - Makefile
sed 's/^X//' >Makefile << 'END-of-Makefile'
Xall:	abc
X
Xclean:
X	rm -f *.so *.o abc
X
Xbase.o:
X	c++ -g3 -fPIC -DPIC -c base.cpp -o base.o
X
Xlibbase.so:	base.o
X	c++ -g3 -fPIC -DPIC --shared -Wl,-soname,libbase.so -o libbase.so base.o
X
Xmain.o:
X	c++ -g3 -fPIC -DPIC -c main.cpp -o main.o
X
Xabc:	libbase.so main.o
X	c++ -g3 -fPIC -DPIC -o abc main.o
END-of-Makefile
echo x - abc.h
sed 's/^X//' >abc.h << 'END-of-abc.h'
Xclass abc {
Xpublic:
X	virtual void func() = 0;
X};
X
END-of-abc.h
echo x - base.cpp
sed 's/^X//' >base.cpp << 'END-of-base.cpp'
X#include <iostream>
X#include "base.h"
X
Xusing namespace std;
Xvoid base::func()
X{
X	cout << "in base::func()" << endl;
X}
X
Xextern "C"
Xabc * base_factory()
X{
X	return new base;
X}
END-of-base.cpp
echo x - base.h
sed 's/^X//' >base.h << 'END-of-base.h'
X#include "abc.h"
X
Xclass base : public abc {
Xpublic:
X	virtual void func();
X};
X
Xextern "C" abc *base_factory();
END-of-base.h
echo x - main.cpp
sed 's/^X//' >main.cpp << 'END-of-main.cpp'
Xextern "C" {
X#include <dlfcn.h>
X#include <unistd.h>
X#include <string.h>
X}
X#include <iostream>
X#include "base.h"
X
Xvoid main()
X{
X	char buf[1024];
X	char *path = getcwd(buf,sizeof(buf));
X	strcat(path, "/libbase.so");
X	void *base = dlopen(path,DL_LAZY);
X
X	if (base == NULL) {
X	    cout << "can't open " << path << ": " << dlerror() << endl;
X	    exit(1);
X	}
X
X	abc *(*factoryFunc)() = (abc *(*)()) dlsym(base,"base_factory");
X
X	if (factoryFunc == NULL) {
X	    cout << "can't find factory function: " << dlerror() << endl;
X	    exit (1);
X	}
X
X	abc *obj = factoryFunc();
X
X	if (obj == NULL) {
X	    cout << "faild to make object" << endl;
X	    exit (1);
X	}
X
X	obj->func();
X	exit(0);
X}
X
END-of-main.cpp
exit