OSDN Git Service

タグを打ち忘れていたついでに、html版ドキュメントを追加しました。
[ring-lang-081/ring.git] / docs / build / html / _sources / extension.txt
1 .. index:: 
2         single: 拡張機能; はじめに
3
4 ==============================
5 C/C++ による拡張機能の開発方法
6 ==============================
7
8 .. note:: 現在、本章の説明だけでは拡張機能の開発は困難です。
9                 Ring のソースコード (include, src, visualsrc, stdlib フォルダ)、および拡張機能のソースコード (android, extensions, libdepwin フォルダ) のコードリーディングを強く推奨します。
10                 
11
12 プログラミング言語 C / C++ で記述した関数を新たに追加することにより Ring 仮想計算機 (Ring VM) の機能を拡張できます。 Ring VM には C により記述された様々な関数が付属しており Ring の関数として呼び出せます。
13
14 新しい関数を記述してから Ring VM のリビルドすることで Ring 言語の機能を拡張できます。
15 また、共有ライブラリ (.dll / .so) ファイルを作成することで Ring VM をリビルドせずに機能の拡張ができます。
16
17 Ring のソースコードには Ring VM へ新しいモジュールを追加するための二本のファイルが付属しています。
18
19 .. index:: 
20         pair: 拡張機能; ring_ext.h
21
22 ring_ext.h
23 ==========
24
25 ファイル ring_ext.h にはビルド処理の間にモジュールの包含、または除外を変更できる定数があります。
26
27 .. code-block:: C
28
29         #ifndef ringext_h
30         #define ringext_h
31         /* 定数 */
32         #define RING_VM_LISTFUNCS       1
33         #define RING_VM_REFMETA         1
34         #define RING_VM_MATH            1
35         #define RING_VM_FILE            1
36         #define RING_VM_OS              1
37         #define RING_VM_MYSQL           1
38         #define RING_VM_ODBC            1
39         #define RING_VM_OPENSSL         1
40         #define RING_VM_CURL            1
41         #define RING_VM_DLL             1
42         #endif
43
44
45 .. index:: 
46         pair: 拡張機能; ring_ext.c
47
48 ring_ext.c
49 ==========
50
51 モジュールのスタートアップ関数を呼び出す前に、ファイル ring_ext.c は ring_ext.h で定義されている定数を確認します。
52
53 モジュールは Ring VM へモジュール関数を登録する関数があります。
54
55 .. code-block:: C
56
57         #include "ring.h"
58
59         void ring_vm_extension ( RingState *pRingState )
60         {
61                 /* リフレクションとメタプログラミング */
62                 #if RING_VM_REFMETA
63                         ring_vm_refmeta_loadfunctions(pRingState);
64                 #endif
65                 /* リスト関数 */
66                 #if RING_VM_LISTFUNCS
67                         ring_vm_listfuncs_loadfunctions(pRingState);
68                 #endif
69                 /* 算術 */
70                 #if RING_VM_MATH
71                         ring_vm_math_loadfunctions(pRingState);
72                 #endif
73                 /* ファイル */
74                 #if RING_VM_FILE
75                         ring_vm_file_loadfunctions(pRingState);
76                 #endif
77                 /* OS */
78                 #if RING_VM_OS
79                         ring_vm_os_loadfunctions(pRingState);
80                 #endif
81                 /* MySQL */
82                 #if RING_VM_MYSQL
83                         ring_vm_mysql_loadfunctions(pRingState);
84                 #endif
85                 /* ODBC */
86                 #if RING_VM_ODBC
87                         ring_vm_odbc_loadfunctions(pRingState);
88                 #endif
89                 /* OPENSSL */
90                 #if RING_VM_OPENSSL
91                         ring_vm_openssl_loadfunctions(pRingState);
92                 #endif
93                 /* CURL */
94                 #if RING_VM_CURL
95                         ring_vm_curl_loadfunctions(pRingState);
96                 #endif
97                 /* DLL */
98                 #if RING_VM_DLL
99                         ring_vm_dll_loadfunctions(pRingState);
100                 #endif
101         }
102
103 .. index:: 
104         pair: 拡張機能; モジュールの組織化
105
106 モジュールの組織化
107 ===================
108
109 モジュールごとに Ring ヘッダファイル (ring.h) をインクルードすることから始まります。
110 このファイルには Ring VM の拡張機能で用いる Ring API があります。
111
112 モジュールには Ring VM へモジュール関数を登録するための関数が付属しています。
113 ring_vm_funcregister() 関数で登録を完了します。
114
115 ring_vm_funcregister() 関数は二つの仮関数を扱います。
116 一番目の仮引数は Ring プログラムが関数を呼び出すために使用される関数名です。
117 二番目の仮引数は C プログラム側の関数ポインタです。
118
119 この用例では、モジュール関数の登録用コードが ring_vmmath.c モジュールにあります。
120
121 .. code-block:: C
122
123         #include "ring.h"
124
125         void ring_vm_math_loadfunctions ( RingState *pRingState )
126         {
127                 ring_vm_funcregister("sin",ring_vm_math_sin);
128                 ring_vm_funcregister("cos",ring_vm_math_cos);
129                 ring_vm_funcregister("tan",ring_vm_math_tan);
130                 ring_vm_funcregister("asin",ring_vm_math_asin);
131                 ring_vm_funcregister("acos",ring_vm_math_acos);
132                 ring_vm_funcregister("atan",ring_vm_math_atan);
133                 ring_vm_funcregister("atan2",ring_vm_math_atan2);
134                 ring_vm_funcregister("sinh",ring_vm_math_sinh);
135                 ring_vm_funcregister("cosh",ring_vm_math_cosh);
136                 ring_vm_funcregister("tanh",ring_vm_math_tanh);
137                 ring_vm_funcregister("exp",ring_vm_math_exp);
138                 ring_vm_funcregister("log",ring_vm_math_log);
139                 ring_vm_funcregister("log10",ring_vm_math_log10);
140                 ring_vm_funcregister("ceil",ring_vm_math_ceil);
141                 ring_vm_funcregister("floor",ring_vm_math_floor);
142                 ring_vm_funcregister("fabs",ring_vm_math_fabs);
143                 ring_vm_funcregister("pow",ring_vm_math_pow);
144                 ring_vm_funcregister("sqrt",ring_vm_math_sqrt);
145                 ring_vm_funcregister("unsigned",ring_vm_math_unsigned);
146                 ring_vm_funcregister("decimals",ring_vm_math_decimals);
147                 ring_vm_funcregister("murmur3hash",ring_vm_math_murmur3hash);
148         }
149
150 .. tip:: ring_vm_math_loadfunctions() 関数は ring_vm_extension() 関数により、
151                  呼び出されることを覚えておいてください (ring_ext.c ファイルで)。
152
153 .. index:: 
154         pair: 拡張機能; 関数の構造
155
156 関数の構造
157 ==========
158
159 このような手順がモジュール関数ごとにあります。
160
161 1 - 仮引数の個数を検査
162
163 2 - 仮引数の型を検査
164
165 3 - 仮引数の値を取得
166
167 4 - コードの実行 / 関数の呼び出し
168
169 5 - 返値を返す
170
171 この構造は関数と非常に似ています (入力~処理~出力)。 
172 ここでは Ring API の 1, 2, 3, および 5 の手順を使用しています。
173
174
175 .. index:: 
176         pair: 拡張機能; 仮引数の個数を検査するには
177
178 仮引数の個数を検査するには
179 ===========================
180
181 RING_API_PARACOUNT マクロで仮引数の個数を検査します。
182
183 RING_API_PARACOUNT は == または != 演算子により数値で比較します。
184
185
186 用例:
187
188 .. code-block:: C
189
190         if ( RING_API_PARACOUNT != 1 ) {
191                 /* コード */
192         }
193
194         
195 用例:
196
197 .. code-block:: C
198
199         if ( RING_API_PARACOUNT == 1 ) {
200                 /* コード */
201         }
202
203 .. index:: 
204         pair: 拡張機能; エラーメッセージの表示
205
206 エラーメッセージの表示
207 =======================
208
209 RING_API_ERROR() 関数はエラーメッセージを表示します。
210
211 この関数はエラー、およびプログラム実行時に表示します。
212
213 .. note:: この関数の動作は Ring コードで Try/Catch/Done ステートメントにより変更できますので 
214                   C コードでは、この関数の後に retrun を記述してください。
215                   
216
217 文法:
218
219 .. code-block:: C
220
221         RING_API_ERROR(const char *cErrorMsg);
222         
223
224 Ring API には定義済みのエラーメッセージがあり、このように使うことができます。
225
226 .. code-block:: C
227
228         #define RING_API_MISS1PARA "Bad parameters count, the function expect one parameter"
229         #define RING_API_MISS2PARA "Bad parameters count, the function expect two parameters"
230         #define RING_API_MISS3PARA "Bad parameters count, the function expect three parameters"
231         #define RING_API_MISS4PARA "Bad parameters count, the function expect four parameters"
232         #define RING_API_BADPARATYPE    "Bad parameter type!"
233         #define RING_API_BADPARACOUNT   "Bad parameters count!"
234         #define RING_API_BADPARARANGE   "Bad parameters value, error in range!"
235         #define RING_API_NOTPOINTER     "Error in parameter, not pointer!"
236         #define RING_API_NULLPOINTER    "Error in parameter, NULL pointer!"
237         #define RING_API_EMPTYLIST      "Bad parameter, empty list!"
238
239 .. index:: 
240         pair: 拡張機能; 仮引数の型を検査するには
241
242 仮引数の型を検査するには
243 =========================
244
245 この関数は仮引数の型を検査します。
246
247 .. code-block:: C
248
249         int RING_API_ISNUMBER(int nParameterNumber);
250         int RING_API_ISSTRING(int nParameterNumber);
251         int RING_API_ISLIST(int nParameterNumber);
252         int RING_API_ISPOINTER(int nParameterNumber);
253
254 これらの関数の実行結果は 1 (True) または 0 (False) です。
255
256 .. index:: 
257         pair: 拡張機能; 仮引数の値を取得するには
258
259 仮引数の値を取得するには
260 =========================
261
262 この関数は仮引数の値を取得します。
263
264 .. code-block:: C
265
266         double RING_API_GETNUMBER(int nParameterNumber);
267         const char *RING_API_GETSTRING(int nParameterNumber);
268         int RING_API_GETSTRINGSIZE(int nParameterNumber);
269         List *RING_API_GETLIST(int nParameterNumber);
270         void *RING_API_GETCPOINTER(int nParameterNumber, const char *cPoinerType);
271         int RING_API_GETPOINTERTYPE(int nParameterNumber);
272
273         
274 .. index:: 
275         pair: 拡張機能; 返値
276
277 返値
278 ====
279
280 この関数は関数の返値を取得します。
281
282 .. code-block:: C
283
284         RING_API_RETNUMBER(double nValue);
285         RING_API_RETSTRING(const char *cString);
286         RING_API_RETSTRING2(const char *cString,int nStringSize);
287         RING_API_RETLIST(List *pList);
288         RING_API_RETCPOINTER(void *pValue,const char *cPointerType);
289         RING_API_RETMANAGEDCPOINTER(void *pValue,const char *cPointerType,
290                                         void (* pFreeFunc)(void *,void *))
291
292 .. index:: 
293         pair: 拡張機能; 関数プロトタイプ
294
295
296 関数プロトタイプ
297 ================
298
299 Ring VM の拡張機能用の新しい関数を定義するには、このプロトタイプを使用します。
300
301 .. code-block:: C
302
303         void my_function_name( void *pPointer );
304         
305 または RING_FUNC() マクロを使えます。
306
307 .. code-block:: C
308
309         RING_FUNC(my_function_name);
310
311         
312 .. index:: 
313         pair: 拡張機能; Sin() 関数の実装
314
315 Sin() 関数の実装
316 ================
317
318 このコードは Ring API と C 関数 sin() による
319 Sin() 関数の実装です。 
320
321
322 .. code-block:: C
323
324         void ring_vm_math_sin ( void *pPointer )
325         {
326                 if ( RING_API_PARACOUNT != 1 ) {
327                         RING_API_ERROR(RING_API_MISS1PARA);
328                         return ;
329                 }
330                 if ( RING_API_ISNUMBER(1) ) {
331                         RING_API_RETNUMBER(sin(RING_API_GETNUMBER(1)));
332                 } else {
333                         RING_API_ERROR(RING_API_BADPARATYPE);
334                 }
335         }
336
337
338 .. index:: 
339         pair: 拡張機能; Fopen() および Fclose() の実装
340
341 Fopen() および Fclose() の実装
342 ==============================
343
344 このコードは Ring API と C 関数 fopen() による
345 fopen() 関数の実装です。
346
347 この関数は二つの仮引数を扱います。第一仮引数はファイル名を文字列で指定します。
348 第二仮引数はモードを文字列で指定します。
349
350 ファイル ring_vmfile.h はポインタ型などの定数として使用するものがあります。
351
352 .. code-block:: C
353
354         #define RING_VM_POINTER_FILE    "file"
355         #define RING_VM_POINTER_FILEPOS "filepos"
356
357 ring_vmfile.c における関数の実装です。
358
359 .. code-block:: C
360
361         void ring_vm_file_fopen ( void *pPointer )
362         {
363                 FILE *fp  ;
364                 if ( RING_API_PARACOUNT != 2 ) {
365                         RING_API_ERROR(RING_API_MISS2PARA);
366                         return ;
367                 }
368                 if ( RING_API_ISSTRING(1) && RING_API_ISSTRING(2) ) {
369                         fp = fopen(RING_API_GETSTRING(1),RING_API_GETSTRING(2));
370                         RING_API_RETCPOINTER(fp,RING_VM_POINTER_FILE);
371                 } else {
372                         RING_API_ERROR(RING_API_BADPARATYPE);
373                 }
374         }
375
376
377 このコードは fclose() 関数の実装です。
378
379 .. code-block:: C
380
381         void ring_vm_file_fclose ( void *pPointer )
382         {
383                 FILE *fp  ;
384                 if ( RING_API_PARACOUNT != 1 ) {
385                         RING_API_ERROR(RING_API_MISS1PARA);
386                         return ;
387                 }
388                 if ( RING_API_ISPOINTER(1) ) {
389                         fp = (FILE *) RING_API_GETCPOINTER(1,RING_VM_POINTER_FILE) ;
390                         if ( fp != NULL ) {
391                                 RING_API_RETNUMBER(fclose(fp));
392                                 RING_API_SETNULLPOINTER(1);
393                         }
394                 } else {
395                         RING_API_ERROR(RING_API_BADPARATYPE);
396                 }
397         }
398
399 fopen() および fclose() から次の実装について学びました
400
401 1 - RING_API_RETCPOINTER() 関数で C ポインタを返す方法
402
403 2 - RING_API_ISPOINTER() 関数で仮引数がポインタの場合における検査方法
404
405 3 - RING_API_GETCPOINTER() 関数で C ポインタ値の取得方法
406
407 4 - RING_API_SETNULLPOINTER() 関数で C ポインタ変数 (Ring VM では) に NULL を設定する方法。
408
409 .. index:: 
410         pair: 拡張機能; RING API - リスト関数
411
412 Ring API - リスト関数
413 =====================
414
415 リストの新規作成とリスト項目操作用の Ring API リスト関数を学びます。
416
417 .. code-block:: C
418
419         List * ring_list_new ( int nSize ) ;
420         void ring_list_newitem ( List *pList ) ;
421         Item * ring_list_getitem ( List *pList,int index ) ;
422         List * ring_list_delete ( List *pList ) ;
423         void ring_list_deleteitem ( List *pList,int index ) ;
424         void ring_list_print ( List *pList ) ;
425         int ring_list_gettype ( List *pList, int index ) ;
426         void ring_list_setint ( List *pList, int index ,int number ) ;
427         void ring_list_addint ( List *pList,int x ) ;
428         void ring_list_setpointer ( List *pList, int index ,void *pValue ) ;
429         void ring_list_addpointer ( List *pList,void *pValue ) ;
430         void ring_list_setfuncpointer ( List *pList, int index ,void (*pFunc)(void *) ) ;
431         void ring_list_addfuncpointer ( List *pList,void (*pFunc)(void *) ) ;
432         int ring_list_isfuncpointer ( List *pList, int index ) ;
433         void ring_list_setdouble ( List *pList, int index ,double number ) ;
434         void ring_list_adddouble ( List *pList,double x ) ;
435         void ring_list_setstring ( List *pList, int index ,const char *str ) ;
436         void ring_list_setstring2 ( List *pList, int index ,const char *str,int nStrSize ) ;
437         void ring_list_addstring ( List *pList,const char *str ) ;
438         void ring_list_addstring2 ( List *pList,const char *str,int nStrSize ) ;
439         List * ring_list_newlist ( List *pList ) ;
440         List * ring_list_getlist ( List *pList, int index ) ;
441         void ring_list_setlist ( List *pList, int index ) ;
442         void ring_list_setactiveitem ( List *pList, Items *pItems, int index ) ;
443         void ring_list_copy ( List *pNewList, List *pList ) ;
444         int ring_list_isnumber ( List *pList, int index ) ;
445         int ring_list_isstring ( List *pList, int index ) ;
446         int ring_list_islist ( List *pList, int index ) ;
447         int ring_list_ispointer ( List *pList, int index ) ;
448         void ring_list_deleteallitems ( List *pList ) ;
449         void ring_list_insertitem ( List *pList,int x ) ;
450         void ring_list_insertint ( List *pList,int nPos,int x ) ;
451         void ring_list_insertdouble ( List *pList,int nPos,double x ) ;
452         void ring_list_insertpointer ( List *pList,int nPos,void *pValue ) ;
453         void ring_list_insertstring ( List *pList,int nPos,const char *str ) ;
454         void ring_list_insertstring2 ( List *pList,int nPos,const char *str,int nStrSize ) ;
455         void ring_list_insertfuncpointer ( List *pList,int nPos,void (*pFunc)(void *) ) ;
456         List * ring_list_insertlist ( List *pList,int nPos ) ;
457         int ring_list_isiteminsidelist ( List *pList,Item *pItem ) ;
458         int ring_list_findstring ( List *pList,const char *str,int nColumn ) ;
459         int ring_list_finddouble ( List *pList,double nNum1,int nColumn ) ;
460         void ring_list_sortnum ( List *pList,int left,int right,int nColumn ) ;
461         void ring_list_sortstr ( List *pList,int left,int right,int nColumn ) ;
462         int ring_list_binarysearchnum ( List *pList,double nNum1,int nColumn ) ;
463         int ring_list_binarysearchstr ( List *pList,const char *cFind,int nColumn ) ;
464         void ring_list_swap ( List *pList,int x,int y ) ;
465         double ring_list_getdoublecolumn ( List *pList,int nIndex,int nColumn ) ;
466         char * ring_list_getstringcolumn ( List *pList,int nIndex,int nColumn ) ;
467         void ring_list_genarray ( List *pList ) ;
468         void ring_list_deletearray ( List *pList ) ;
469         void ring_list_genhashtable ( List *pList ) ;
470         void ring_list_genhashtable2 ( List *pList ) ;
471         void ring_list_refcopy ( List *pNewList, List *pList ) ;
472         void ring_list_clear ( List *pList ) ;
473         /* マクロ */
474         ring_list_isdouble(pList,index)
475         ring_list_isint(pList,index) 
476         ring_list_deletelastitem(x)
477         ring_list_gethashtable(x) 
478         ring_list_getint(pList,index)
479         ring_list_getpointer(pList,index)
480         ring_list_getfuncpointer(pList,index)
481         ring_list_callfuncpointer(pList,index,x)
482         ring_list_getdouble(pList,index) 
483         ring_list_getstring(pList,index) 
484         ring_list_getstringobject(pList,index) 
485         ring_list_getstringsize(pList,index)
486         ring_list_getsize(x) (x->nSize)
487
488 .. index:: 
489         pair: 拡張機能; RING API - 文字列関数
490
491 Ring API - 文字列関数
492 =====================
493
494 文字列の新規作成と文字列内容操作用の Ring API 文字列関数を学びます。
495
496 .. code-block:: C
497
498         String * ring_string_new ( const char *str ) ;
499         String * ring_string_new2 ( const char *str,int nStrSize ) ;
500         String * ring_string_delete ( String *pString ) ;
501         int ring_string_size ( String *pString ) ;
502         void ring_string_set ( String *pString,const char *str ) ;
503         void ring_string_set2 ( String *pString,const char *str,int nStrSize ) ;
504         void ring_string_add ( String *pString,const char *str ) ;
505         void ring_string_add2 ( String *pString,const char *str,int nStrSize ) ;
506         void ring_string_print ( String *pString ) ;
507         void ring_string_setfromint ( String *pString,int x ) ;
508         char * ring_string_lower ( char *cStr ) ;
509         char * ring_string_upper ( char *cStr ) ;
510         char * ring_string_lower2 ( char *cStr,int nStrSize ) ;
511         char * ring_string_upper2 ( char *cStr,int nStrSize ) ;
512         char * ring_string_find ( char *cStr1,char *cStr2 ) ;
513         char * ring_string_find2 ( char *cStr1,int nStrSize1,char *cStr2,int nStrSize2 ) ;
514         /* マクロ */
515         ring_string_tolower(x)
516         ring_string_toupper(x)
517         ring_string_get(x)
518
519
520 .. index:: 
521         pair: 拡張機能; MySQL_Columns() 関数の実装
522
523 MySQL_Columns() 関数の実装
524 =======================================
525
526 このコードは MySQL_Columns() 関数の実装です。
527
528 この関数はカラム情報を返します。
529
530 .. code-block:: C
531
532         void ring_vm_mysql_columns ( void *pPointer )
533         {
534                 MYSQL *con  ;
535                 MYSQL_RES *result  ;
536                 int nColumns,x  ;
537                 MYSQL_ROW row  ;
538                 MYSQL_FIELD *field  ;
539                 List *pList, *pList2  ;
540                 if ( RING_API_PARACOUNT != 1 ) {
541                         RING_API_ERROR(RING_API_MISS1PARA);
542                         return ;
543                 }
544                 if ( RING_API_ISPOINTER(1) ) {
545                         con = (MYSQL *) RING_API_GETCPOINTER(1,RING_VM_POINTER_MYSQL) ;
546                         if ( con == NULL ) {
547                                 return ;
548                         }
549                         result = mysql_store_result(con);
550                         if ( result == NULL ) {
551                                 RING_API_RETNUMBER(0);
552                                 return ;
553                         }
554                         pList = RING_API_NEWLIST ;
555                         nColumns = mysql_num_fields(result);
556                         if ( row = mysql_fetch_row(result) ) {
557                                 while ( field = mysql_fetch_field(result) ) {
558                                         pList2 = ring_list_newlist(pList);
559                                         ring_list_addstring(pList2,field->name);
560                                         ring_list_adddouble(pList2,field->length);
561                                         ring_list_adddouble(pList2,field->type);
562                                         ring_list_adddouble(pList2,field->flags);
563                                 }
564                         }
565                         mysql_free_result(result);
566                         RING_API_RETLIST(pList);
567                 } else {
568                         RING_API_ERROR(RING_API_BADPARATYPE);
569                 }
570         }
571
572
573 List はリスト型であり、以前の関数でリスト型のポインタ
574 \*pList, \*pList2; の二つ使用して宣言されています。
575
576         
577 .. note:: この関数は RING_API_NEWLIST で新しいリストを作成するために使用しますが
578                   ring_list_new() の代わりに一時作業用のリストを作成します。関数のスコープはメモリと関連付けられています。
579                   このように関数からリストを返せます。また Ring コードにより保存された格納済みの変数ならば、
580                   リストの削除を行いません。それ以外ならば Ring VM により自動削除されます。
581                   
582
583 リストは部分リストを有することができ、部分リストは ring_list_newlist() 関数で作成します。
584
585 ring_list_addstring() 関数は部分リストへ文字列の項目を追加します。
586
587 ring_list_adddouble() 関数は部分リストへ数値の項目を追加します。 
588
589 .. note:: Ring VM 拡張機能の関数から返されたリストにある数値の項目は倍精度実数型 (double) であるため 
590           ring_list_adddouble() 関数でリストへ追加してください。
591                   
592
593 RING_API_RETLIST() 関数は拡張機能の関数からリストを返します。
594
595 .. index:: 
596         pair: 拡張機能; 共有ライブラリ
597
598 動的 / 共有ライブラリ (DLL/So/Dylib) および LoadLib() 関数
599 ==============================================================
600
601 新しい関数を C/C++ と Ring API で記述後に Ring VM のリビルドをするのではなく、 DLL /So / Dylib
602 ファイルの作成を行い、このファイルを実行時に LoadLib() 関数へ指定することで動的に関数を使えます。
603
604
605 C による動的ライブラリの用例
606
607 .. code-block:: C
608
609         #include "ring.h"
610
611         RING_FUNC(ring_ringlib_dlfunc)
612         {
613                 printf("Message from dlfunc");
614         }
615
616         RING_API void ringlib_init(RingState *pRingState)
617         {
618                 ring_vm_funcregister("dlfunc",ring_ringlib_dlfunc); 
619         }
620
621 考えかたとしては ringlib_init() 関数を作成することであり、この関数は生成された DLL ファイルを
622 LoadLib() 関数で読み込んで使用する時に Ring VM から呼び出されます。
623
624 ringlib_init() 関数内でモジュール関数の登録、またはモジュール関数を全て登録処理するための関数を呼び出せます。
625
626 この Ring コードは実行時に DLL ライブラリの用法です。
627
628 .. code-block:: ring
629
630         See "Dynamic DLL" + NL
631         LoadLib("ringlib.dll")
632         dlfunc()
633
634 実行結果:
635
636 .. code-block:: ring
637
638         Dynamic DLL
639         Message from dlfunc
640
641 .. index:: 
642         pair: 拡張機能; Using RING_API_RETMANAGEDCPOINTER() の用法
643
644
645 RING_API_RETMANAGEDCPOINTER() の用法
646 ====================================
647
648 RING_API_RETMANAGEDCPOINTER() は C/C++ 言語で記述された Ring 拡張機能でマネージドポインタを Ring へ返します。このポインタは参照カウンタを使用している Ring VM により制御可能です。
649
650 これは RingQt の QPixMap オブジェクトなどのアンマネージドのリソース解放用コードを書く必要性を回避するには重要です。
651
652 また、コード生成器は必要に応じて拡張機能を RING_API_RETMANAGEDCPOINTER() に対応したものへ自動更新します。
653
654 文法:
655
656 .. code-block:: ring
657
658                 RING_API_RETMANAGEDCPOINTER(void *pValue,const char *cPointerType,
659                                                 void (* pFreeFunc)(void *,void *))
660
661 用例:
662
663 この用例は ring_qt.cpp の QPixMap クラスにある Scaled() メソッドからの引用です。
664
665 .. code-block:: none
666
667         RING_FUNC(ring_QPixmap_scaled)
668         {
669                 QPixmap *pObject ;
670                 if ( RING_API_PARACOUNT != 5 ) {
671                         RING_API_ERROR(RING_API_BADPARACOUNT);
672                         return ;
673                 }
674                 RING_API_IGNORECPOINTERTYPE ;
675                 if ( ! RING_API_ISPOINTER(1) ) {
676                         RING_API_ERROR(RING_API_BADPARATYPE);
677                         return ;
678                 }
679                 pObject = (QPixmap *) RING_API_GETCPOINTER(1,"QPixmap");
680                 if ( ! RING_API_ISNUMBER(2) ) {
681                         RING_API_ERROR(RING_API_BADPARATYPE);
682                         return ;
683                 }
684                 if ( ! RING_API_ISNUMBER(3) ) {
685                         RING_API_ERROR(RING_API_BADPARATYPE);
686                         return ;
687                 }
688                 if ( ! RING_API_ISNUMBER(4) ) {
689                         RING_API_ERROR(RING_API_BADPARATYPE);
690                         return ;
691                 }
692                 if ( ! RING_API_ISNUMBER(5) ) {
693                         RING_API_ERROR(RING_API_BADPARATYPE);
694                         return ;
695                 }
696                 {
697                         QPixmap *pValue ; 
698                         pValue = new QPixmap() ;
699                         *pValue = pObject->scaled( (int ) RING_API_GETNUMBER(2),
700                                  (int ) RING_API_GETNUMBER(3),
701                                  (Qt::AspectRatioMode )  (int) RING_API_GETNUMBER(4),
702                                  (Qt::TransformationMode )  (int) RING_API_GETNUMBER(5));
703                         RING_API_RETMANAGEDCPOINTER(pValue,"QPixmap",ring_QPixmap_freefunc);
704                 }
705         }
706
707 この関数は二種類の仮引数 (Ring のステートと確保されたメモリのポインタ) の指定によりメモリを解放します。
708
709 用例:
710
711 .. code-block:: none
712
713         void ring_QPixmap_freefunc(void *pState,void *pPointer)
714         {
715                 QPixmap *pObject ; 
716                 pObject = (QPixmap *) pPointer;
717                 delete pObject ;
718         }
719