Loading a complex class

I have a class that uses some ACE and boost libraries and c++0x features. I would love to be able to use this class in cint or pyroot. So I created a wrapper class that contains a just pointer to the fancy class. This way i can use forward declaration instead of including the fancy class’s header in this wrapper class header file, and I can get rootcint to generate the dict file. I compiled the dict file and linked the obj with the complex class’s obj w/o problem. But when i tried to load the wrapper class in cint, i got some errors complaining undefined symbols:

Here’s my linkdef.h

#ifndef LINKDEF_H
#define LINKDEF_H
#ifdef __CINT__
#pragma link C++ class WrapperClass-!;
#endif /*__CINIT__*/
#endif  /* LINKDEF_H */[/code]

[code]root [0] gDebug=7; gSystem.Load("libComplexClassWithWrapper.so")
Info in <TPluginManager::FindHandler>: did not find plugin for class TSystem and uri ....rootmap
dlopen error: /home/.../libComplexClassWithWrapper.so: undefined symbol: _ZNK5boost15program_options29value_semantic_codecvt_helperIcE5parseERNS_3anyERKSt6vectorISsSaISsEEb
Load Error: Failed to load Dynamic link library /home/.../libComplexClassWithWrapper.so
Info in <TUnixSystem::Load>: loaded library /home/.../libComplexClassWithWrapper.so status -1
(int)(-1)

Does that mean I can not use the wrapper to trick cint? I am having trouble let rootcint to parse the complex class’s header, since some ACE header are not that “standard” to cint, and boost is all about templates…

You need to find out where this “undefined symbol” belongs to, then which shared library provides this symbol and then load this shared library before you load your own wrapper (note, you might need to load several boost libraries in a specific order due to their dependencies). [code][…]$ c++filt _ZNK5boost15program_options29value_semantic_codecvt_helperIcE5parseERNS_3anyERKSt6vectorISsSaISsEEb

boost::program_options::value_semantic_codecvt_helper::parse(boost::any&, std::vector<std::basic_string<char, std::char_traits, std::allocator >, std::allocator<std::basic_string<char, std::char_traits, std::allocator > > > const&, bool) const

[…]$ grep _ZNK5boost15program_options29value_semantic_codecvt_helperIcE5parseERNS_3anyERKSt6vectorISsSaISsEEb /usr/lib/libboost*

Binary file /usr/lib/libboost_program_options.a matches
Binary file /usr/lib/libboost_program_options-mt.a matches
Binary file /usr/lib/libboost_program_options-mt.so matches
Binary file /usr/lib/libboost_program_options.so matches
Binary file /usr/lib/libboost_program_options.so.1.40.0 matches
[/code] So, you might try: root [0] gSystem.Load("/usr/lib/libboost_program_options.so"); root [1] gSystem.Load("libComplexClassWithWrapper.so");

Yes Pepe you are absolutely right, I forgot boost::program_options is not a header only lib.
Ok i will try to load all the ACE and boost and the other 3rd party libs in order. hopefully I am able to nail them all down…

hmmm unfortunately it didn’t work out. I am able to load all so files, but it seems the wrapper class was not found…?

root [0] .L /usr/local/lib/libboost_program_options.so root [1] .L /usr/local/lib/libboost_system.so root [2] .L libComplextClassWithWrapper.so root [3] WrapperClass a("Name", "Config") /usr/local/src/root-5.28/bin/root.exe: symbol lookup error: /home/.../libComplextClassWithWrapper.so: undefined symbol: _ZN14WrapperClassC1ERKSsS1_

That undefined symbol is in libComplextClassWithWrapper.so

How about: root [3] WrapperClass a;

Yeah I see what you are directing to. Actually the wrapper class doesn’t have a default ctor. it accepts 2 strings. I stripped those out to make it as simple as possible. Edited the previous post.

Also, it’s a bit confusing to me why these two boost lib need to be loaded. Since they are not in the complex class’s header or the data member. They are only used by some tmp variables in src.

