source: Sophya/trunk/SophyaLib/SysTools/pdlmgr.cc@ 3842

Last change on this file since 3842 was 3605, checked in by ansari, 16 years ago

Remplacement (MacOS X) des fonctions deprecated NSxxx de chargement dynamique par dlopen()... , Reza 29/04/2009

File size: 9.8 KB
RevLine 
[1371]1//
[219]2// Gestionnaire de lien dynamique - R. Ansari 12/98
3// LAL (Orsay) / IN2P3-CNRS DAPNIA/SPP (Saclay) / CEA
[1371]4//
[1783]5#include <machdefs.h>
[219]6
[2615]7#include "sopnamsp.h"
[913]8#include "pdlmgr.h"
[219]9#include <stdio.h>
10#include <stdlib.h>
11
[2322]12#include <iostream>
[219]13
14
15// Extension de noms de fichiers Shared libs
16static const char* sofext = ".so";
17static const char* sofext_HPUX = ".sl";
[1900]18// static const char* sofext_Darwin = ".dylib"; pas necessaire - Reza 02/2002
[219]19
20// Variables et methodes static
21int PDynLinkMgr::numSO = 0;
22string* PDynLinkMgr::tmpDir = NULL;
23
[895]24/*!
25 \class SOPHYA::PDynLinkMgr
[913]26 \ingroup SysTools
[895]27 This classes handles the run-time operations related to using shared
28 libraries. The present version has been adapted for different Unix
[2598]29 flavours (Linux, HP/Compaq/Digital OSF-Tru64, SGI IRIX, IBM AIX, Sun Solaris,
30 MacOS X/Darwin). \n
[3605]31 For MacOS X/Darwin (version <= 10.3), the NSxxx API
[2598]32 <tt> (NSLinkModule , NSCreateObjectFileImageFromFile, ...) </tt>
[3605]33 is used. From MacOSX v >= 10.4, NSxxx API is deprecated.
[1275]34 The example here shows the linking of shared library named "mylib.so"
[913]35 containing a function \c double \c myfunction(double x).
36 \code
37 #include "pdlmgr.h"
38 typedef double (* AFunctionOfX) (double x);
39 {
40 // ...
41 string soname = "mylib.so";
42 string funcname = "myfunction";
43 PDynLinkMgr dyl(son);
44 AFunctionOfX f = (AFunctionOfX)dyl.GetFunction(funcname);
45 double x = 3.1425;
46 if (f != NULL)
47 cout << " X= " << x << " myfunction(x)=" << f(x) << endl;
48 // ...
49 }
50 \endcode
[895]51*/
52
[219]53/* --Methode-Static-- */
[895]54/*! Sets the path for a temporary space where shared libraries are copied.
55 The path is appended to \b LD_LIBRARY_PATH
56*/
[219]57void PDynLinkMgr::SetTmpDir(string const & path)
58{
[1275]59if ( (path.length() > 0) && (path[path.length()-1] != '/') ) GetTmpDir() = path + '/';
[219]60else GetTmpDir() = path;
[1275]61#if defined(OSF1) || defined(Linux) || defined(SunOS) || defined(IRIX64)
62 char* varenv=NULL;
63#if !defined(IRIX64)
[480]64 string cmd = "LD_LIBRARY_PATH=";
65 varenv=getenv("LD_LIBRARY_PATH");
[1275]66#else
[3226]67#ifdef SO_ARCH64
[3204]68 string cmd = "LD_LIBRARYN64_PATH=";
69 varenv=getenv("LD_LIBRARYN64_PATH");
70#else
[480]71 string cmd = "LD_LIBRARYN32_PATH=";
72 varenv=getenv("LD_LIBRARYN32_PATH");
[1275]73#endif
74#endif
[480]75
76 if (varenv == NULL) {
77 cmd += '.';
78 if (path.length() > 0) cmd += ':' + path;
79 }
80 else {
81 if (varenv[0] != '.') cmd += ".:";
82 if (path.length() > 0) cmd += path + ':';
83 cmd += varenv;
[1294]84 putenv(const_cast<char *>(cmd.c_str()));
[480]85 }
86#elif defined(AIX)
87 string cmd = "LIBPATH=";
88 char* varenv=NULL;
89 varenv=getenv("LIBPATH");
90 if (varenv == NULL) {
91 cmd += '.';
92 if (path.length() > 0) cmd += ':' + path;
93 cmd += ":/usr/lib:/lib";
94 }
95 else {
96 if (varenv[0] != '.') cmd += ".:";
97 if (path.length() > 0) cmd += path + ':';
98 cmd += varenv;
[2867]99 //AIX: l'argument de putenv n'est pas const (Reza Dec 2005)
100 //On fait un new - mais qui fait le delete ?
101 char * pevc = new char [cmd.length()+1];
102 strcpy(pevc, cmd.c_str());
103 putenv(pevc);
[480]104 }
105
106#endif
[219]107return;
108}
109
110/* --Methode-Static-- */
[895]111/*! Returns the temporary space path */
[219]112string& PDynLinkMgr::GetTmpDir()
113{
114if (tmpDir == NULL) {
115 tmpDir = new string("");
116 char* varenv;
[1277]117 if ( (varenv=getenv("TMPDIR")) != NULL ) {
118 *tmpDir = varenv;
119 if ((*tmpDir)[tmpDir->length()-1] != '/') (*tmpDir) += '/';
[219]120 }
[1277]121}
[219]122return(*tmpDir);
123}
124
125/* --Methode-Static-- */
[895]126/*! Compiles the C source file named \b fname and creates the
127 corresponding shared library linking against the standard
128 C library (-lc) and the math library (-lm).
129 Returns a pointer to the created PDynLinkMgr object (by new).
130 Returns the NULL pointer in case of errors.
131*/
[219]132PDynLinkMgr* PDynLinkMgr::BuildFromCFile(string const & fname)
133{
134size_t l = fname.length();
135if (l < 1) return(NULL);
136string fnameobj = GetTmpDir()+"tmp_pdl.o";
137
138string cmd;
139int rc;
140
[3204]141string compopt = "cc -c -o ";
142#if defined(__GNUG__)
143#ifndef SO_NOFPIC
144compopt = "cc -fPIC -c -o " ;
[1249]145#endif
[219]146#endif
[3204]147#if defined(IRIX64) && defined(SO_ARCH64)
148compopt = "cc -64 -c -o " ;
149#endif
150#if defined(AIX) && defined(SO_ARCH64)
151compopt = "cc -q64 -c -o " ;
152#endif
153
154// Compilation du fichier
155cmd = compopt + fnameobj + " " + fname;
156
[219]157rc = system(cmd.c_str());
158if (rc != 0) {
159 cerr << "PDynLinkMgr::BuildFromCFile() Error Rc(" << cmd <<")= "<< rc << endl;
160 return(NULL);
161 }
162
163char buff[32];
164numSO++;
165#ifndef HPUX
166sprintf(buff,"pdlmgr%d%s", numSO,sofext);
167#endif
168string fnameso = GetTmpDir()+buff;
169
170// Creation du shared-lib
171#if defined(OSF1)
172 cmd = "ld -shared -o " + fnameso + " -all " + fnameobj + " -none -lm -lc";
[480]173#elif defined(Linux)
[219]174 cmd = "ld -shared -o " + fnameso + " " + fnameobj + " -lm -lc";
[480]175#elif defined(SunOS)
176 cmd = "ld -G -o " + fnameso + " " + fnameobj + " -lm -lc";
177#elif defined(IRIX64)
[3226]178#ifdef SO_ARCH64
[1249]179 cmd = "ld -64 -shared -o " + fnameso + " " + fnameobj + " -lm -lc";
180#else
[480]181 cmd = "ld -shared -o " + fnameso + " " + fnameobj + " -lm -lc";
[1249]182#endif
[480]183#elif defined(AIX)
[2867]184 // cmd = "ld -G -bnogc -bexpall -bM:1L -o " + fnameso + " " + fnameobj;
[3226]185#ifdef SO_ARCH64
[3204]186 cmd = "cc -brtl -qmkshrobj -q64 -o " + fnameso + " " + fnameobj + " -lm -lc";;
187#else
[2867]188 cmd = "cc -brtl -qmkshrobj -o " + fnameso + " " + fnameobj + " -lm -lc";;
[3204]189#endif
[480]190#elif defined(HPUX)
191 cmd = "ld -b -o " + fnameso + " " + fnameobj + " -lm -lc";
[1795]192#elif defined(Darwin)
[2496]193 // cmd = "cc -bundle -flat_namespace -undefined suppress -o " + fnameso + " " + fnameobj + " -lm -lcc_dynamic -lSystem ";
194 cmd = "cc -bundle -o " + fnameso + " " + fnameobj + " -lSystem -lm";
[480]195#else
196 cmd = "ld -o " + fnameso + " " + fnameobj + " -lm -lc";
[219]197#endif
198rc = system(cmd.c_str());
199if (rc != 0) {
200 cerr << "PDynLinkMgr::BuildFromCFile() Error Rc(" << cmd <<")= "<< rc << endl;
201 return(NULL);
202 }
[296]203PDynLinkMgr* rdyn = new PDynLinkMgr(fnameso, false);
204rdyn->copy = true;
205return(rdyn);
[219]206
207}
208
209/* --Methode-- */
[895]210/*! The constructor.
211 \param soname : Name of the shared library. ".so" is appended
212 to the name if no dot "." is found in the name.
213 \param cp : if true, copies the shared library in the temporary space.
214*/
[219]215PDynLinkMgr::PDynLinkMgr(string& soname, bool cp)
216{
[2496]217dylok = false;
[219]218soName = "";
219
220if (soname.find_last_of(".") > soname.length())
221#ifdef HPUX
222 soname += sofext_HPUX;
223#else
224 soname += sofext;
225#endif
226
227string fnameso;
228if (cp) {
229 numSO++;
230 char buff[32];
231#ifndef HPUX
232 sprintf(buff,"pdlmgr%d%s", numSO,sofext);
[1795]233#elif defined(Darwin)
234 sprintf(buff,"pdlmgr%d%s", numSO,sofext_Darwin);
[219]235#else
236 sprintf(buff,"pdlmgr%d%s", numSO,sofext_HPUX);
237#endif
238 fnameso = GetTmpDir()+buff;
239 string cmd = "cp " + soname + " " + fnameso;
240 int rc = system(cmd.c_str());
241 if (rc != 0) {
242 cerr << "PDynLinkMgr::PDynLinkMgr() Error Rc(" << cmd <<")= "<< rc << endl;
243 return;
244 }
245 }
246else fnameso = soname;
247copy = cp;
248soName = fnameso;
249
[2496]250string sdylerr;
[480]251#if defined(HPUX)
252cerr << "PDynLinkMgr::PDynLinkMgr() Not yet available on HP-UX " << endl;
253return;
[3605]254#elif defined(Darwin) && ( GCC_VERSION <= 3350 )
[2496]255NSObjectFileImageReturnCode nsrc = NSCreateObjectFileImageFromFile(fnameso.c_str(), &nsobjfile);
256if (nsrc == NSObjectFileImageSuccess) {
257 nsmod = NSLinkModule(nsobjfile, fnameso.c_str(),
258 NSLINKMODULE_OPTION_BINDNOW | NSLINKMODULE_OPTION_PRIVATE |
259 NSLINKMODULE_OPTION_RETURN_ON_ERROR);
260 // The second argument of NSLinkModule is the module name
261 // We might associate later a name for the module in the PDynLinkMgr object
262 if (nsmod != NULL) dylok = true;
263 else cerr << "PDynLinkMgr::PDynLinkMgr()/ Error from NSLinkModule ... " << endl;
264}
265else {
266 cerr << "PDynLinkMgr::PDynLinkMgr()/ Error from NSCreateObjectFileImageFromFile ... " << endl;
267 if (nsrc == NSObjectFileImageFailure) cerr << " ErrCode= NSObjectFileImageFailure " << endl;
268 else if (nsrc == NSObjectFileImageInappropriateFile) cerr << " ErrCode= NSObjectFileImageInappropriateFile" << endl;
269 else if (nsrc == NSObjectFileImageArch ) cerr << " ErrCode= NSObjectFileImageArch" << endl;
270 else if (nsrc == NSObjectFileImageFormat) cerr << " ErrCode= NSObjectFileImageFormat" << endl;
271 else if (nsrc == NSObjectFileImageAccess) cerr << " ErrCode= NSObjectFileImageAccess" << endl;
[2498]272 }
[480]273#else
[2496]274dlhandle = NULL;
[219]275dlhandle = dlopen(fnameso.c_str(), RTLD_NOW);
[2496]276if (dlhandle != NULL) dylok = true;
277else {
278 sdylerr = "Loader Error (dlerror()):";
279 sdylerr += dlerror();
[2498]280 }
[2496]281#endif
282
283if (!dylok) {
[219]284 cerr << "PDynLinkMgr::PDynLinkMgr(): Error opening SO " << fnameso
285 << " (" << soname << ")" << endl;
[2496]286 if (sdylerr.length() > 0) cerr << sdylerr;
[219]287 return;
288 }
289}
290
291/* --Methode-- */
[895]292/*! Destructor. Closes the shared library. Removes the file if it had been
293 copied in the temporary space, or generated by \b BuildFromCFile */
[219]294PDynLinkMgr::~PDynLinkMgr()
295{
[480]296#if defined(HPUX)
297cerr << "PDynLinkMgr::~PDynLinkMgr() Not yet available on HP-UX " << endl;
[2496]298// return;
[3605]299#elif defined(Darwin) && ( GCC_VERSION <= 3350 )
[2496]300if (dylok) {
301 if (nsmod != NULL) NSUnLinkModule(nsmod, NSUNLINKMODULE_OPTION_NONE);
302 NSDestroyObjectFileImage(nsobjfile);
303 }
[480]304#else
[2496]305if (dylok) {
306 if (dlhandle) dlclose(dlhandle); dlhandle = NULL;
307 }
308#endif
[219]309if (copy) {
[296]310 string cmd = "rm -f " + soName;
[219]311 system(cmd.c_str());
312 }
313}
314
315/* --Methode-- */
[895]316/*! Returns a handle to the function named \b funcname.
317 Returns the NULL pointer in case of error */
[219]318DlFunction PDynLinkMgr::GetFunction(string const & funcname)
319{
320DlFunction f = NULL;
[2496]321if (!dylok) {
322 cerr << "PDynLinkMgr::GetFunction() Error:sharedobjet/dynamic library not open -> f=NULL" << endl;
323 return f;
324}
[480]325#if defined(HPUX)
326cerr << "PDynLinkMgr::GetFunction() Not yet available on HP-UX " << endl;
327return f;
[2496]328#endif
[3605]329#if defined(Darwin) && ( GCC_VERSION <= 3350 )
[1900]330string funame = "_" + funcname;
[2496]331NSSymbol nsf = NSLookupSymbolInModule(nsmod, funame.c_str());
332f = (DlFunction)NSAddressOfSymbol(nsf);
[1900]333#else
[1902]334string const & funame = funcname;
[219]335if (dlhandle != NULL)
[1900]336 f = (DlFunction)dlsym(dlhandle, funame.c_str());
[2496]337#endif
338
[480]339if (f == NULL) cerr << "PDynLinkMgr::GetFunction(): Error linking " << funcname << endl;
340return(f);
[219]341}
342
[1795]343
Note: See TracBrowser for help on using the repository browser.