modules using java in nwni mode fixed.
[scilab.git] / scilab / modules / ast / src / cpp / types / function.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2008-2008 - DIGITEO - Antoine ELIAS
4  *  Copyright (C) 2010-2010 - DIGITEO - Bruno JOFRET
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 #include <algorithm>
18 #include <sstream>
19 #include <vector>
20 #include "function.hxx"
21 #include "double.hxx"
22 #include "gatewaystruct.hxx"
23 #include "configvariable.hxx"
24 #include "scilabWrite.hxx"
25
26 extern "C"
27 {
28 #include "core_math.h"
29 #include "charEncoding.h"
30 #include "Scierror.h"
31 #include "sciprint.h"
32 #include "localization.h"
33 #include "sci_path.h"
34 #include "sci_malloc.h"
35 #include "os_string.h"
36 #include "lasterror.h"
37 #include "dynamic_module.h"
38 #include "functions_manager.h"
39 }
40
41 // dummy function definition for non nwni compatible modules
42 static void dummy()
43 {
44     char* fname = wide_string_to_UTF8(ConfigVariable::getWhere().back().m_name.c_str());
45     Scierror(999, _("Scilab '%s' function disabled in -nogui or -nwni mode.\n"), fname);
46     FREE(fname);
47 }
48 static types::Function::ReturnValue sci_dummy_in_NWNI(types::typed_list &/*in*/, int /*_iRetCount*/, types::typed_list &/*out*/)
49 {
50     dummy();
51     return types::Function::Error;
52 }
53 static types::Function::ReturnValue sci_dummy_in_NWNI_OPT(types::typed_list &/*in*/, types::optional_list &/*opt*/, int /*_iRetCount*/, types::typed_list &/*out*/)
54 {
55     dummy();
56     return types::Function::Error;
57 }
58 static int sci_dummy_in_NWNI_OLDC(char * /*fname*/, void* /*pvApiCtx*/)
59 {
60     dummy();
61     return 1;
62 }
63 static int sci_dummy_in_NWNI_MEX(int /*nlhs*/, int** /*plhs*/, int /*nrhs*/, int** /*prhs*/)
64 {
65     dummy();
66     return 1;
67 }
68 static int sci_dummy_in_NWNI_C(scilabEnv /*env*/, int /*nin*/, scilabVar* /*in*/, int /*nopt*/, scilabOpt /*opt*/, int /*nout*/, scilabVar* /*out*/)
69 {
70     dummy();
71     return 1;
72 }
73
74 // Function Class definition
75 namespace types
76 {
77 Function* Function::createFunction(const std::wstring& _wstName, GW_FUNC _pFunc, const std::wstring& _wstModule)
78 {
79     return new Function(_wstName, _pFunc, NULL, _wstModule);
80 }
81
82 Function* Function::createFunction(const std::wstring& _wstName, GW_FUNC_OPT _pFunc, const std::wstring& _wstModule)
83 {
84     return new OptFunction(_wstName, _pFunc, NULL, _wstModule);
85 }
86
87 Function* Function::createFunction(const std::wstring& _wstName, OLDGW_FUNC _pFunc, const std::wstring& _wstModule)
88 {
89     return new WrapFunction(_wstName, _pFunc, NULL, _wstModule);
90 }
91
92 Function* Function::createFunction(const std::wstring& _wstName, MEXGW_FUNC _pFunc, const std::wstring& _wstModule)
93 {
94     return new WrapMexFunction(_wstName, _pFunc, NULL, _wstModule);
95 }
96
97 Function* Function::createFunction(const std::wstring& _wstName, GW_FUNC _pFunc, LOAD_DEPS _pLoadDeps, const std::wstring& _wstModule)
98 {
99     return new Function(_wstName, _pFunc, _pLoadDeps, _wstModule);
100 }
101
102 Function* Function::createFunction(const std::wstring& _wstName, GW_FUNC_OPT _pFunc, LOAD_DEPS _pLoadDeps, const std::wstring& _wstModule)
103 {
104     return new OptFunction(_wstName, _pFunc, _pLoadDeps, _wstModule);
105 }
106
107 Function* Function::createFunction(const std::wstring& _wstName, OLDGW_FUNC _pFunc, LOAD_DEPS _pLoadDeps, const std::wstring& _wstModule)
108 {
109     return new WrapFunction(_wstName, _pFunc, _pLoadDeps, _wstModule);
110 }
111
112 Function* Function::createFunction(const std::wstring& _wstName, MEXGW_FUNC _pFunc, LOAD_DEPS _pLoadDeps, const std::wstring& _wstModule)
113 {
114     return new WrapMexFunction(_wstName, _pFunc, _pLoadDeps, _wstModule);
115 }
116
117 Function* Function::createFunction(const std::wstring& _wstName, const std::wstring& _wstEntryPointName, const std::wstring& _wstLibName, FunctionType _iType, LOAD_DEPS _pLoadDeps, const std::wstring& _wstModule, bool _bCloseLibAfterCall)
118 {
119     if (isNonNwniModule(_wstModule.data()))
120     {
121         switch (_iType)
122         {
123             case FunctionType::EntryPointOldC:
124                 return new WrapFunction(_wstName, &sci_dummy_in_NWNI_OLDC, NULL, _wstModule);
125             case FunctionType::EntryPointCPP:
126                 return new Function(_wstName, &sci_dummy_in_NWNI, NULL, _wstModule);
127             case FunctionType::EntryPointMex:
128                 return new WrapMexFunction(_wstName, &sci_dummy_in_NWNI_MEX, NULL, _wstModule);
129             case FunctionType::EntryPointCPPOpt:
130                 return new OptFunction(_wstName, &sci_dummy_in_NWNI_OPT, NULL, _wstModule);
131             case FunctionType::EntryPointC:
132                 return new WrapCFunction(_wstName, &sci_dummy_in_NWNI_C, NULL, _wstModule);
133         }
134     }
135     else
136     {
137         return new DynamicFunction(_wstName, _wstEntryPointName, _wstLibName, _iType, _pLoadDeps, _wstModule, _bCloseLibAfterCall);
138     }
139     
140     // must never append
141     return NULL;
142 }
143
144 Function* Function::createFunction(const std::wstring& _wstName, const std::wstring& _wstEntryPointName, const std::wstring& _wstLibName, FunctionType _iType, const std::wstring& _wstLoadDepsName, const std::wstring& _wstModule, bool _bCloseLibAfterCall)
145 {
146     if (isNonNwniModule(_wstModule.data()))
147     {
148         switch (_iType)
149         {
150             case FunctionType::EntryPointOldC:
151                 return new WrapFunction(_wstName, &sci_dummy_in_NWNI_OLDC, NULL, _wstModule);
152             case FunctionType::EntryPointCPP:
153                 return new Function(_wstName, &sci_dummy_in_NWNI, NULL, _wstModule);
154             case FunctionType::EntryPointMex:
155                 return new WrapMexFunction(_wstName, &sci_dummy_in_NWNI_MEX, NULL, _wstModule);
156             case FunctionType::EntryPointCPPOpt:
157                 return new OptFunction(_wstName, &sci_dummy_in_NWNI_OPT, NULL, _wstModule);
158             case FunctionType::EntryPointC:
159                 return new WrapCFunction(_wstName, &sci_dummy_in_NWNI_C, NULL, _wstModule);
160         }
161     }
162     else
163     {
164         return new DynamicFunction(_wstName, _wstEntryPointName, _wstLibName, _iType, _wstLoadDepsName, _wstModule, _bCloseLibAfterCall);
165     }
166
167     // must never append
168     return NULL;
169 }
170
171 Function* Function::createFunction(const std::wstring& _wstName, GW_C_FUNC _pFunc, const std::wstring& _wstModule)
172 {
173     return new WrapCFunction(_wstName, _pFunc, NULL, _wstModule);
174 }
175
176 Function* Function::createFunction(const std::wstring& _wstName, GW_C_FUNC _pFunc, LOAD_DEPS _pLoadDeps, const std::wstring& _wstModule)
177 {
178     return new WrapCFunction(_wstName, _pFunc, _pLoadDeps, _wstModule);
179 }
180
181
182 Function::Function(const std::wstring& _wstName, GW_FUNC _pFunc, LOAD_DEPS _pLoadDeps, const std::wstring& _wstModule) : Callable(), m_pFunc(_pFunc), m_pLoadDeps(_pLoadDeps)
183 {
184     setName(_wstName);
185     char* s = wide_string_to_UTF8(m_wstName.data());
186     m_stName = s;
187     FREE(s);
188
189     setModule(_wstModule);
190 }
191
192 Function::~Function()
193 {
194
195 }
196
197
198 Function::ReturnValue Function::call(typed_list &in, optional_list &/*opt*/, int _iRetCount, typed_list &out)
199 {
200     int ret = 1;
201     if (m_pLoadDeps != NULL)
202     {
203         ret = m_pLoadDeps(m_wstName);
204     }
205
206     if (ret == 0)
207     {
208         return Error;
209     }
210
211     return this->m_pFunc(in, _iRetCount, out);
212 }
213
214 void Function::whoAmI()
215 {
216     std::cout << "types::Function";
217 }
218
219 bool Function::toString(std::wostringstream& /*ostr*/)
220 {
221     // display nothing. ie : c = cos
222     return true;
223 }
224
225 Function* Function::clone()
226 {
227     IncreaseRef();
228     return this;
229 }
230
231 bool Function::operator==(const InternalType& it)
232 {
233     if (!const_cast<InternalType &>(it).isFunction())
234     {
235         return false;
236     }
237     return this->getFunc() == const_cast<InternalType &>(it).getAs<Function>()->getFunc();
238 }
239
240 OptFunction::OptFunction(const std::wstring& _wstName, GW_FUNC_OPT _pFunc, LOAD_DEPS _pLoadDeps, const std::wstring& _wstModule)
241 {
242     m_wstName = _wstName;
243     char* s = wide_string_to_UTF8(m_wstName.data());
244     m_stName = s;
245     FREE(s);
246     m_pFunc = _pFunc;
247     m_pLoadDeps = _pLoadDeps;
248     m_wstModule = _wstModule;
249 }
250
251 OptFunction::OptFunction(OptFunction* _pWrapFunction)
252 {
253     m_wstModule  = _pWrapFunction->getModule();
254     m_wstName    = _pWrapFunction->getName();
255     char* s = wide_string_to_UTF8(m_wstName.data());
256     m_stName = s;
257     FREE(s);
258     m_pFunc = _pWrapFunction->getFunc();
259     m_pLoadDeps = _pWrapFunction->getDeps();
260 }
261
262 OptFunction* OptFunction::clone()
263 {
264     return new OptFunction(this);
265 }
266
267 Function::ReturnValue OptFunction::call(typed_list &in, optional_list &opt, int _iRetCount, typed_list &out)
268 {
269     int ret = 1;
270     if (m_pLoadDeps != NULL)
271     {
272         ret = m_pLoadDeps(m_wstName);
273     }
274
275     if (ret == 0)
276     {
277         return Error;
278     }
279
280     return this->m_pFunc(in, opt, _iRetCount, out);
281 }
282
283 WrapFunction::WrapFunction(const std::wstring& _wstName, OLDGW_FUNC _pFunc, LOAD_DEPS _pLoadDeps, const std::wstring& _wstModule)
284 {
285     m_wstName = _wstName;
286     m_pOldFunc = _pFunc;
287     m_wstModule = _wstModule;
288     char* s = wide_string_to_UTF8(m_wstName.data());
289     m_stName = s;
290     FREE(s);
291     m_pLoadDeps = _pLoadDeps;
292 }
293
294 WrapFunction::WrapFunction(WrapFunction* _pWrapFunction)
295 {
296     m_wstModule = _pWrapFunction->getModule();
297     m_wstName = _pWrapFunction->getName();
298     char* s = wide_string_to_UTF8(m_wstName.data());
299     m_stName = s;
300     FREE(s);
301     m_pOldFunc  = _pWrapFunction->getFunc();
302     m_pLoadDeps = _pWrapFunction->getDeps();
303 }
304
305 WrapFunction* WrapFunction::clone()
306 {
307     return new WrapFunction(this);
308 }
309
310 Function::ReturnValue WrapFunction::call(typed_list &in, optional_list &opt, int _iRetCount, typed_list &out)
311 {
312     int ret = 1;
313     int inSize = (int)in.size();
314     int optSize = (int)opt.size();
315     int isRef = checkReferenceModule(m_wstModule.c_str());
316
317     if (m_pLoadDeps != NULL)
318     {
319         ret = m_pLoadDeps(m_wstName);
320     }
321
322     if (ret == 0)
323     {
324         return Error;
325     }
326
327     ReturnValue retVal = Callable::OK;
328     GatewayStruct gStr;
329     _iRetCount = std::max(1, _iRetCount);
330     gStr.m_iIn = inSize + optSize;
331     gStr.m_iOut = _iRetCount;
332
333     //copy input parameter to prevent calling gateway modifies input data
334     typed_list inCopy;
335
336     if (isRef == 0)
337     {
338         for (int i = 0; i < inSize; i++)
339         {
340             inCopy.push_back(in[i]->clone());
341         }
342     }
343     else
344     {
345         for (int i = 0; i < inSize; i++)
346         {
347             inCopy.push_back(in[i]);
348         }
349     }
350     gStr.m_pIn = &inCopy;
351     gStr.m_pOpt = &opt;
352     typed_list::value_type tmpOut[MAX_OUTPUT_VARIABLE];
353     std::fill_n(tmpOut, MAX_OUTPUT_VARIABLE, static_cast<typed_list::value_type>(0));
354     gStr.m_pOut = tmpOut;
355     gStr.m_piRetCount = &_iRetCount;
356     gStr.m_pstName = m_stName.data();
357     // we should use a stack array of the max size to avoid dynamic alloc.
358     std::vector<int> outOrder(_iRetCount < 1 ? 1 : _iRetCount, -1);
359     gStr.m_pOutOrder = outOrder.data();
360
361     //call gateway
362     m_pOldFunc(const_cast<char*>(m_stName.data()), reinterpret_cast<int*>(&gStr));
363     if (ConfigVariable::isError())
364     {
365         retVal = Callable::Error;
366         ConfigVariable::resetError();
367     }
368     else
369     {
370         for (std::size_t i(0); i != (size_t)_iRetCount && outOrder[i] != -1 && outOrder[i] != 0; ++i)
371         {
372             if (outOrder[i] - 1 < gStr.m_iIn)
373             {
374                 std::size_t const iPos(outOrder[i] - 1);
375                 //protect variable to deletion
376                 inCopy[iPos]->IncreaseRef();
377                 if (inCopy[iPos]->isDouble() && ((types::Double*)inCopy[iPos])->isViewAsInteger())
378                 {
379                     types::Double* pD = inCopy[iPos]->getAs<types::Double>();
380                     pD->convertFromInteger();
381                 }
382
383                 if (inCopy[iPos]->isDouble() && ((types::Double*)inCopy[iPos])->isViewAsZComplex())
384                 {
385                     types::Double* pD = inCopy[iPos]->getAs<types::Double>();
386                     pD->convertFromZComplex();
387                 }
388
389                 out.push_back(inCopy[iPos]);
390             }
391             else
392             {
393                 std::size_t const iPos(outOrder[i] - gStr.m_iIn - 1);
394                 if (tmpOut[iPos]->isDouble() && ((types::Double*)tmpOut[iPos])->isViewAsInteger())
395                 {
396                     types::Double* pD = tmpOut[iPos]->getAs<types::Double>();
397                     pD->convertFromInteger();
398                 }
399
400                 if (tmpOut[iPos]->isDouble() && ((types::Double*)tmpOut[iPos])->isViewAsZComplex())
401                 {
402                     types::Double* pD = tmpOut[iPos]->getAs<types::Double>();
403                     pD->convertFromZComplex();
404                 }
405
406                 out.push_back(tmpOut[iPos]);
407                 tmpOut[iPos] = 0;
408             }
409         }
410     }
411
412     for (std::size_t i(0); i != MAX_OUTPUT_VARIABLE; ++i)
413     {
414         if (tmpOut[i])
415         {
416             tmpOut[i]->killMe();
417         }
418     }
419
420     //clean input copy
421     if (isRef == 0)
422     {
423         //protect outputs
424         int size = (int)out.size();
425         for (int i = 0; i < size; i++)
426         {
427             out[i]->IncreaseRef();
428         }
429
430         for (int i = 0; i < inSize; i++)
431         {
432             inCopy[i]->killMe();
433         }
434
435         //unprotect outputs
436         for (int i = 0; i < size; i++)
437         {
438             out[i]->DecreaseRef();
439         }
440     }
441
442     return retVal;
443 }
444
445 WrapMexFunction::WrapMexFunction(const std::wstring& _wstName, MEXGW_FUNC _pFunc, LOAD_DEPS _pLoadDeps, const std::wstring& _wstModule)
446 {
447     m_wstName = _wstName;
448     char* s = wide_string_to_UTF8(m_wstName.data());
449     m_stName = s;
450     FREE(s);
451     m_pOldFunc = _pFunc;
452     m_wstModule = _wstModule;
453     m_pLoadDeps = _pLoadDeps;
454 }
455
456 WrapMexFunction::WrapMexFunction(WrapMexFunction* _pWrapFunction)
457 {
458     m_wstModule = _pWrapFunction->getModule();
459     char* s = wide_string_to_UTF8(m_wstName.data());
460     m_stName = s;
461     FREE(s);
462     m_wstName = _pWrapFunction->getName();
463     m_pOldFunc = _pWrapFunction->getFunc();
464     m_pLoadDeps = _pWrapFunction->getDeps();
465 }
466
467 WrapMexFunction* WrapMexFunction::clone()
468 {
469     return new WrapMexFunction(this);
470 }
471
472 Function::ReturnValue WrapMexFunction::call(typed_list &in, optional_list &/*opt*/, int _iRetCount, typed_list &out)
473 {
474     int ret = 1;
475     if (m_pLoadDeps != NULL)
476     {
477         ret = m_pLoadDeps(m_wstName);
478     }
479
480     if (ret == 0)
481     {
482         return Error;
483     }
484
485     ReturnValue retVal = Callable::OK;
486
487     char* name = wide_string_to_UTF8(getName().c_str());
488     ConfigVariable::setMexFunctionName(name);
489     FREE(name);
490
491     int nlhs = _iRetCount;
492     int** plhs = new int*[nlhs];
493     memset(plhs, 0x00, sizeof(int*) * nlhs);
494
495     int nrhs = (int)in.size();
496     int** prhs = new int*[nrhs];
497     for (int i = 0; i < nrhs; i++)
498     {
499         prhs[i] = (int*)(in[i]);
500     }
501
502     try
503     {
504         m_pOldFunc(nlhs, plhs, nrhs, prhs);
505     }
506     catch (const ast::InternalError& ie)
507     {
508         delete[] plhs;
509         delete[] prhs;
510         throw ie;
511     }
512
513     if (_iRetCount == 1 && plhs[0] == NULL)
514     {
515         //dont copy empty values, juste return "no value"
516         return retVal;
517     }
518
519     for (int i = 0; i < nlhs; i++)
520     {
521         out.push_back((types::InternalType*)plhs[i]);
522     }
523
524     delete[] plhs;
525     delete[] prhs;
526     return retVal;
527 }
528
529 WrapCFunction::WrapCFunction(const std::wstring& _wstName, GW_C_FUNC _pFunc, LOAD_DEPS _pLoadDeps, const std::wstring& _wstModule)
530 {
531     m_wstName = _wstName;
532     char* s = wide_string_to_UTF8(m_wstName.data());
533     m_stName = s;
534     FREE(s);
535     m_pCFunc = _pFunc;
536     m_wstModule = _wstModule;
537     m_pLoadDeps = _pLoadDeps;
538 }
539
540 WrapCFunction::WrapCFunction(WrapCFunction* _pWrapFunction)
541 {
542     m_wstModule = _pWrapFunction->getModule();
543     char* s = wide_string_to_UTF8(m_wstName.data());
544     m_stName = s;
545     FREE(s);
546     m_wstName = _pWrapFunction->getName();
547     m_pCFunc = _pWrapFunction->getFunc();
548     m_pLoadDeps = _pWrapFunction->getDeps();
549 }
550
551 WrapCFunction* WrapCFunction::clone()
552 {
553     return new WrapCFunction(this);
554 }
555
556 Function::ReturnValue WrapCFunction::call(typed_list& in, optional_list& opt, int _iRetCount, typed_list& out)
557 {
558     if (m_pLoadDeps != NULL)
559     {
560         if (m_pLoadDeps(m_wstName) == 0)
561         {
562             return Error;
563         }
564     }
565
566     ReturnValue retVal = OK;
567
568     try
569     {
570         GatewayCStruct gcs;
571         gcs.name = m_stName;
572         out.resize(_iRetCount, NULL);
573         if (m_pCFunc((void*)&gcs, (int)in.size(), (scilabVar*)(in.data()), (int)opt.size(), (scilabOpt)&opt, _iRetCount, (scilabVar*)(out.data())))
574         {
575             retVal = Error;
576         }
577     }
578     catch (const ast::InternalError& ie)
579     {
580         throw ie;
581     }
582
583     if (retVal == OK)
584     {
585         if (_iRetCount == 1 && out[0] == NULL)
586         {
587             //dont copy empty values, juste return "no value"
588             out.clear();
589             return retVal;
590         }
591     }
592
593     return retVal;
594 }
595
596 DynamicFunction::DynamicFunction(const std::wstring& _wstName, const std::wstring& _wstEntryPointName, const std::wstring& _wstLibName, FunctionType _iType, const std::wstring& _wstLoadDepsName, const std::wstring& _wstModule, bool _bCloseLibAfterCall)
597 {
598     m_wstName               = _wstName;
599     char* s = wide_string_to_UTF8(m_wstName.data());
600     m_stName = s;
601     FREE(s);
602     m_wstLibName = _wstLibName;
603     m_wstModule             = _wstModule;
604     m_wstEntryPoint         = _wstEntryPointName;
605     m_wstLoadDepsName       = _wstLoadDepsName;
606     m_pLoadDeps             = NULL;
607     m_bCloseLibAfterCall    = _bCloseLibAfterCall;
608     m_iType                 = _iType;
609     m_pFunc                 = NULL;
610     m_pOptFunc              = NULL;
611     m_pOldFunc              = NULL;
612     m_pMexFunc              = NULL;
613     m_pFunction             = NULL;
614     m_pCFunc                = NULL;
615 }
616
617 DynamicFunction::DynamicFunction(const std::wstring& _wstName, const std::wstring& _wstEntryPointName, const std::wstring& _wstLibName, FunctionType _iType, LOAD_DEPS _pLoadDeps, const std::wstring& _wstModule, bool _bCloseLibAfterCall)
618 {
619     m_wstName               = _wstName;
620     char* s = wide_string_to_UTF8(m_wstName.data());
621     m_stName = s;
622     FREE(s);
623     m_wstLibName = _wstLibName;
624     m_wstModule             = _wstModule;
625     m_wstEntryPoint         = _wstEntryPointName;
626     m_pLoadDeps             = _pLoadDeps;
627     m_wstLoadDepsName       = L"";
628     m_bCloseLibAfterCall    = _bCloseLibAfterCall;
629     m_iType                 = _iType;
630     m_pFunc                 = NULL;
631     m_pOptFunc              = NULL;
632     m_pOldFunc              = NULL;
633     m_pMexFunc              = NULL;
634     m_pFunction             = NULL;
635     m_pCFunc                = NULL;
636 }
637
638 Function::ReturnValue DynamicFunction::call(typed_list &in, optional_list &opt, int _iRetCount, typed_list &out)
639 {
640     if (m_pFunction == NULL)
641     {
642         if (Init() != OK)
643         {
644             return Error;
645         }
646     }
647
648     /*call function*/
649     if (m_pFunction->call(in, opt, _iRetCount, out) != OK)
650     {
651         return Error;
652     }
653
654     /*Close lib is mandatory*/
655     if (m_bCloseLibAfterCall)
656     {
657         Clear();
658     }
659
660     return OK;
661 }
662
663 DynamicFunction::~DynamicFunction()
664 {
665     if (m_pFunction)
666     {
667         delete m_pFunction;
668     }
669 }
670
671 Callable::ReturnValue DynamicFunction::Init()
672 {
673     /*Load library*/
674     if (m_wstLibName.empty())
675     {
676         Scierror(999, _("%s: Library name must not be empty\n."), m_wstName.c_str());
677         return Error;
678     }
679
680     DynLibHandle hLib = getDynModule(m_wstLibName.c_str());
681     if (hLib == 0)
682     {
683         char* pstLibName = wide_string_to_UTF8(m_wstLibName.c_str());
684         hLib = LoadDynLibrary(pstLibName);
685
686         if (hLib == 0)
687         {
688             //2nd chance for linux !
689 #ifndef _MSC_VER
690             char* pstError = strdup(GetLastDynLibError());
691
692             /* Haven't been able to find the lib with dlopen...
693             * This can happen for two reasons:
694             * - the lib must be dynamically linked
695             * - Some silly issues under Suse (see bug #2875)
696             * Note that we are handling only the "source tree build"
697             * because libraries are split (they are in the same directory
698             * in the binary)
699             */
700             wchar_t* pwstScilabPath = getSCIW();
701             wchar_t pwstModulesPath[] = L"/modules/";
702             wchar_t pwstLTDir[] =  L".libs/";
703
704             /* Build the full path to the library */
705             int iPathToLibLen = (wcslen(pwstScilabPath) + wcslen(pwstModulesPath) + wcslen(m_wstModule.c_str()) + wcslen(L"/") + wcslen(pwstLTDir) + wcslen(m_wstLibName.c_str()) + 1);
706             wchar_t* pwstPathToLib = (wchar_t*)MALLOC(iPathToLibLen * sizeof(wchar_t));
707             os_swprintf(pwstPathToLib, iPathToLibLen, L"%ls%ls%ls/%ls%ls", pwstScilabPath, pwstModulesPath, m_wstModule.c_str(), pwstLTDir, m_wstLibName.c_str());
708             FREE(pwstScilabPath);
709             char* pstPathToLib = wide_string_to_UTF8(pwstPathToLib);
710             FREE(pwstPathToLib);
711             hLib = LoadDynLibrary(pstPathToLib);
712
713             if (hLib == 0)
714             {
715                 Scierror(999, _("An error has been detected while loading %s: %s\n"), pstLibName, pstError);
716                 FREE(pstError);
717
718                 pstError = GetLastDynLibError();
719                 Scierror(999, _("An error has been detected while loading %s: %s\n"), pstPathToLib, pstError);
720
721                 FREE(pstLibName);
722                 FREE(pstPathToLib);
723                 return Error;
724             }
725             FREE(pstPathToLib);
726             FREE(pstError);
727 #else
728             char* pstError = wide_string_to_UTF8(m_wstLibName.c_str());
729             Scierror(999, _("Impossible to load %s library\n"), pstError);
730             FREE(pstError);
731             FREE(pstLibName);
732             return Error;
733 #endif
734         }
735         FREE(pstLibName);
736         addDynModule(m_wstLibName.c_str(), hLib);
737
738         /*Load deps*/
739         if (m_wstLoadDepsName.empty() == false && m_pLoadDeps == NULL)
740         {
741             char* pstLoadDepsName = wide_string_to_UTF8(m_wstLoadDepsName.c_str());
742             m_pLoadDeps = (LOAD_DEPS)GetDynLibFuncPtr(hLib, pstLoadDepsName);
743             FREE(pstLoadDepsName);
744         }
745
746     }
747
748     /*Load gateway*/
749     if (m_wstName != L"")
750     {
751         char* pstEntryPoint = wide_string_to_UTF8(m_wstEntryPoint.c_str());
752         switch (m_iType)
753         {
754             case EntryPointCPPOpt :
755                 m_pOptFunc = (GW_FUNC_OPT)GetDynLibFuncPtr(hLib, pstEntryPoint);
756                 break;
757             case EntryPointCPP :
758                 m_pFunc = (GW_FUNC)GetDynLibFuncPtr(hLib, pstEntryPoint);
759                 break;
760             case EntryPointOldC :
761                 m_pOldFunc = (OLDGW_FUNC)GetDynLibFuncPtr(hLib, pstEntryPoint);
762                 break;
763             case EntryPointMex:
764                 m_pMexFunc = (MEXGW_FUNC)GetDynLibFuncPtr(hLib, pstEntryPoint);
765                 break;
766             case EntryPointC:
767                 m_pCFunc = (GW_C_FUNC)GetDynLibFuncPtr(hLib, pstEntryPoint);
768                 break;
769         }
770
771         FREE(pstEntryPoint);
772     }
773
774     if (m_pFunc == NULL && m_pOldFunc == NULL && m_pMexFunc == NULL && m_pOptFunc == NULL && m_pCFunc == NULL)
775     {
776         char* pstEntry = wide_string_to_UTF8(m_wstEntryPoint.c_str());
777         char* pstLib = wide_string_to_UTF8(m_wstLibName.c_str());
778         Scierror(999, _("Impossible to load %s function in %s library: %s\n"), pstEntry, pstLib, GetLastDynLibError());
779         FREE(pstEntry);
780         FREE(pstLib);
781         return Error;
782     }
783
784     switch (m_iType)
785     {
786         case EntryPointCPPOpt :
787             m_pFunction = new OptFunction(m_wstName, m_pOptFunc, m_pLoadDeps, m_wstModule);
788             break;
789         case EntryPointCPP :
790             m_pFunction = new Function(m_wstName, m_pFunc, m_pLoadDeps, m_wstModule);
791             break;
792         case EntryPointOldC :
793             m_pFunction = new WrapFunction(m_wstName, m_pOldFunc, m_pLoadDeps, m_wstModule);
794             break;
795         case EntryPointMex:
796             m_pFunction = new WrapMexFunction(m_wstName, m_pMexFunc, m_pLoadDeps, m_wstModule);
797             break;
798         case EntryPointC:
799             m_pFunction = new WrapCFunction(m_wstName, m_pCFunc, m_pLoadDeps, m_wstModule);
800             break;
801     }
802
803     if (m_pFunction == NULL)
804     {
805         return Error;
806     }
807     return OK;
808 }
809
810 void DynamicFunction::Clear()
811 {
812     m_pFunc     = NULL;
813     m_pOldFunc  = NULL;
814     m_pMexFunc  = NULL;
815 }
816
817 }