1 /***************************************************************************
2                            cpluginmanager.cpp  -  description
3                              -------------------
4     begin                : Fri Sep 27 2002
5     copyright            : (C) 2002-2003 by Mathias Küster
6     email                : mathen@users.berlios.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #include "cpluginmanager.h"
19 
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23 
24 #include <stdio.h>
25 #ifndef WIN32
26 #include <dlfcn.h>
27 #endif
28 
29 #include "core/cdir.h"
30 #include "cconfig.h"
31 
32 /** */
CPluginManager()33 CPluginManager::CPluginManager()
34 {
35 	m_pPluginList     = new CList<CPluginObject>();
36 }
37 
38 /** */
~CPluginManager()39 CPluginManager::~CPluginManager()
40 {
41 	SetInstance(0);
42 
43 	delete m_pPluginList;
44 	m_pPluginList = 0;
45 }
46 
47 typedef ePluginStruct* (*PLUGIN_INIT_FUNC)();
48 typedef int (*PLUGIN_DEINIT_FUNC)();
49 
50 /** */
Load(CString path)51 void CPluginManager::Load( CString path )
52 {
53 	CDir dir;
54 	CList<CFileInfo> list;
55 	CFileInfo *fileinfo;
56 	PLUGIN_INIT_FUNC dclib_plugin_init;
57 	CPluginObject * Plugin;
58 
59 #ifndef WIN32
60 	void *h;
61 #else
62 	HINSTANCE h;
63 #endif
64 	// set default path
65 	if ( path.IsEmpty() )
66 		path = CConfig::Instance()->GetDCLibPluginPath();
67 
68 	/* Empty setting to disable plugin load */
69 	if ( path.IsEmpty() )
70 		return;
71 
72 	printf("Searching for plugins in '%s'\n", path.Data());
73 
74 	// set pluginpath
75 	dir.SetPath(path);
76 
77 	// get all files
78 	if ( dir.ReadEntrys( CDir::Files, &list ) )
79 	{
80 		fileinfo = 0;
81 		while( (fileinfo=list.Next(fileinfo)) != 0 )
82 		{
83 #ifdef WIN32
84 			if ( dir.Extension(fileinfo->name).ToUpper() != "DLL" )
85 #else
86 			if ( dir.Extension(fileinfo->name).ToUpper() != "SO" )
87 #endif
88 				continue;
89 
90 			printf("Found plugin: '%s'\n",fileinfo->name.Data());
91 
92 #ifdef WIN32
93 			if ( (h = LoadLibraryEx((path+DIRSEPARATOR+fileinfo->name).Data(),NULL,0)) == NULL )
94 			{
95 #else
96 			if ( (h = dlopen( (path+DIRSEPARATOR+fileinfo->name).Data(), RTLD_LAZY )) == NULL )
97 			{
98 				printf("Error dlopen %s\n",dlerror());
99 #endif
100 				continue;
101 			}
102 
103 			/* The "fix" for the warning:
104 			 *
105 			 * ISO C++ forbids casting between pointer-to-function and pointer-to-object
106 			 *
107 			 * as documented in dlopen(3) does not appear to make much
108 			 * sense and generates a:
109 			 *
110 			 * dereferencing type-punned pointer will break strict-aliasing rules
111 			 *
112 			 * warning but we already have plenty of those. Trying other things
113 			 * like reinterpret_cast is no help.
114 			 */
115 #ifdef WIN32
116 			dclib_plugin_init = (PLUGIN_INIT_FUNC) GetProcAddress(h,"dclib_plugin_init");
117 #else
118 			*(void**) (&dclib_plugin_init) = dlsym(h, "dclib_plugin_init");
119 #endif
120 
121 			if ( dclib_plugin_init == NULL )
122 			{
123 #ifndef WIN32
124 				printf("Error dlsym %s\n",dlerror());
125 				dlclose(h);
126 #else
127 				FreeLibrary(h);
128 #endif
129 			}
130 			else
131 			{
132 				Plugin = new CPluginObject();
133 				Plugin->m_sFileName = path + fileinfo->name;
134 
135 				Plugin->m_Handle = h;
136 				Plugin->m_ePluginStruct = dclib_plugin_init();
137 
138 				Plugin->m_ePluginStruct->init();
139 
140 				//ps->deinit();
141 
142 /*
143 				if ( Plugin->m_eType == eptNONE )
144 				{
145 					printf("Error init plugin\n");
146 #ifndef WIN32
147 					dlclose(h);
148 #else
149 					FreeLibrary(h);
150 #endif
151 					delete Plugin;
152 					continue;
153 				}
154 */
155 				m_pPluginList->Add(Plugin);
156 			}
157 		}
158 	}
159 }
160 
161 /** */
162 void CPluginManager::InitPlugins()
163 {
164 	CPluginObject * plugin = 0;
165 
166 	while ( (plugin = m_pPluginList->Next(plugin)) != 0 )
167 	{
168 		if ( Init(plugin) == false )
169 		{
170 			printf("Init Failed\n");
171 		}
172 	}
173 }
174 
175 /** */
176 void CPluginManager::DeInitPlugins()
177 {
178 	CPluginObject * plugin = 0;
179 
180 	while ( (plugin = m_pPluginList->Next(0)) != 0 )
181 	{
182 		plugin->m_ePluginStruct->deinit();
183 
184 #ifndef WIN32
185 		dlclose(plugin->m_Handle);
186 #else
187 		FreeLibrary(plugin->m_Handle);
188 #endif
189 		m_pPluginList->Remove(plugin);
190 		delete plugin;
191 	}
192 }
193 
194 /** */
195 bool CPluginManager::Init( CPluginObject * plugin )
196 {
197 	if ( plugin->m_ePluginStruct->m_eType != eptLIB )
198 	{
199 		printf("Plugin != LIB not for me ...\n");
200 		return false;
201 	}
202 
203 	return true;
204 }
205