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