Document of c-modernization-kit (funcman) 1.0.0

Loading...
Searching...
No Matches
funcman_get_func.c
Go to the documentation of this file.
1
16
17#include <funcman.h>
18#include <string.h>
19
20/* doxygen コメントは、ヘッダに記載 */
21 void *_funcman_get_func(funcman_object *fobj)
22{
23#ifndef _WIN32
24 const char *ext = ".so";
25#else /* _WIN32 */
26 const char *ext = ".dll";
27#endif /* _WIN32 */
28 char lib_with_ext[FUNCMAN_NAME_MAX];
29
30 /* ロード完了後は resolved が 0 以外になる。早期リターンで判定する。
31 * もし解決に失敗している場合は、NULL が返却される。 */
32 if (fobj->resolved != 0)
33 {
34 return fobj->func_ptr;
35 }
36
37 /* ロード処理を排他制御する。
38 * ロック取得後に再度 resolved を確認し、他スレッドが先にロードを
39 * 完了していた場合は処理をスキップする (double-checked locking)。 */
40#ifndef _WIN32
41 if (pthread_mutex_lock(&fobj->mutex) != 0)
42 {
43 return NULL;
44 }
45#else /* _WIN32 */
46 AcquireSRWLockExclusive(&fobj->lock);
47#endif /* _WIN32 */
48
49 if (fobj->resolved == 0)
50 {
51 if (strcmp(fobj->lib_name, "default") == 0 && strcmp(fobj->func_name, "default") == 0)
52 {
53 fobj->resolved = 2; /* resolved=2: 明示的デフォルト */
54 goto unlock;
55 }
56 if (fobj->lib_name[0] == '\0' || fobj->func_name[0] == '\0')
57 {
58 fobj->resolved = -1; /* resolved=-1: 定義なし (定義ファイル不存在、定義行が不存在) */
59 goto unlock;
60 }
61 if (strlen(fobj->lib_name) + strlen(ext) >= FUNCMAN_NAME_MAX)
62 {
63 fobj->resolved = -2; /* resolved=-2: 名称長さオーバー */
64 goto unlock;
65 }
66#ifndef _WIN32
67 strcpy(lib_with_ext, fobj->lib_name);
68 strcat(lib_with_ext, ext);
69#else /* _WIN32 */
70 strcpy_s(lib_with_ext, sizeof(lib_with_ext), fobj->lib_name);
71 strcat_s(lib_with_ext, sizeof(lib_with_ext), ext);
72#endif /* _WIN32 */
73
74#ifndef _WIN32
75 fobj->handle = dlopen(lib_with_ext, RTLD_LAZY);
76#else /* _WIN32 */
77 fobj->handle = LoadLibrary(lib_with_ext);
78#endif /* _WIN32 */
79 if (fobj->handle == NULL)
80 {
81 fobj->resolved = -3; /* resolved=-3: ライブラリオープンエラー */
82 goto unlock;
83 }
84
85#ifndef _WIN32
86 fobj->func_ptr = dlsym(fobj->handle, fobj->func_name);
87#else /* _WIN32 */
88 fobj->func_ptr = (void *)GetProcAddress(fobj->handle, fobj->func_name);
89#endif /* _WIN32 */
90 if (fobj->func_ptr == NULL)
91 {
92 fobj->resolved = -4; /* resolved=-4: 関数探索エラー */
93#ifndef _WIN32
94 dlclose(fobj->handle);
95#else /* _WIN32 */
96 FreeLibrary(fobj->handle);
97#endif /* _WIN32 */
98 fobj->handle = NULL;
99 }
100 fobj->resolved = 1; /* resolved=1: 解決済 */
101 }
102
103unlock:
104#ifndef _WIN32
105 pthread_mutex_unlock(&fobj->mutex);
106#else /* _WIN32 */
107 ReleaseSRWLockExclusive(&fobj->lock);
108#endif /* _WIN32 */
109
110 return fobj->func_ptr;
111}
funcman.h
関数動的呼び出し機構 (funcman) の公開 API ヘッダー。
FUNCMAN_NAME_MAX
#define FUNCMAN_NAME_MAX
lib_name / func_name 配列の最大長 (終端 '\0' を含む)。
Definition funcman.h:56
_funcman_get_func
void * _funcman_get_func(funcman_object *fobj)
拡張関数ポインタを返します。この関数は内部用です。
Definition funcman_get_func.c:21
funcman_object
関数ポインタキャッシュエントリ。
Definition funcman.h:67
funcman_object::handle
MODULE_HANDLE handle
キャッシュ済みハンドル (NULL = 未ロード)。
Definition funcman.h:71
funcman_object::func_name
char func_name[FUNCMAN_NAME_MAX]
関数シンボル名。[0]=='\0' = 未設定。
Definition funcman.h:70
funcman_object::resolved
int resolved
解決済フラグ (0 = 未解決)。
Definition funcman.h:73
funcman_object::func_ptr
void * func_ptr
キャッシュ済み関数ポインタ (NULL = 未取得)。
Definition funcman.h:72
funcman_object::lib_name
char lib_name[FUNCMAN_NAME_MAX]
拡張子なしライブラリ名。[0]=='\0' = 未設定。
Definition funcman.h:69
funcman_object::mutex
pthread_mutex_t mutex
ロード処理を保護する mutex (Linux)。
Definition funcman.h:76