check view as integer after call of C gateway
[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     else
442     {
443         for (int i = 0; i < in.size(); ++i)
444         {
445             if (in[i]->isDouble() && ((types::Double*)in[i])->isViewAsInteger())
446             {
447                 types::Double* pD = in[i]->getAs<types::Double>();
448                 pD->convertFromInteger();
449             }
450         }
451
452     }
453
454     for (auto i : opt)
455     {
456         if (i.second->isDouble() && ((types::Double*)i.second)->isViewAsInteger())
457         {
458             types::Double* pD = i.second->getAs<types::Double>();
459             pD->convertFromInteger();
460         }
461     }
462
463     return retVal;
464 }
465
466 WrapMexFunction::WrapMexFunction(const std::wstring& _wstName, MEXGW_FUNC _pFunc, LOAD_DEPS _pLoadDeps, const std::wstring& _wstModule)
467 {
468     m_wstName = _wstName;
469     char* s = wide_string_to_UTF8(m_wstName.data());
470     m_stName = s;
471     FREE(s);
472     m_pOldFunc = _pFunc;
473     m_wstModule = _wstModule;
474     m_pLoadDeps = _pLoadDeps;
475 }
476
477 WrapMexFunction::WrapMexFunction(WrapMexFunction* _pWrapFunction)
478 {
479     m_wstModule = _pWrapFunction->getModule();
480     char* s = wide_string_to_UTF8(m_wstName.data());
481     m_stName = s;
482     FREE(s);
483     m_wstName = _pWrapFunction->getName();
484     m_pOldFunc = _pWrapFunction->getFunc();
485     m_pLoadDeps = _pWrapFunction->getDeps();
486 }
487
488 WrapMexFunction* WrapMexFunction::clone()
489 {
490     return new WrapMexFunction(this);
491 }
492
493 Function::ReturnValue WrapMexFunction::call(typed_list &in, optional_list &/*opt*/, int _iRetCount, typed_list &out)
494 {
495     int ret = 1;
496     if (m_pLoadDeps != NULL)
497     {
498         ret = m_pLoadDeps(m_wstName);
499     }
500
501     if (ret == 0)
502     {
503         return Error;
504     }
505
506     ReturnValue retVal = Callable::OK;
507
508     char* name = wide_string_to_UTF8(getName().c_str());
509     ConfigVariable::setMexFunctionName(name);
510     FREE(name);
511
512     int nlhs = _iRetCount;
513     int** plhs = new int*[nlhs];
514     memset(plhs, 0x00, sizeof(int*) * nlhs);
515
516     int nrhs = (int)in.size();
517     int** prhs = new int*[nrhs];
518     for (int i = 0; i < nrhs; i++)
519     {
520         prhs[i] = (int*)(in[i]);
521     }
522
523     try
524     {
525         m_pOldFunc(nlhs, plhs, nrhs, prhs);
526     }
527     catch (const ast::InternalError& ie)
528     {
529         delete[] plhs;
530         delete[] prhs;
531         throw ie;
532     }
533
534     if (_iRetCount == 1 && plhs[0] == NULL)
535     {
536         //dont copy empty values, juste return "no value"
537         return retVal;
538     }
539
540     for (int i = 0; i < nlhs; i++)
541     {
542         out.push_back((types::InternalType*)plhs[i]);
543     }
544
545     delete[] plhs;
546     delete[] prhs;
547     return retVal;
548 }
549
550 WrapCFunction::WrapCFunction(const std::wstring& _wstName, GW_C_FUNC _pFunc, LOAD_DEPS _pLoadDeps, const std::wstring& _wstModule)
551 {
552     m_wstName = _wstName;
553     char* s = wide_string_to_UTF8(m_wstName.data());
554     m_stName = s;
555     FREE(s);
556     m_pCFunc = _pFunc;
557     m_wstModule = _wstModule;
558     m_pLoadDeps = _pLoadDeps;
559 }
560
561 WrapCFunction::WrapCFunction(WrapCFunction* _pWrapFunction)
562 {
563     m_wstModule = _pWrapFunction->getModule();
564     char* s = wide_string_to_UTF8(m_wstName.data());
565     m_stName = s;
566     FREE(s);
567     m_wstName = _pWrapFunction->getName();
568     m_pCFunc = _pWrapFunction->getFunc();
569     m_pLoadDeps = _pWrapFunction->getDeps();
570 }
571
572 WrapCFunction* WrapCFunction::clone()
573 {
574     return new WrapCFunction(this);
575 }
576
577 Function::ReturnValue WrapCFunction::call(typed_list& in, optional_list& opt, int _iRetCount, typed_list& out)
578 {
579     if (m_pLoadDeps != NULL)
580     {
581         if (m_pLoadDeps(m_wstName) == 0)
582         {
583             return Error;
584         }
585     }
586
587     ReturnValue retVal = OK;
588
589     try
590     {
591         GatewayCStruct gcs;
592         gcs.name = m_stName;
593         out.resize(_iRetCount, NULL);
594         if (m_pCFunc((void*)&gcs, (int)in.size(), (scilabVar*)(in.data()), (int)opt.size(), (scilabOpt)&opt, _iRetCount, (scilabVar*)(out.data())))
595         {
596             retVal = Error;
597         }
598     }
599     catch (const ast::InternalError& ie)
600     {
601         throw ie;
602     }
603
604     if (retVal == OK)
605     {
606         if (_iRetCount == 1 && out[0] == NULL)
607         {
608             //dont copy empty values, juste return "no value"
609             out.clear();
610             return retVal;
611         }
612     }
613
614     return retVal;
615 }
616
617 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)
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_wstLoadDepsName       = _wstLoadDepsName;
627     m_pLoadDeps             = NULL;
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 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)
639 {
640     m_wstName               = _wstName;
641     char* s = wide_string_to_UTF8(m_wstName.data());
642     m_stName = s;
643     FREE(s);
644     m_wstLibName = _wstLibName;
645     m_wstModule             = _wstModule;
646     m_wstEntryPoint         = _wstEntryPointName;
647     m_pLoadDeps             = _pLoadDeps;
648     m_wstLoadDepsName       = L"";
649     m_bCloseLibAfterCall    = _bCloseLibAfterCall;
650     m_iType                 = _iType;
651     m_pFunc                 = NULL;
652     m_pOptFunc              = NULL;
653     m_pOldFunc              = NULL;
654     m_pMexFunc              = NULL;
655     m_pFunction             = NULL;
656     m_pCFunc                = NULL;
657 }
658
659 Function::ReturnValue DynamicFunction::call(typed_list &in, optional_list &opt, int _iRetCount, typed_list &out)
660 {
661     if (m_pFunction == NULL)
662     {
663         if (Init() != OK)
664         {
665             return Error;
666         }
667     }
668
669     /*call function*/
670     if (m_pFunction->call(in, opt, _iRetCount, out) != OK)
671     {
672         return Error;
673     }
674
675     /*Close lib is mandatory*/
676     if (m_bCloseLibAfterCall)
677     {
678         Clear();
679     }
680
681     return OK;
682 }
683
684 DynamicFunction::~DynamicFunction()
685 {
686     if (m_pFunction)
687     {
688         delete m_pFunction;
689     }
690 }
691
692 Callable::ReturnValue DynamicFunction::Init()
693 {
694     /*Load library*/
695     if (m_wstLibName.empty())
696     {
697         Scierror(999, _("%s: Library name must not be empty\n."), m_wstName.c_str());
698         return Error;
699     }
700
701     DynLibHandle hLib = getDynModule(m_wstLibName.c_str());
702     if (hLib == 0)
703     {
704         char* pstLibName = wide_string_to_UTF8(m_wstLibName.c_str());
705         hLib = LoadDynLibrary(pstLibName);
706
707         if (hLib == 0)
708         {
709             //2nd chance for linux !
710 #ifndef _MSC_VER
711             char* pstError = strdup(GetLastDynLibError());
712
713             /* Haven't been able to find the lib with dlopen...
714             * This can happen for two reasons:
715             * - the lib must be dynamically linked
716             * - Some silly issues under Suse (see bug #2875)
717             * Note that we are handling only the "source tree build"
718             * because libraries are split (they are in the same directory
719             * in the binary)
720             */
721             wchar_t* pwstScilabPath = getSCIW();
722             wchar_t pwstModulesPath[] = L"/modules/";
723             wchar_t pwstLTDir[] =  L".libs/";
724
725             /* Build the full path to the library */
726             int iPathToLibLen = (wcslen(pwstScilabPath) + wcslen(pwstModulesPath) + wcslen(m_wstModule.c_str()) + wcslen(L"/") + wcslen(pwstLTDir) + wcslen(m_wstLibName.c_str()) + 1);
727             wchar_t* pwstPathToLib = (wchar_t*)MALLOC(iPathToLibLen * sizeof(wchar_t));
728             os_swprintf(pwstPathToLib, iPathToLibLen, L"%ls%ls%ls/%ls%ls", pwstScilabPath, pwstModulesPath, m_wstModule.c_str(), pwstLTDir, m_wstLibName.c_str());
729             FREE(pwstScilabPath);
730             char* pstPathToLib = wide_string_to_UTF8(pwstPathToLib);
731             FREE(pwstPathToLib);
732             hLib = LoadDynLibrary(pstPathToLib);
733
734             if (hLib == 0)
735             {
736                 Scierror(999, _("An error has been detected while loading %s: %s\n"), pstLibName, pstError);
737                 FREE(pstError);
738
739                 pstError = GetLastDynLibError();
740                 Scierror(999, _("An error has been detected while loading %s: %s\n"), pstPathToLib, pstError);
741
742                 FREE(pstLibName);
743                 FREE(pstPathToLib);
744                 return Error;
745             }
746             FREE(pstPathToLib);
747             FREE(pstError);
748 #else
749             char* pstError = wide_string_to_UTF8(m_wstLibName.c_str());
750             Scierror(999, _("Impossible to load %s library\n"), pstError);
751             FREE(pstError);
752             FREE(pstLibName);
753             return Error;
754 #endif
755         }
756         FREE(pstLibName);
757         addDynModule(m_wstLibName.c_str(), hLib);
758
759         /*Load deps*/
760         if (m_wstLoadDepsName.empty() == false && m_pLoadDeps == NULL)
761         {
762             char* pstLoadDepsName = wide_string_to_UTF8(m_wstLoadDepsName.c_str());
763             m_pLoadDeps = (LOAD_DEPS)GetDynLibFuncPtr(hLib, pstLoadDepsName);
764             FREE(pstLoadDepsName);
765         }
766
767     }
768
769     /*Load gateway*/
770     if (m_wstName != L"")
771     {
772         char* pstEntryPoint = wide_string_to_UTF8(m_wstEntryPoint.c_str());
773         switch (m_iType)
774         {
775             case EntryPointCPPOpt :
776                 m_pOptFunc = (GW_FUNC_OPT)GetDynLibFuncPtr(hLib, pstEntryPoint);
777                 break;
778             case EntryPointCPP :
779                 m_pFunc = (GW_FUNC)GetDynLibFuncPtr(hLib, pstEntryPoint);
780                 break;
781             case EntryPointOldC :
782                 m_pOldFunc = (OLDGW_FUNC)GetDynLibFuncPtr(hLib, pstEntryPoint);
783                 break;
784             case EntryPointMex:
785                 m_pMexFunc = (MEXGW_FUNC)GetDynLibFuncPtr(hLib, pstEntryPoint);
786                 break;
787             case EntryPointC:
788                 m_pCFunc = (GW_C_FUNC)GetDynLibFuncPtr(hLib, pstEntryPoint);
789                 break;
790         }
791
792         FREE(pstEntryPoint);
793     }
794
795     if (m_pFunc == NULL && m_pOldFunc == NULL && m_pMexFunc == NULL && m_pOptFunc == NULL && m_pCFunc == NULL)
796     {
797         char* pstEntry = wide_string_to_UTF8(m_wstEntryPoint.c_str());
798         char* pstLib = wide_string_to_UTF8(m_wstLibName.c_str());
799         Scierror(999, _("Impossible to load %s function in %s library: %s\n"), pstEntry, pstLib, GetLastDynLibError());
800         FREE(pstEntry);
801         FREE(pstLib);
802         return Error;
803     }
804
805     switch (m_iType)
806     {
807         case EntryPointCPPOpt :
808             m_pFunction = new OptFunction(m_wstName, m_pOptFunc, m_pLoadDeps, m_wstModule);
809             break;
810         case EntryPointCPP :
811             m_pFunction = new Function(m_wstName, m_pFunc, m_pLoadDeps, m_wstModule);
812             break;
813         case EntryPointOldC :
814             m_pFunction = new WrapFunction(m_wstName, m_pOldFunc, m_pLoadDeps, m_wstModule);
815             break;
816         case EntryPointMex:
817             m_pFunction = new WrapMexFunction(m_wstName, m_pMexFunc, m_pLoadDeps, m_wstModule);
818             break;
819         case EntryPointC:
820             m_pFunction = new WrapCFunction(m_wstName, m_pCFunc, m_pLoadDeps, m_wstModule);
821             break;
822     }
823
824     if (m_pFunction == NULL)
825     {
826         return Error;
827     }
828     return OK;
829 }
830
831 void DynamicFunction::Clear()
832 {
833     m_pFunc     = NULL;
834     m_pOldFunc  = NULL;
835     m_pMexFunc  = NULL;
836 }
837
838 }