When I try “c++filt ZN14WrapperClassC1ERKSsS1” I can see that this symbol cannot be demangled. Any idea why?
Maybe you could “inspect” what you get when you try: root [3] .Class WrapperClass and then maybe you could try: root [4] WrapperClass *a = new WrapperClass("Name", "Config"); Last, but not least … are you sure that your wrapper shared library contains (at least) both object files … your “WrapperClass” object file and the object file with the CINT’s dictionary for this class?

hehe yeah i changed the names. Here are the real logs:

[code]root [0] .L /usr/local/lib/libboost_program_options.so
root [1] .L /usr/local/lib/libboost_system.so
root [2] .L libCTT-feed-ose-onix.so
root [3] .Class OseFeedWrapper

class OseFeedWrapper
size=0x8 FILE:libCTT-feed-ose-onix.so LINE:-1
(tagnum=3583,voffset=-1,isabstract=0,parent=-1,gcomp=0:-1,funcs(dn21=~xcpd)=80)
List of base class--------------------------------------------------------
List of member variable---------------------------------------------------
Defined in OseFeedWrapper
libCTT-feed-ose-onix.so -1 0xffffffffffffffff oseFeedLite* pFeed
List of member function---------------------------------------------------
filename line:size busy function type and name (in OseFeedWrapper)
libCTT-feed-ose-onix.so -1:-1 0 public: void ~OseFeedWrapper(void);
libCTT-feed-ose-onix.so -1:-1 0 public: OseFeedWrapper OseFeedWrapper(const string& friendlyName,const string& config_file);
libCTT-feed-ose-onix.so -1:-1 0 public: OseFeedWrapper OseFeedWrapper(const OseFeedWrapper&);
libCTT-feed-ose-onix.so -1:-1 0 public: OseFeedWrapper& operator=(const OseFeedWrapper&);
root [4] OseFeedWrapper a(“name”, “config”)
/usr/local/src/root-5.28/bin/root.exe: symbol lookup error: /home/huishi/work/NBProjects/CTT/feed/onix/ose/CTT-feed-ose-onix/dist/Debug/GNU-Linux-x86/./libCTT-feed-ose-onix.so: undefined symbol: ZN14OseFeedWrapperC1ERKSsS1
[/code]

Ah you are right, i forgot the WrapperClass.o. Let me add it, will report back in 1 min

[...]$ c++filt _ZN14OseFeedWrapperC1ERKSsS1_ OseFeedWrapper::OseFeedWrapper(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)

Yay the wrapper class trick works. It is that I forgot to include the wrapper class obj. ~~ :smiley:

Many many thx Pepe, you are the man. Cool things to learn, root cint can load any shared lib (it uses dlopen) and c++filt is new to me.

[quote=“Pepe Le Pew”][...]$ c++filt _ZN14OseFeedWrapperC1ERKSsS1_ OseFeedWrapper::OseFeedWrapper(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) [/quote]

I’m not sure if CINT is able to create a “string &” from a “const char *”, so maybe you could try: root [3] std::string friendlyName("Name"); root [4] std::string config_file("Config"); root [5] WrapperClass a(friendlyName, config_file);

BTW. If “c++filt” is new to you, then try also: [...]$ nm -D -C /usr/lib/libboost_program_options.so [...]$ nm -C /usr/lib/libboost_program_options.a

Actually it can use const char* for string&

root [4] OseFeedWrapper("ose", "ose_prod_abn.conf") Activating log lite thread ...

[quote=“Pepe Le Pew”]I’m not sure if CINT is able to create a “string &” from a “const char *”, so maybe you could try: root [3] std::string friendlyName("Name"); root [4] std::string config_file("Config"); root [5] WrapperClass a(friendlyName, config_file); [/quote]

Nice. i only know strings before… too many things to learn yet too little time to spare.

[quote=“Pepe Le Pew”]BTW. If “c++filt” is new to you, then try also: [...]$ nm -D -C /usr/lib/libboost_program_options.so [...]$ nm -C /usr/lib/libboost_program_options.a[/quote]