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