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