110983988845cf899f103d8e188b49c11f5af30d
[scilab.git] / scilab / modules / dynamic_link / src / cpp / dynamic_link.cpp
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) INRIA/ENPC
4 * Copyright (C) DIGITEO - 2011 - Allan CORNET
5 *
6 * This file must be used under the terms of the CeCILL.
7 * This source file is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution.  The terms
9 * are also available at
10 * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
11 *
12 */
13
14 /*---------------------------------------------------------------------------*/
15
16 #include "configvariable.hxx"
17
18 extern "C"
19 {
20 #include <string.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include "dynamic_link.h"
24 #include "dynamiclibrary.h"
25 #include "men_Sutils.h"
26 #include "MALLOC.h" /* MALLOC */
27 #include "sci_warning.h"
28 #include "sciprint.h"
29 #include "stack-c.h"
30 #include "addinter.h"
31 #include "localization.h"
32 #include "Scierror.h"
33 #include "FileExist.h"
34 #include "ilib_verbose.h"
35 #ifdef _MSC_VER
36 #include "getenvc.h"
37 #include "dllinfo.h"
38
39 /* struct used by fortran (F2C) */
40 /* required to be defined in C */
41
42 typedef struct {
43     char name[nlgh+1];
44 } CINTER_struct;
45
46 __declspec (dllexport) CINTER_struct C2F(cinter);
47
48 /* struct used by fortran (F2C) */
49 /* required to be defined in C */
50 typedef struct {
51     int ibuf[lsiz];
52 } IBFU_struct;
53 __declspec (dllexport) CINTER_struct C2F(ibfu);
54
55 #endif
56 #include "getshortpathname.h"
57 #include "BOOL.h"
58 #include "charEncoding.h"
59 }
60
61 static void Underscores(BOOL _bFortran, wchar_t* _pwstEntryPointName, wchar_t* _pwstTrailingName);
62
63 typedef void (*function) (wchar_t*);
64
65
66 int scilabLink(int _iLibID, wchar_t* _pwstLibraryName, wchar_t** _pwstEntryPointName, int _iEntryPointSize, BOOL _bFortran ,int *_piErr)
67 {
68     int iLibID = -1; 
69
70     if(_iLibID == -1) 
71     {
72         iLibID = Sci_dlopen(_pwstLibraryName);
73     } 
74     else 
75     {
76         iLibID = _iLibID;
77     }
78
79     if(iLibID == -1) 
80     {
81         if( getWarningMode() ) 
82         {
83 #ifdef _MSC_VER
84             if(isDllW(_pwstLibraryName))
85             {
86 #ifdef _WIN64
87                 if(isX86DllW(_pwstLibraryName))
88                 {
89                     if(getIlibVerboseLevel() != ILIB_VERBOSE_NO_OUTPUT)
90                     {
91                         sciprint(_("%s: can not to load a x86 dll in a x64 environment.\n" ), "link");
92                     }
93                     SetLastError(ERROR_DLL_INIT_FAILED);
94                 }
95 #else
96                 if(isX64DllW(_pwstLibraryName))
97                 {
98                     if(getIlibVerboseLevel() != ILIB_VERBOSE_NO_OUTPUT)
99                     {
100                         sciprint(_("%s: can not load a x64 dll in a x86 environment.\n" ), "link");
101                     }
102                     SetLastError(ERROR_DLL_INIT_FAILED);
103                 }
104 #endif
105             }
106             else
107             {
108                 wchar_t* pwstPathSearch = searchEnvW(_pwstLibraryName, L"PATH");
109                 if(pwstPathSearch == NULL)
110                 {
111                     if(getIlibVerboseLevel() != ILIB_VERBOSE_NO_OUTPUT)
112                     {
113                         sciprint(_("%ls: The file %ls does not exist in PATH environment.\n" ), L"link", _pwstLibraryName);
114                     }
115                 }
116             }
117 #else
118             if(getIlibVerboseLevel() != ILIB_VERBOSE_NO_OUTPUT)
119             {
120                 sciprint(_("Link failed for dynamic library '%ls'.\n"), _pwstLibraryName);
121                 sciprint(_("An error occurred: %s\n"), GetLastDynLibError());
122             }
123 #endif
124         }
125         *_piErr = -1;
126         return iLibID;
127     }
128
129     if( (_iLibID == -1) && (getIlibVerboseLevel() != ILIB_VERBOSE_NO_OUTPUT)) 
130     {
131         sciprint(_("Shared archive loaded.\n"));
132         sciprint(_("Link done.\n"));
133     }
134
135     for(int i = 0 ; i < _iEntryPointSize ; i++)
136     {
137         *_piErr = Sci_dlsym(_pwstEntryPointName[i], iLibID, _bFortran);
138     }
139
140     return iLibID;
141 }
142 /*---------------------------------------------------------------------------*/
143 /**
144 * Underscores : deals with the trailing _ 
145 * in entry names 
146 */
147 static void Underscores(BOOL _bFortran, wchar_t* _pwstEntryPointName, wchar_t* _pwstTrailingName)
148 {
149 #ifdef WLU1
150     *_pwstTrailingName = L'_';
151     _pwstTrailingName++;
152 #endif
153     wcscpy(_pwstTrailingName, _pwstEntryPointName);
154 #ifdef WTU
155     if(_bFortran)
156     {
157         wcscat(_pwstTrailingName, L"_");
158     }
159 #endif
160     return;
161 }
162 /*---------------------------------------------------------------------------*/
163 int Sci_dlclose(unsigned long long _hLib)
164 {
165     return FreeDynLibrary((DynLibHandle)_hLib);
166 }
167 /*---------------------------------------------------------------------------*/
168 int Sci_dlopen(wchar_t* _pwstDynLibPath)
169 {
170     static DynLibHandle hLib = NULL;
171     int i = 0;
172
173 #ifdef _MSC_VER
174     {
175         hLib = LoadDynLibraryW(_pwstDynLibPath);
176     }
177 #else
178     {
179         char* pstDynLibPath = wide_string_to_UTF8(_pwstDynLibPath);
180         hLib = LoadDynLibrary (pstDynLibPath);
181         FREE(pstDynLibPath);
182     }
183 #endif
184
185     if(hLib == NULL)
186     {
187         return -1 ; /* the shared archive was not loaded. */
188     }
189
190     ConfigVariable::DynamicLibraryStr* pDL = ConfigVariable::getNewDynamicLibraryStr();
191     ConfigVariable::setLibraryName(pDL, _pwstDynLibPath);
192     pDL->hLib = (unsigned long long)hLib;
193
194     
195     return ConfigVariable::addDynamicLibrary(pDL);
196 }
197 /*---------------------------------------------------------------------------*/
198 int Sci_dlsym(wchar_t* _pwstEntryPointName, int _iLibID, BOOL _bFortran)
199 {
200     DynLibHandle hDynLib = NULL;
201     ConfigVariable::EntryPointStr* pEP = ConfigVariable::getNewEntryPointStr();
202     //+3 : 1 for '\0', 1 for prefix _, 1 for suffix _
203     wchar_t* pwstEntryPointName = (wchar_t*)MALLOC(sizeof(wchar_t) * (wcslen(_pwstEntryPointName) + 3));
204     memset(pwstEntryPointName, 0x00, (wcslen(_pwstEntryPointName) + 3));
205
206     Underscores(_bFortran, _pwstEntryPointName, pwstEntryPointName);
207
208     
209     if(_iLibID < 0 || ConfigVariable::isDynamicLibrary(_iLibID) == false)
210     {//no valid library at this ID
211         return -3;
212     }
213
214     /** entry was previously loaded **/
215     if(ConfigVariable::getEntryPoint(_pwstEntryPointName, _iLibID) != NULL)
216     {
217         sciprint(_("Entry name %ls.\n"), _pwstEntryPointName);
218         return -4;
219     }
220
221     pEP->iLibIndex = _iLibID;
222     hDynLib = (DynLibHandle)  ConfigVariable::getDynamicLibrary(_iLibID)->hLib;
223 #ifdef _MCS_VER
224     pEP->functionPtr = (function) GetDynLibFuncPtrW(hDynLib, pwstEntryPointName);
225 #else
226     char* pstEntryPointName = wide_string_to_UTF8(pwstEntryPointName);
227     pEP->functionPtr = (function) GetDynLibFuncPtr(hDynLib, pstEntryPointName);
228     FREE(pstEntryPointName);
229 #endif    
230     if(pEP->functionPtr == NULL)
231     {
232         if(getIlibVerboseLevel() != ILIB_VERBOSE_NO_OUTPUT)
233         {
234             sciprint(_("%ls is not an entry point.\n"), _pwstEntryPointName);
235         }
236         return -5;
237     }
238
239
240     if(0 /*debug mode*/)
241     {
242         sciprint(_("Linking %ls.\n"), _pwstEntryPointName);
243     }
244
245     ConfigVariable::setEntryPointName(pEP, _pwstEntryPointName);
246     ConfigVariable::addEntryPoint(pEP);
247     FREE(pwstEntryPointName);
248     return 0;  
249 }
250 /*---------------------------------------------------------------------------*/