1 /*
2  * Copyright (c) 2006-2024 RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author        Notes
8  * 2010-11-17      yi.qiu   first version
9  */
10 
11 #include <rtthread.h>
12 #include <rtm.h>
13 #include <string.h>
14 
15 #include "dlmodule.h"
16 
17 #define MODULE_ROOT_DIR     "/modules"
18 
19 /**
20  * @brief  dynamically load a shared library at runtime.
21  *
22  * @param  filename the path to the shared library to load, which shouldn't be set to NULL.
23  * @param  flags options for loading the shared library.
24  * @return void* on success, it returns a handle (a pointer) to the opened shared library, otherwise it returns NULL.
25  *
26  * @note   This function is an API of POSIX standard, which is used for dynamically loading shared libraries at runtime.
27  *         the function first tries to check if the module is already loaded, by finding module in module list.
28  *         If module is found in memory (RT_NULL check fails), the reference count (nref) is incremented.
29  *         Otherwise,  dlmodule_load() will be called to load the module into memory.
30  *         A handle (a pointer to the module) is returned at last, which can be used with other functions like dlsym().
31  */
dlopen(const char * filename,int flags)32 void* dlopen(const char *filename, int flags)
33 {
34     struct rt_dlmodule *module;
35     char *fullpath;
36     const char*def_path = MODULE_ROOT_DIR;
37 
38     /* check parameters */
39     RT_ASSERT(filename != RT_NULL);
40 
41     if (filename[0] != '/') /* it's a relative path, prefix with MODULE_ROOT_DIR */
42     {
43         fullpath = rt_malloc(strlen(def_path) + strlen(filename) + 2);
44 
45         /* join path and file name */
46         rt_snprintf(fullpath, strlen(def_path) + strlen(filename) + 2,
47             "%s/%s", def_path, filename);
48     }
49     else
50     {
51         fullpath = (char*)filename; /* absolute path, use it directly */
52     }
53 
54     rt_enter_critical();
55 
56     /* find in module list */
57     module = dlmodule_find(fullpath);
58 
59     if(module != RT_NULL)
60     {
61         rt_exit_critical();
62         module->nref++;
63     }
64     else
65     {
66         rt_exit_critical();
67         module = dlmodule_load(fullpath);
68     }
69 
70     if(fullpath != filename)
71     {
72         rt_free(fullpath);
73     }
74 
75     return (void*)module;
76 }
77 RTM_EXPORT(dlopen);
78