dlsym problem. unexpected behavour.

Hi!
I'm hoping to get some help over here. Tired of searching for information, cause it doesn't help(possibly manual are with errors)

So, the problem is here(this is executable source part):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 void *handle = dlopen(execution, RTLD_LAZY);
	      if(handle)
	      {
		
		  typedef int (*hello_t)(string mode, const MonolithMode *mono, ModuleOutput *out,
					     Options *extra, const Kingmaker *king, const Ambassador* post, Tesla *data , string test);
		  hello_t hello = (hello_t) dlsym(handle, "InitiateModule");


		  if(dlerror() == NULL)
		  {
		    		  hello(commands[param].mode, mode, output, extras, url, form, tesla, "hello world");

		  status = 0;
		  }
		  else
		  {
		    cout<<"Function not found!!! ";
		    status = -1;
		    //<<dlerror();
		    cout<<"test";
		  }
		  
		  cout<<"Seems working!!";
		  dlclose(handle);
	      }
	      else
	      {
		  cout<<dlerror();
		  cout<<"Assembly error";
	      }


And ot the other side, there is a dinamycaly linkable library. Execution of library actually works, but only without attempts of using given arguments. What could be problem in?
Here is a part of a library code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
extern "C" int InitiateModule(char *mode, const MonolithMode *monomode, ModuleOutput *output, const Kingmaker *url, const Ambassador *ambassador, 
  Tesla *tesla, string a)
{
	cout<<endl<<"what a fuck?"<<endl;
	int rows = 1;
	int columns = 1;
	string *directive;
	directive = new string;
	Kingmaker *kingmaker;
	kingmaker = new Kingmaker;
//	Tesla *tesla;
//	tesla = new Tesla;
	IceGrid *languages;
	languages = new IceGrid(rows, columns);
	*directive = "SELECT count(*) FROM `el_global_languages` WHERE `active` = '1'";
	cout<<endl<<"what a fuck?"<<endl;
	cout<<endl<<"what a fuck?"<<endl;
	cout<<a<<endl;  /*HERE COMES UNEXPECTED OUTPUT(SOME KIND OF MEMORY DUMP). THE SAME THING ALWAYS HAPPENS WHEN NEW VARIABLE IS NOT GIVEN ANY VALUE*/
	tesla->Turbo(*directive, languages); /*AT THIS POINT PROGRAM CRASHES WITH SEGMENTATION FAULT*/
	cout<<endl<<"what a fuck?"<<endl;


Seems like main executable geven an empty or undefined values, or library somehow does not accept them.
Any ideas? Huge thanks for any help!
Last edited on
The parameters don't match. The first parameter is a char*, and you're passing in a string because your local prototype is wrong.

In the library that exports InitiateModule, you should also define a header file that declares a matching type like:

1
2
3
4
extern "C" {
typedef int InitiateModuleType(char *mode, const MonolithMode *monomode, ModuleOutput *output, const Kingmaker *url, const Ambassador *ambassador, 
  Tesla *tesla, string a);
}


In the application your code should use that definition. e.g.
1
2
3
4
5
6
7
if (void *handle = dlopen(execution, RTLD_LAZY))
{
    if (InitiateModuleType* func = (InitiateModuleType*)dlsym(handle, "InitiateModule"))
    {
        func( /* your args here */ );
    }
}



Also, why are you declaring a function to have C linkage, but pass in C++ types as parameters?
Well. I found only dlopen and dlsym as an ability to dinamicaly link libraries. As I found in manuals, C++ replaces the original function name, so extern "C" is required to be able to call function by name. Otherwise, it doesn't find it, because the function name is replaced after compilation and dlopen() is unable to find the function. Any other methods are available for C++?
I'm very sorry for a stupid question... but if prototype of function will be
1
2
3
4
extern "C" {
typedef int InitiateModuleType(char *mode, const MonolithMode *monomode, ModuleOutput *output, const Kingmaker *url, const Ambassador *ambassador, 
  Tesla *tesla, string a);
}


How should look function itself?
InitiateModuleType I added Type on the end to differentiate the type name from the function name.

In the end, you have to decide what language you're using, C or C++. If you're using C, you have to stick to procedures and built in types. If you're using C++, you can use C++ user defined types. You shouldn't mix the two in the way you have done. There are libraries for dealing with C++ mangled names, if you're concerned about name resolution.
Last edited on
kbw, HUGE, HUGE, HUGE thanks to you! Now it works at last.

I had 2 critical mistakes:
1) As you noticed, first argumet really was different types!
2) If you look now carefully, in main programm(that links shared library) was given 8 arguments, but librarry was set to accept 7 arguments

So as a result I got that "segmentation fault". Thanks to you once again! As only I made a header file with
1
2
3
4
extern "C" {
typedef int InitiateModuleType(char *mode, const MonolithMode *monomode, ModuleOutput *output, const Kingmaker *url, const Ambassador *ambassador, 
  Tesla *tesla, string a);
}
as you recommended, compiler immideately showed me errors because of types mismatch. It was great idea to make a header file, otherwise compliller was unable to check if types are the same or not.

PS. Could you give me some advice about how to make it all work in C++ style(not mixed as you said)? Actually dlsym is OS specified and isn't a part of ANCI C++. Where could I take a look for more information?
Last edited on
Typically with C++ you're interested in objects, not individual functions.

If you go back to interfaces and factories, you end up with some create function returning a pointer to some object. It turns out that this is the only function that needs to be exported. The actual object methods can be accessed thru the pointer.

I realise this isn't clear, so here's an example.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class IWorldController
{
public:
	static IWorldController* Create();
	static Release(IWorldController*);

	void	TakeOverWorld();
	void	MakeHappy();
	void	MakeSad();
	unsigned GetRating() const;

protected:
	~IWorldController(); // use Release()
};
extern ā€œCā€ IWorldController* Create(); // calls IWorldController::Create();
extern ā€œCā€ void Release(IWorldController*); // calls IWorldController::Release(); 


The library need only export the Create and Release functions, the app can use these to create the object then release it when you're done.

Also, check this out: http://www.cplusplus.com/forum/general/33662/#msg181279
Oh, i see... Thanks. Well, you see, this software(the one i'm working on) is CMS(for web usage) and I think it's OK to use hybrid style here. I need maximum efficiency and perfomance. Modules(shared libraries in my situation) only need to output html content. And the type is set to "int", cause the only thing is required to know, was process successfull or not. As a parameters was given C++ classes, written by my own to escape multiple constructor/destructor calls for each module, reduce multiple connections to MySQL to only one per execution. That was the aim. Possibly, it's not the best solution, but I'm quite worried about performance.
One thing more... If my software would work as a http server, I guess I'd bette use 100% C++ style. But it's running over Apache web server, and as a result process dies each time the page load is complete. So I guess there is no reason to create classes that is not quite necessary, as you know, there is always a compromise between programming style and perfomance, I preffed to use something in a middle between convinient programming and saving system resouces.
The last question... Is there any solution to catch loadable module crash and continue programm running?

I mean for example, main program called dlsym with some function called ExecuteModule(int value), and for example the module source to be as follows:
1
2
3
4
void ExecuteModule(int value)
{
      cout<<(5/value)<<endl;
}


As you can see in this module has a serious defect. If as argument is given "0", it will result in module crash(fatal error) and the program will end with something as abort(1). If that module is made by third party developer and developer didn't check if value == 0, to escape that crash, is it possible to escape main program crash? I mean catch crash from executable and for example decide continue?
Last edited on
Topic archived. No new replies allowed.