1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
|
/*-------------------------------------------------------------------------
* C-Pluff, a plug-in framework for C
* Copyright 2007 Johannes Lehtinen
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*-----------------------------------------------------------------------*/
/** @file
* C-Pluff C API header file.
* The elements declared here constitute the C-Pluff C API. To use the
* API include this file and link the main program and plug-in runtime
* libraries with the C-Pluff C library. In addition to local declarations,
* this file also includes cpluffdef.h header file for defines common to C
* and C++ API.
*/
#ifndef CPLUFF_H_
#define CPLUFF_H_
/**
* @defgroup cDefines Defines
* Preprocessor defines.
*/
#ifdef _WIN32
#include "win32/cpluffdef.h"
#else
#include "cpluffdef.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif /*__cplusplus*/
/* ------------------------------------------------------------------------
* Defines
* ----------------------------------------------------------------------*/
/**
* @def CP_C_API
* @ingroup cDefines
*
* Marks a symbol declaration to be part of the C-Pluff C API.
* This macro declares the symbol to be imported from the C-Pluff library.
*/
#ifndef CP_C_API
#define CP_C_API CP_IMPORT
#endif
/**
* @defgroup cScanFlags Flags for plug-in scanning
* @ingroup cDefines
*
* These constants can be orred together for the flags
* parameter of ::cp_scan_plugins.
*/
/*@{*/
/**
* This flag enables upgrades of installed plug-ins by unloading
* the old version and installing the new version.
*/
#define CP_SP_UPGRADE 0x01
/**
* This flag causes all plug-ins to be stopped before any
* plug-ins are to be upgraded.
*/
#define CP_SP_STOP_ALL_ON_UPGRADE 0x02
/**
* This flag causes all plug-ins to be stopped before any
* plugins are to be installed (also if new version is to be installed
* as part of an upgrade).
*/
#define CP_SP_STOP_ALL_ON_INSTALL 0x04
/**
* Setting this flag causes the currently active plug-ins to be restarted
* after all changes to the plug-ins have been made (if they were stopped).
*/
#define CP_SP_RESTART_ACTIVE 0x08
/*@}*/
/* ------------------------------------------------------------------------
* Data types
* ----------------------------------------------------------------------*/
/**
* @defgroup cEnums Enumerations
* Constant value enumerations.
*/
/**
* @defgroup cTypedefs Typedefs
* Typedefs of various kind.
*/
/**
* @defgroup cStructs Data structures
* Data structure definitions.
*/
/* Enumerations */
/**
* @ingroup cEnums
*
* An enumeration of status codes returned by API functions.
* Most of the interface functions return a status code. The returned
* status code either indicates successful completion of the operation
* or some specific kind of error. Some functions do not return a status
* code because they never fail.
*/
enum cp_status_t {
/**
* Operation was performed successfully (equals to zero).
* @showinitializer
*/
CP_OK = 0,
/** Not enough memory or other operating system resources available */
CP_ERR_RESOURCE,
/** The specified object is unknown to the framework */
CP_ERR_UNKNOWN,
/** An I/O error occurred */
CP_ERR_IO,
/** Malformed plug-in descriptor was encountered when loading a plug-in */
CP_ERR_MALFORMED,
/** Plug-in or symbol conflicts with another plug-in or symbol. */
CP_ERR_CONFLICT,
/** Plug-in dependencies could not be satisfied. */
CP_ERR_DEPENDENCY,
/** Plug-in runtime signaled an error. */
CP_ERR_RUNTIME
};
/**
* @ingroup cEnums
* An enumeration of possible plug-in states. Plug-in states are controlled
* by @ref cFuncsPlugin "plug-in management functions". Plug-in states can be
* observed by @ref cp_register_plistener "registering" a
* @ref cp_plugin_listener_func_t "plug-in listener function"
* or by calling ::cp_get_plugin_state.
*
* @sa cp_plugin_listener_t
* @sa cp_get_plugin_state
*/
enum cp_plugin_state_t {
/**
* Plug-in is not installed. No plug-in information has been
* loaded.
*/
CP_PLUGIN_UNINSTALLED,
/**
* Plug-in is installed. At this stage the plug-in information has
* been loaded but its dependencies to other plug-ins has not yet
* been resolved. The plug-in runtime has not been loaded yet.
* The extension points and extensions provided by the plug-in
* have been registered.
*/
CP_PLUGIN_INSTALLED,
/**
* Plug-in dependencies have been resolved. At this stage it has
* been verified that the dependencies of the plug-in are satisfied
* and the plug-in runtime has been loaded but it is not active
* (it has not been started or it has been stopped).
* Plug-in is resolved when a dependent plug-in is being
* resolved or before the plug-in is started. Plug-in is put
* back to installed stage if its dependencies are being
* uninstalled.
*/
CP_PLUGIN_RESOLVED,
/**
* Plug-in is starting. The plug-in has been resolved and the start
* function (if any) of the plug-in runtime is about to be called.
* A plug-in is started when explicitly requested by the main
* program or when a dependent plug-in is about to be started or when
* a dynamic symbol defined by the plug-in is being resolved. This state
* is omitted and the state changes directly from resolved to active
* if the plug-in runtime does not define a start function.
*/
CP_PLUGIN_STARTING,
/**
* Plug-in is stopping. The stop function (if any) of the plug-in
* runtime is about to be called. A plug-in is stopped if the start
* function fails or when stopping is explicitly
* requested by the main program or when its dependencies are being
* stopped. This state is omitted and the state changes directly from
* active to resolved if the plug-in runtime does not define a stop
* function.
*/
CP_PLUGIN_STOPPING,
/**
* Plug-in has been successfully started and it has not yet been
* stopped.
*/
CP_PLUGIN_ACTIVE
};
/**
* @ingroup cEnums
* An enumeration of possible message severities for framework logging. These
* constants are used when passing a log message to a
* @ref cp_logger_func_t "logger function" and when
* @ref cp_register_logger "registering" a logger function.
*/
enum cp_log_severity_t {
/** Used for detailed debug messages */
CP_LOG_DEBUG,
/** Used for informational messages such as plug-in state changes */
CP_LOG_INFO,
/** Used for messages warning about possible problems */
CP_LOG_WARNING,
/** Used for messages reporting errors */
CP_LOG_ERROR
};
/*@}*/
/* Typedefs */
/**
* @defgroup cTypedefsOpaque Opaque types
* @ingroup cTypedefs
* Opaque data type definitions.
*/
/*@{*/
/**
* A plug-in context represents the co-operation environment of a set of
* plug-ins from the perspective of a particular participating plug-in or
* the perspective of the main program. It is used as an opaque handle to
* the shared resources but the framework also uses the context to identify
* the plug-in or the main program invoking framework functions. Therefore
* a plug-in should not generally expose its context instance to other
* plug-ins or the main program and neither should the main program
* expose its context instance to plug-ins. The main program creates
* plug-in contexts using ::cp_create_context and plug-ins receive their
* plug-in contexts via @ref cp_plugin_runtime_t::create.
*/
typedef struct cp_context_t cp_context_t;
/*@}*/
/**
* @defgroup cTypedefsShorthand Shorthand type names
* @ingroup cTypedefs
* Shorthand type names for structs and enumerations.
*/
/*@{*/
/** A type for cp_plugin_info_t structure. */
typedef struct cp_plugin_info_t cp_plugin_info_t;
/** A type for cp_plugin_import_t structure. */
typedef struct cp_plugin_import_t cp_plugin_import_t;
/** A type for cp_ext_point_t structure. */
typedef struct cp_ext_point_t cp_ext_point_t;
/** A type for cp_extension_t structure. */
typedef struct cp_extension_t cp_extension_t;
/** A type for cp_cfg_element_t structure. */
typedef struct cp_cfg_element_t cp_cfg_element_t;
/** A type for cp_plugin_runtime_t structure. */
typedef struct cp_plugin_runtime_t cp_plugin_runtime_t;
/** A type for cp_status_t enumeration. */
typedef enum cp_status_t cp_status_t;
/** A type for cp_plugin_state_t enumeration. */
typedef enum cp_plugin_state_t cp_plugin_state_t;
/** A type for cp_log_severity_t enumeration. */
typedef enum cp_log_severity_t cp_log_severity_t;
/*@}*/
/**
* @defgroup cTypedefsFuncs Callback function types
* @ingroup cTypedefs
* Typedefs for client supplied callback functions.
*/
/*@{*/
/**
* A listener function called synchronously after a plugin state change.
* The function should return promptly.
* @ref cFuncsInit "Library initialization",
* @ref cFuncsContext "plug-in context management",
* @ref cFuncsPlugin "plug-in management",
* listener registration (::cp_register_plistener and ::cp_unregister_plistener)
* and @ref cFuncsSymbols "dynamic symbol" functions must not be called from
* within a plug-in listener invocation. Listener functions are registered
* using ::cp_register_plistener.
*
* @param plugin_id the plug-in identifier
* @param old_state the old plug-in state
* @param new_state the new plug-in state
* @param user_data the user data pointer supplied at listener registration
*/
typedef void (*cp_plugin_listener_func_t)(const char *plugin_id, cp_plugin_state_t old_state, cp_plugin_state_t new_state, void *user_data);
/**
* A logger function called to log selected plug-in framework messages. The
* messages may be localized. Plug-in framework API functions must not
* be called from within a logger function invocation. In a multi-threaded
* environment logger function invocations are serialized by the framework.
* Logger functions are registered using ::cp_register_logger.
*
* @param severity the severity of the message
* @param msg the message to be logged, possibly localized
* @param apid the identifier of the activating plug-in or NULL for the main program
* @param user_data the user data pointer given when the logger was registered
*/
typedef void (*cp_logger_func_t)(cp_log_severity_t severity, const char *msg, const char *apid, void *user_data);
/**
* A fatal error handler for handling unrecoverable errors. If the error
* handler returns then the framework aborts the program. Plug-in framework
* API functions must not be called from within a fatal error handler
* invocation. The fatal error handler function is set using
* ::cp_set_fatal_error_handler.
*
* @param msg the possibly localized error message
*/
typedef void (*cp_fatal_error_func_t)(const char *msg);
/**
* A run function registered by a plug-in to perform work.
* The run function should perform a finite chunk of work and it should
* return a non-zero value if there is more work to be done. Run functions
* are registered using ::cp_run_function and the usage is discussed in
* more detail in the @ref cFuncsPluginExec "serial execution" section.
*
* @param plugin_data the plug-in instance data pointer
* @return non-zero if there is more work to be done or zero if finished
*/
typedef int (*cp_run_func_t)(void *plugin_data);
/*@}*/
/* Data structures */
/**
* @ingroup cStructs
* Plug-in information structure captures information about a plug-in. This
* information can be loaded from a plug-in descriptor using
* ::cp_load_plugin_descriptor. Information about installed plug-ins can
* be obtained using ::cp_get_plugin_info and ::cp_get_plugins_info. This
* structure corresponds to the @a plugin element in a plug-in descriptor.
*/
struct cp_plugin_info_t {
/**
* The obligatory unique identifier of the plugin. A recommended way
* to generate identifiers is to use domain name service (DNS) prefixes
* (for example, org.cpluff.ExamplePlugin) to avoid naming conflicts. This
* corresponds to the @a id attribute of the @a plugin element in a plug-in
* descriptor.
*/
char *identifier;
/**
* An optional plug-in name. NULL if not available. The plug-in name is
* intended only for display purposes and the value can be localized.
* This corresponds to the @a name attribute of the @a plugin element in
* a plug-in descriptor.
*/
char *name;
/**
* An optional release version string. NULL if not available. This
* corresponds to the @a version attribute of the @a plugin element in
* a plug-in descriptor.
*/
char *version;
/**
* An optional provider name. NULL if not available. This is the name of
* the author or the organization providing the plug-in. The
* provider name is intended only for display purposes and the value can
* be localized. This corresponds to the @a provider-name attribute of the
* @a plugin element in a plug-in descriptor.
*/
char *provider_name;
/**
* Path of the plugin directory or NULL if not known. This is the
* (absolute or relative) path to the plug-in directory containing
* plug-in data and the plug-in runtime library. The value corresponds
* to the path specified to ::cp_load_plugin_descriptor when loading
* the plug-in.
*/
char *plugin_path;
/**
* Optional ABI compatibility information. NULL if not available.
* This is the earliest version of the plug-in interface the current
* interface is backwards compatible with when it comes to the application
* binary interface (ABI) of the plug-in. That is, plug-in clients compiled against
* any plug-in interface version from @a abi_bw_compatibility to
* @ref version (inclusive) can use the current version of the plug-in
* binary. This describes binary or runtime compatibility.
* The value corresponds to the @a abi-compatibility
* attribute of the @a backwards-compatibility element in a plug-in descriptor.
*/
char *abi_bw_compatibility;
/**
* Optional API compatibility information. NULL if not available.
* This is the earliest version of the plug-in interface the current
* interface is backwards compatible with when it comes to the
* application programming interface (API) of the plug-in. That is,
* plug-in clients written for any plug-in interface version from
* @a api_bw_compatibility to @ref version (inclusive) can be compiled
* against the current version of the plug-in API. This describes
* source or build time compatibility. The value corresponds to the
* @a api-compatibility attribute of the @a backwards-compatibility
* element in a plug-in descriptor.
*/
char *api_bw_compatibility;
/**
* Optional C-Pluff version requirement. NULL if not available.
* This is the version of the C-Pluff implementation the plug-in was
* compiled against. It is used to determine the compatibility of
* the plug-in runtime and the linked in C-Pluff implementation. Any
* C-Pluff version that is backwards compatible on binary level with the
* specified version fulfills the requirement.
*/
char *req_cpluff_version;
/** Number of import entries in the @ref imports array. */
unsigned int num_imports;
/**
* An array of @ref num_imports import entries. These correspond to
* @a import elements in a plug-in descriptor.
*/
cp_plugin_import_t *imports;
/**
* The base name of the plug-in runtime library, or NULL if none.
* A platform specific prefix (for example, "lib") and an extension
* (for example, ".dll" or ".so") may be added to the base name.
* This corresponds to the @a library attribute of the
* @a runtime element in a plug-in descriptor.
*/
char *runtime_lib_name;
/**
* The symbol pointing to the plug-in runtime function information or
* NULL if none. The symbol with this name should point to an instance of
* @ref cp_plugin_runtime_t structure. This corresponds to the
* @a funcs attribute of the @a runtime element in a plug-in descriptor.
*/
char *runtime_funcs_symbol;
/** Number of extension points in @ref ext_points array. */
unsigned int num_ext_points;
/**
* An array of @ref num_ext_points extension points provided by this
* plug-in. These correspond to @a extension-point elements in a
* plug-in descriptor.
*/
cp_ext_point_t *ext_points;
/** Number of extensions in @ref extensions array. */
unsigned int num_extensions;
/**
* An array of @ref num_extensions extensions provided by this
* plug-in. These correspond to @a extension elements in a plug-in
* descriptor.
*/
cp_extension_t *extensions;
};
/**
* @ingroup cStructs
* Information about plug-in import. Plug-in import structures are
* contained in @ref cp_plugin_info_t::imports.
*/
struct cp_plugin_import_t {
/**
* The identifier of the imported plug-in. This corresponds to the
* @a plugin attribute of the @a import element in a plug-in descriptor.
*/
char *plugin_id;
/**
* An optional version requirement. NULL if no version requirement.
* This is the version of the imported plug-in the importing plug-in was
* compiled against. Any version of the imported plug-in that is
* backwards compatible with this version fulfills the requirement.
* This corresponds to the @a if-version attribute of the @a import
* element in a plug-in descriptor.
*/
char *version;
/**
* Is this import optional. 1 for optional and 0 for mandatory import.
* An optional import causes the imported plug-in to be started if it is
* available but does not stop the importing plug-in from starting if the
* imported plug-in is not available. If the imported plug-in is available
* but the API version conflicts with the API version requirement then the
* importing plug-in fails to start. This corresponds to the @a optional
* attribute of the @a import element in a plug-in descriptor.
*/
int optional;
};
/**
* @ingroup cStructs
* Extension point structure captures information about an extension
* point. Extension point structures are contained in
* @ref cp_plugin_info_t::ext_points.
*/
struct cp_ext_point_t {
/**
* A pointer to plug-in information containing this extension point.
* This reverse pointer is provided to make it easy to get information
* about the plug-in which is hosting a particular extension point.
*/
cp_plugin_info_t *plugin;
/**
* The local identifier uniquely identifying the extension point within the
* host plug-in. This corresponds to the @name id attribute of an
* @a extension-point element in a plug-in descriptor.
*/
char *local_id;
/**
* The unique identifier of the extension point. This is automatically
* constructed by concatenating the identifier of the host plug-in and
* the local identifier of the extension point.
*/
char *identifier;
/**
* An optional extension point name. NULL if not available. The extension
* point name is intended for display purposes only and the value can be
* localized. This corresponds to the @a name attribute of
* an @a extension-point element in a plug-in descriptor.
*/
char *name;
/**
* An optional path to the extension schema definition.
* NULL if not available. The path is relative to the plug-in directory.
* This corresponds to the @a schema attribute
* of an @a extension-point element in a plug-in descriptor.
*/
char *schema_path;
};
/**
* @ingroup cStructs
* Extension structure captures information about an extension. Extension
* structures are contained in @ref cp_plugin_info_t::extensions.
*/
struct cp_extension_t {
/**
* A pointer to plug-in information containing this extension.
* This reverse pointer is provided to make it easy to get information
* about the plug-in which is hosting a particular extension.
*/
cp_plugin_info_t *plugin;
/**
* The unique identifier of the extension point this extension is
* attached to. This corresponds to the @a point attribute of an
* @a extension element in a plug-in descriptor.
*/
char *ext_point_id;
/**
* An optional local identifier uniquely identifying the extension within
* the host plug-in. NULL if not available. This corresponds to the
* @a id attribute of an @a extension element in a plug-in descriptor.
*/
char *local_id;
/**
* An optional unique identifier of the extension. NULL if not available.
* This is automatically constructed by concatenating the identifier
* of the host plug-in and the local identifier of the extension.
*/
char *identifier;
/**
* An optional extension name. NULL if not available. The extension name
* is intended for display purposes only and the value can be localized.
* This corresponds to the @a name attribute
* of an @a extension element in a plug-in descriptor.
**/
char *name;
/**
* Extension configuration starting with the extension element.
* This includes extension configuration information as a tree of
* configuration elements. These correspond to the @a extension
* element and its contents in a plug-in descriptor.
*/
cp_cfg_element_t *configuration;
};
/**
* @ingroup cStructs
* A configuration element contains configuration information for an
* extension. Utility functions ::cp_lookup_cfg_element and
* ::cp_lookup_cfg_value can be used for traversing the tree of
* configuration elements. Pointer to the root configuration element is
* stored at @ref cp_extension_t::configuration and others are contained as
* @ref cp_cfg_element_t::children "children" of parent elements.
*/
struct cp_cfg_element_t {
/**
* The name of the configuration element. This corresponds to the name of
* the element in a plug-in descriptor.
*/
char *name;
/** Number of attribute name, value pairs in the @ref atts array. */
unsigned int num_atts;
/**
* An array of pointers to alternating attribute names and values.
* Attribute values can be localized.
*/
char **atts;
/**
* An optional value of this configuration element. NULL if not available.
* The value can be localized. This corresponds to the
* text contents of the element in a plug-in descriptor.
*/
char *value;
/** A pointer to the parent element or NULL if this is a root element. */
cp_cfg_element_t *parent;
/** The index of this element among its siblings (0-based). */
unsigned int index;
/** Number of children in the @ref children array. */
unsigned int num_children;
/**
* An array of @ref num_children childrens of this element. These
* correspond to child elements in a plug-in descriptor.
*/
cp_cfg_element_t *children;
};
/**
* @ingroup cStructs
* Container for plug-in runtime information. A plug-in runtime defines a
* static instance of this structure to pass information to the plug-in
* framework. The plug-in framework then uses the information
* to create and control plug-in instances. The symbol pointing
* to the runtime information instance is named by the @a funcs
* attribute of the @a runtime element in a plug-in descriptor.
*
* The following graph displays how these functions are used to control the
* state of the plug-in instance.
*
* @dot
* digraph lifecycle {
* rankdir=LR;
* node [shape=ellipse, fontname=Helvetica, fontsize=10];
* edge [fontname=Helvetica, fontsize=10];
* none [label="no instance"];
* inactive [label="inactive"];
* active [label="active"];
* none -> inactive [label="create", URL="\ref create"];
* inactive -> active [label="start", URL="\ref start"];
* active -> inactive [label="stop", URL="\ref stop"];
* inactive -> none [label="destroy", URL="\ref destroy"];
* }
* @enddot
*/
struct cp_plugin_runtime_t {
/**
* An initialization function called to create a new plug-in
* runtime instance. The initialization function initializes and
* returns an opaque plug-in instance data pointer which is then
* passed on to other control functions. This data pointer should
* be used to access plug-in instance specific data. For example,
* the context reference must be stored as part of plug-in instance
* data if the plug-in runtime needs it. On failure, the function
* must return NULL.
*
* C-pluff API functions must not be called from within a create
* function invocation and symbols from imported plug-ins must not be
* used because they may not available yet.
*
* @param ctx the plug-in context of the new plug-in instance
* @return an opaque pointer to plug-in instance data or NULL on failure
*/
void *(*create)(cp_context_t *ctx);
/**
* A start function called to start a plug-in instance.
* The start function must return zero (CP_OK) on success and non-zero
* on failure. If the start fails then the stop function (if any) is
* called to clean up plug-in state. @ref cFuncsInit "Library initialization",
* @ref cFuncsContext "plug-in context management" and
* @ref cFuncsPlugin "plug-in management" functions must not be
* called from within a start function invocation. The start function
* pointer can be NULL if the plug-in runtime does not have a start
* function.
*
* The start function implementation should set up plug-in and return
* promptly. If there is further work to be done then a plug-in can
* start a thread or register a run function using ::cp_run_function.
* Symbols from imported plug-ins are guaranteed to be available for
* the start function.
*
* @param data an opaque pointer to plug-in instance data
* @return non-zero on success, or zero on failure
*/
int (*start)(void *data);
/**
* A stop function called to stop a plugin instance.
* This function must cease all plug-in runtime activities.
* @ref cFuncsInit "Library initialization",
* @ref cFuncsContext "plug-in context management",
* @ref cFuncsPlugin "plug-in management"
* functions, ::cp_run_function and ::cp_resolve_symbol must not be called
* from within a stop function invocation. The stop function pointer can
* be NULL if the plug-in runtime does not have a stop function.
* It is guaranteed that no run functions registered by the plug-in are
* called simultaneously or after the call to the stop function.
*
* The stop function should release any external resources hold by
* the plug-in. Dynamically resolved symbols are automatically released
* and dynamically defined symbols and registered run functions are
* automatically unregistered after the call to stop function.
* Resolved external symbols are still available for the stop function
* and symbols provided by the plug-in should remain available
* after the call to stop function (although functionality might be
* limited). Final cleanup can be safely done in the destroy function.
*
* @param data an opaque pointer to plug-in instance data
*/
void (*stop)(void *data);
/**
* A destroy function called to destroy a plug-in instance.
* This function should release any plug-in instance data.
* The plug-in is stopped before this function is called.
* C-Pluff API functions must not be called from within a destroy
* function invocation and symbols from imported plug-ins must not be
* used because they may not be available anymore. Correspondingly,
* it is guaranteed that the symbols provided by the plug-in are not
* used by other plug-ins when destroy function has been called.
*
* @param data an opaque pointer to plug-in instance data
*/
void (*destroy)(void *data);
};
/*@}*/
/* ------------------------------------------------------------------------
* Function declarations
* ----------------------------------------------------------------------*/
/**
* @defgroup cFuncs Functions
*
* C API functions. The C-Pluff C API functions and
* any data exposed by them are generally thread-safe if the library has been
* compiled with multi-threading support. The
* @ref cFuncsInit "framework initialization functions"
* are exceptions, they are not thread-safe.
*/
/**
* @defgroup cFuncsFrameworkInfo Framework information
* @ingroup cFuncs
*
* These functions can be used to query runtime information about the
* linked in C-Pluff implementation. They may be used by the main program or
* by a plug-in runtime.
*/
/*@{*/
/**
* Returns the release version string of the linked in C-Pluff
* implementation.
*
* @return the C-Pluff release version string
*/
CP_C_API const char *cp_get_version(void) CP_GCC_PURE;
/**
* Returns the canonical host type associated with the linked in C-Pluff implementation.
* A multi-platform installation manager could use this information to
* determine what plug-in versions to install.
*
* @return the canonical host type
*/
CP_C_API const char *cp_get_host_type(void) CP_GCC_PURE;
/*@}*/
/**
* @defgroup cFuncsInit Framework initialization
* @ingroup cFuncs
*
* These functions are used for framework initialization.
* They are intended to be used by the main program. These functions are
* not thread safe.
*/
/*@{*/
/**
* Sets the fatal error handler called on non-recoverable errors. The default
* error handler prints the error message out to standard error and aborts
* the program. If the user specified error handler returns then the framework
* will abort the program. Setting NULL error handler will restore the default
* handler. This function is not thread-safe and it should be called
* before initializing the framework to catch all fatal errors.
*
* @param error_handler the fatal error handler
*/
CP_C_API void cp_set_fatal_error_handler(cp_fatal_error_func_t error_handler);
/**
* Initializes the plug-in framework. This function must be called
* by the main program before calling any other plug-in framework
* functions except @ref cFuncsFrameworkInfo "framework information" functions and
* ::cp_set_fatal_error_handler. This function may be
* called several times but it is not thread-safe. Library resources
* should be released by calling ::cp_destroy when the framework is
* not needed anymore.
*
* Additionally, to enable localization support, the main program should
* set the current locale using @code setlocale(LC_ALL, "") @endcode
* before calling this function.
*
* @return @ref CP_OK (zero) on success or error code on failure
*/
CP_C_API cp_status_t cp_init(void);
/**
* Destroys the plug-in framework and releases the resources used by it.
* The plug-in framework is only destroyed after this function has
* been called as many times as ::cp_init. This function is not
* thread-safe. Plug-in framework functions other than ::cp_init,
* ::cp_get_framework_info and ::cp_set_fatal_error_handler
* must not be called after the plug-in framework has been destroyed.
* All contexts are destroyed and all data references returned by the
* framework become invalid.
*/
CP_C_API void cp_destroy(void);
/*@}*/
/**
* @defgroup cFuncsContext Plug-in context initialization
* @ingroup cFuncs
*
* These functions are used to manage plug-in contexts from the main
* program perspective. They are not intended to be used by a plug-in runtime.
* From the main program perspective a plug-in context is a container for
* installed plug-ins. There can be several plug-in context instances if there
* are several independent sets of plug-ins. However, different plug-in
* contexts are not very isolated from each other in practice because the
* global symbols exported by a plug-in runtime in one context are visible to
* all plug-ins in all context instances.
*/
/*@{*/
/**
* Creates a new plug-in context which can be used as a container for plug-ins.
* Plug-ins are loaded and installed into a specific context. The main
* program may have more than one plug-in context but the plug-ins that
* interact with each other should be placed in the same context. The
* resources associated with the context are released by calling
* ::cp_destroy_context when the context is not needed anymore. Remaining
* contexts are automatically destroyed when the plug-in framework is
* destroyed.
*
* @param status pointer to the location where status code is to be stored, or NULL
* @return the newly created plugin context, or NULL on failure
*/
CP_C_API cp_context_t * cp_create_context(cp_status_t *status);
/**
* Destroys the specified plug-in context and releases the associated resources.
* Stops and uninstalls all plug-ins in the context. The context must not be
* accessed after calling this function.
*
* @param ctx the context to be destroyed
*/
CP_C_API void cp_destroy_context(cp_context_t *ctx) CP_GCC_NONNULL(1);
/**
* Registers a plug-in collection with a plug-in context. A plug-in collection
* is a directory that has plug-ins as its immediate subdirectories. The
* plug-in context will scan the directory when ::cp_scan_plugins is called.
* Returns @ref CP_OK if the directory has already been registered. A plug-in
* collection can be unregistered using ::cp_unregister_pcollection or
* ::cp_unregister_pcollections.
*
* @param ctx the plug-in context
* @param dir the directory
* @return @ref CP_OK (zero) on success or @ref CP_ERR_RESOURCE if insufficient memory
*/
CP_C_API cp_status_t cp_register_pcollection(cp_context_t *ctx, const char *dir) CP_GCC_NONNULL(1, 2);
/**
* Unregisters a previously registered plug-in collection from a
* plug-in context. Plug-ins already loaded from the collection are not
* affected. Does nothing if the directory has not been registered.
* Plug-in collections can be registered using ::cp_register_pcollection.
*
* @param ctx the plug-in context
* @param dir the previously registered directory
*/
CP_C_API void cp_unregister_pcollection(cp_context_t *ctx, const char *dir) CP_GCC_NONNULL(1, 2);
/**
* Unregisters all plug-in collections from a plug-in context.
* Plug-ins already loaded are not affected. Plug-in collections can
* be registered using ::cp_register_pcollection.
*
* @param ctx the plug-in context
*/
CP_C_API void cp_unregister_pcollections(cp_context_t *ctx) CP_GCC_NONNULL(1);
/*@}*/
/**
* @defgroup cFuncsLogging Logging
* @ingroup cFuncs
*
* These functions can be used to receive and emit log messages related
* to a particular plug-in context. They can be used by the main program
* or by a plug-in runtime.
*/
/*@{*/
/**
* Registers a logger with a plug-in context or updates the settings of a
* registered logger. The logger will receive selected log messages.
* If the specified logger is not yet known, a new logger registration
* is made, otherwise the settings for the existing logger are updated.
* The logger can be unregistered using ::cp_unregister_logger and it is
* automatically unregistered when the registering plug-in is stopped or
* when the context is destroyed.
*
* @param ctx the plug-in context to log
* @param logger the logger function to be called
* @param user_data the user data pointer passed to the logger
* @param min_severity the minimum severity of messages passed to logger
* @return @ref CP_OK (zero) on success or @ref CP_ERR_RESOURCE if insufficient memory
*/
CP_C_API cp_status_t cp_register_logger(cp_context_t *ctx, cp_logger_func_t logger, void *user_data, cp_log_severity_t min_severity) CP_GCC_NONNULL(1, 2);
/**
* Removes a logger registration.
*
* @param ctx the plug-in context
* @param logger the logger function to be unregistered
*/
CP_C_API void cp_unregister_logger(cp_context_t *ctx, cp_logger_func_t logger) CP_GCC_NONNULL(1, 2);
/**
* Emits a new log message.
*
* @param ctx the plug-in context
* @param severity the severity of the event
* @param msg the log message (possibly localized)
*/
CP_C_API void cp_log(cp_context_t *ctx, cp_log_severity_t severity, const char *msg) CP_GCC_NONNULL(1, 3);
/**
* Returns whether a message of the specified severity would get logged.
*
* @param ctx the plug-in context
* @param severity the target logging severity
* @return whether a message of the specified severity would get logged
*/
CP_C_API int cp_is_logged(cp_context_t *ctx, cp_log_severity_t severity) CP_GCC_NONNULL(1);
/*@}*/
/**
* @defgroup cFuncsPlugin Plug-in management
* @ingroup cFuncs
*
* These functions can be used to manage plug-ins. They are intended to be
* used by the main program.
*/
/*@{*/
/**
* Loads a plug-in descriptor from the specified plug-in installation
* path and returns information about the plug-in. The plug-in descriptor
* is validated during loading. Possible loading errors are reported via the
* specified plug-in context. The plug-in is not installed to the context.
* If operation fails or the descriptor
* is invalid then NULL is returned. The caller must release the returned
* information by calling ::cp_release_plugin_info when it does not
* need the information anymore, typically after installing the plug-in.
* The returned plug-in information must not be modified.
*
* @param ctx the plug-in context
* @param path the installation path of the plug-in
* @param status a pointer to the location where status code is to be stored, or NULL
* @return pointer to the information structure or NULL if error occurs
*/
CP_C_API cp_plugin_info_t * cp_load_plugin_descriptor(cp_context_t *ctx, const char *path, cp_status_t *status) CP_GCC_NONNULL(1, 2);
/**
* Loads a plug-in descriptor from the specified block of memory and returns
* information about the plug-in. The plug-in descriptor
* is validated during loading. Possible loading errors are reported via the
* specified plug-in context. The plug-in is not installed to the context.
* If operation fails or the descriptor
* is invalid then NULL is returned. The caller must release the returned
* information by calling ::cp_release_info when it does not
* need the information anymore, typically after installing the plug-in.
* The returned plug-in information must not be modified.
*
* @param ctx the plug-in context
* @param buffer the buffer containing the plug-in descriptor.
* @param buffer_len the length of the buffer.
* @param status a pointer to the location where status code is to be stored, or NULL
* @return pointer to the information structure or NULL if error occurs
*/
CP_C_API cp_plugin_info_t * cp_load_plugin_descriptor_from_memory(cp_context_t *ctx, const char *buffer, unsigned int buffer_len, cp_status_t *status) CP_GCC_NONNULL(1, 2);
/**
* Installs the plug-in described by the specified plug-in information
* structure to the specified plug-in context. The plug-in information
* must have been loaded using ::cp_load_plugin_descriptor with the same
* plug-in context.
* The installation fails on #CP_ERR_CONFLICT if the context already
* has an installed plug-in with the same plug-in identifier. Installation
* also fails if the plug-in tries to install an extension point which
* conflicts with an already installed extension point.
* The plug-in information must not be modified but it is safe to call
* ::cp_release_plugin_info after the plug-in has been installed.
*
* @param ctx the plug-in context
* @param pi plug-in information structure
* @return @ref CP_OK (zero) on success or an error code on failure
*/
CP_C_API cp_status_t cp_install_plugin(cp_context_t *ctx, cp_plugin_info_t *pi) CP_GCC_NONNULL(1, 2);
/**
* Scans for plug-ins in the registered plug-in directories, installing
* new plug-ins and upgrading installed plug-ins. This function can be used to
* initially load the plug-ins and to later rescan for new plug-ins.
*
* When several versions of the same plug-in is available the most recent
* version will be installed. The upgrade behavior depends on the specified
* @ref cScanFlags "flags". If #CP_SP_UPGRADE is set then upgrades to installed plug-ins are
* allowed. The old version is unloaded and the new version installed instead.
* If #CP_SP_STOP_ALL_ON_UPGRADE is set then all active plug-ins are stopped
* if any plug-ins are to be upgraded. If #CP_SP_STOP_ALL_ON_INSTALL is set then
* all active plug-ins are stopped if any plug-ins are to be installed or
* upgraded. Finally, if #CP_SP_RESTART_ACTIVE is set all currently active
* plug-ins will be restarted after the changes (if they were stopped).
*
* When removing plug-in files from the plug-in directories, the
* plug-ins to be removed must be first unloaded. Therefore this function
* does not check for removed plug-ins.
*
* @param ctx the plug-in context
* @param flags the bitmask of flags
* @return @ref CP_OK (zero) on success or an error code on failure
*/
CP_C_API cp_status_t cp_scan_plugins(cp_context_t *ctx, int flags) CP_GCC_NONNULL(1);
/**
* Starts a plug-in. Also starts any imported plug-ins. If the plug-in is
* already starting then
* this function blocks until the plug-in has started or failed to start.
* If the plug-in is already active then this function returns immediately.
* If the plug-in is stopping then this function blocks until the plug-in
* has stopped and then starts the plug-in.
*
* @param ctx the plug-in context
* @param id identifier of the plug-in to be started
* @return @ref CP_OK (zero) on success or an error code on failure
*/
CP_C_API cp_status_t cp_start_plugin(cp_context_t *ctx, const char *id) CP_GCC_NONNULL(1, 2);
/**
* Stops a plug-in. First stops any dependent plug-ins that are currently
* active. Then stops the specified plug-in. If the plug-in is already
* stopping then this function blocks until the plug-in has stopped. If the
* plug-in is already stopped then this function returns immediately. If the
* plug-in is starting then this function blocks until the plug-in has
* started (or failed to start) and then stops the plug-in.
*
* @param ctx the plug-in context
* @param id identifier of the plug-in to be stopped
* @return @ref CP_OK (zero) on success or @ref CP_ERR_UNKNOWN if unknown plug-in
*/
CP_C_API cp_status_t cp_stop_plugin(cp_context_t *ctx, const char *id) CP_GCC_NONNULL(1, 2);
/**
* Stops all active plug-ins.
*
* @param ctx the plug-in context
*/
CP_C_API void cp_stop_plugins(cp_context_t *ctx) CP_GCC_NONNULL(1);
/**
* Uninstalls the specified plug-in. The plug-in is first stopped if it is active.
* Then uninstalls the plug-in and any dependent plug-ins.
*
* @param ctx the plug-in context
* @param id identifier of the plug-in to be unloaded
* @return @ref CP_OK (zero) on success or @ref CP_ERR_UNKNOWN if unknown plug-in
*/
CP_C_API cp_status_t cp_uninstall_plugin(cp_context_t *ctx, const char *id) CP_GCC_NONNULL(1, 2);
/**
* Uninstalls all plug-ins. All plug-ins are first stopped and then
* uninstalled.
*
* @param ctx the plug-in context
*/
CP_C_API void cp_uninstall_plugins(cp_context_t *ctx) CP_GCC_NONNULL(1);
/*@}*/
/**
* @defgroup cFuncsPluginInfo Plug-in and extension information
* @ingroup cFuncs
*
* These functions can be used to query information about the installed
* plug-ins, extension points and extensions or to listen for plug-in state
* changes. They may be used by the main program or by a plug-in runtime.
*/
/*@{*/
/**
* Returns static information about the specified plug-in. The returned
* information must not be modified and the caller must
* release the information by calling ::cp_release_info when the
* information is not needed anymore. When a plug-in runtime calls this
* function it may pass NULL as the identifier to get information about the
* plug-in itself.
*
* @param ctx the plug-in context
* @param id identifier of the plug-in to be examined or NULL for self
* @param status a pointer to the location where status code is to be stored, or NULL
* @return pointer to the information structure or NULL on failure
*/
CP_C_API cp_plugin_info_t * cp_get_plugin_info(cp_context_t *ctx, const char *id, cp_status_t *status) CP_GCC_NONNULL(1);
/**
* Returns static information about the installed plug-ins. The returned
* information must not be modified and the caller must
* release the information by calling ::cp_release_info when the
* information is not needed anymore.
*
* @param ctx the plug-in context
* @param status a pointer to the location where status code is to be stored, or NULL
* @param num a pointer to the location where the number of returned plug-ins is stored, or NULL
* @return pointer to a NULL-terminated list of pointers to plug-in information
* or NULL on failure
*/
CP_C_API cp_plugin_info_t ** cp_get_plugins_info(cp_context_t *ctx, cp_status_t *status, int *num) CP_GCC_NONNULL(1);
/**
* Returns static information about the currently installed extension points.
* The returned information must not be modified and the caller must
* release the information by calling ::cp_release_info when the
* information is not needed anymore.
*
* @param ctx the plug-in context
* @param status a pointer to the location where status code is to be stored, or NULL
* @param num filled with the number of returned extension points, if non-NULL
* @return pointer to a NULL-terminated list of pointers to extension point
* information or NULL on failure
*/
CP_C_API cp_ext_point_t ** cp_get_ext_points_info(cp_context_t *ctx, cp_status_t *status, int *num) CP_GCC_NONNULL(1);
/**
* Returns static information about the currently installed extension points.
* The returned information must not be modified and the caller must
* release the information by calling ::cp_release_info when the
* information is not needed anymore.
*
* @param ctx the plug-in context
* @param extpt_id the extension point identifier or NULL for all extensions
* @param status a pointer to the location where status code is to be stored, or NULL
* @param num a pointer to the location where the number of returned extension points is to be stored, or NULL
* @return pointer to a NULL-terminated list of pointers to extension
* information or NULL on failure
*/
CP_C_API cp_extension_t ** cp_get_extensions_info(cp_context_t *ctx, const char *extpt_id, cp_status_t *status, int *num) CP_GCC_NONNULL(1);
/**
* Releases a previously obtained reference counted information object. The
* documentation for functions returning such information refers
* to this function. The information must not be accessed after it has
* been released. The framework uses reference counting to deallocate
* the information when it is not in use anymore.
*
* @param ctx the plug-in context
* @param info the information to be released
*/
CP_C_API void cp_release_info(cp_context_t *ctx, void *info) CP_GCC_NONNULL(1, 2);
/**
* Returns the current state of the specified plug-in. Returns
* #CP_PLUGIN_UNINSTALLED if the specified plug-in identifier is unknown.
*
* @param ctx the plug-in context
* @param id the plug-in identifier
* @return the current state of the plug-in
*/
CP_C_API cp_plugin_state_t cp_get_plugin_state(cp_context_t *ctx, const char *id) CP_GCC_NONNULL(1, 2);
/**
* Registers a plug-in listener with a plug-in context. The listener is called
* synchronously immediately after a plug-in state change. There can be several
* listeners registered with the same context. A plug-in listener can be
* unregistered using ::cp_unregister_plistener and it is automatically
* unregistered when the registering plug-in is stopped or when the context
* is destroyed.
*
* @param ctx the plug-in context
* @param listener the plug-in listener to be added
* @param user_data user data pointer supplied to the listener
* @return @ref CP_OK (zero) on success or @ref CP_ERR_RESOURCE if out of resources
*/
CP_C_API cp_status_t cp_register_plistener(cp_context_t *ctx, cp_plugin_listener_func_t listener, void *user_data) CP_GCC_NONNULL(1, 2);
/**
* Removes a plug-in listener from a plug-in context. Does nothing if the
* specified listener was not registered.
*
* @param ctx the plug-in context
* @param listener the plug-in listener to be removed
*/
CP_C_API void cp_unregister_plistener(cp_context_t *ctx, cp_plugin_listener_func_t listener) CP_GCC_NONNULL(1, 2);
/**
* Traverses a configuration element tree and returns the specified element.
* The target element is specified by a base element and a relative path from
* the base element to the target element. The path includes element names
* separated by slash '/'. Two dots ".." can be used to designate a parent
* element. Returns NULL if the specified element does not exist. If there are
* several subelements with the same name, this function chooses the first one
* when traversing the tree.
*
* @param base the base configuration element
* @param path the path to the target element
* @return the target element or NULL if nonexisting
*/
CP_C_API cp_cfg_element_t * cp_lookup_cfg_element(cp_cfg_element_t *base, const char *path) CP_GCC_PURE CP_GCC_NONNULL(1, 2);
/**
* Traverses a configuration element tree and returns the value of the
* specified element or attribute. The target element or attribute is specified
* by a base element and a relative path from the base element to the target
* element or attributes. The path includes element names
* separated by slash '/'. Two dots ".." can be used to designate a parent
* element. The path may end with '@' followed by an attribute name
* to select an attribute. Returns NULL if the specified element or attribute
* does not exist or does not have a value. If there are several subelements
* with the same name, this function chooses the first one when traversing the
* tree.
*
* @param base the base configuration element
* @param path the path to the target element
* @return the value of the target element or attribute or NULL
*/
CP_C_API char * cp_lookup_cfg_value(cp_cfg_element_t *base, const char *path) CP_GCC_PURE CP_GCC_NONNULL(1, 2);
/*@}*/
/**
* @defgroup cFuncsPluginExec Plug-in execution
* @ingroup cFuncs
*
* These functions support a plug-in controlled execution model. Started plug-ins can
* use ::cp_run_function to register @ref cp_run_func_t "a run function" which is called when the
* main program calls ::cp_run_plugins or ::cp_run_plugins_step. A run
* function should do a finite chunk of work and then return telling whether
* there is more work to be done. A run function is automatically unregistered
* when the plug-in is stopped. Run functions make it possible for plug-ins
* to control the flow of execution or they can be used as a coarse
* way of task switching if there is no multi-threading support.
*
* The C-Pluff distribution includes a generic main program, cpluff-loader,
* which only acts as a plug-in loader. It loads and starts up the
* specified plug-ins, passing any additional startup arguments to them and
* then just calls run functions of the plug-ins. This
* makes it is possible to put all the application specific logic in
* plug-ins. Application does not necessarily need a main program of its own.
*
* It is also safe, from framework perspective, to call these functions from
* multiple threads. Run functions may then be executed in parallel threads.
*/
/*@{*/
/**
* Registers a new run function. The plug-in instance data pointer is given to
* the run function as a parameter. The run function must return zero if it has
* finished its work or non-zero if it should be called again later. The run
* function is unregistered when it returns zero. Plug-in framework functions
* stopping the registering plug-in must not be called from within a run
* function. This function does nothing if the specified run
* function is already registered for the calling plug-in instance.
*
* @param ctx the plug-in context of the registering plug-in
* @param runfunc the run function to be registered
* @return @ref CP_OK (zero) on success or an error code on failure
*/
CP_C_API cp_status_t cp_run_function(cp_context_t *ctx, cp_run_func_t runfunc) CP_GCC_NONNULL(1, 2);
/**
* Runs the started plug-ins as long as there is something to run.
* This function calls repeatedly run functions registered by started plug-ins
* until there are no more active run functions. This function is normally
* called by a thin main proram, a loader, which loads plug-ins, starts some
* plug-ins and then passes control over to the started plug-ins.
*
* @param ctx the plug-in context containing the plug-ins
*/
CP_C_API void cp_run_plugins(cp_context_t *ctx) CP_GCC_NONNULL(1);
/**
* Runs one registered run function. This function calls one
* active run function registered by a started plug-in. When the run function
* returns this function also returns and passes control back to the main
* program. The return value can be used to determine whether there are any
* active run functions left. This function does nothing if there are no active
* registered run functions.
*
* @param ctx the plug-in context containing the plug-ins
* @return whether there are active run functions waiting to be run
*/
CP_C_API int cp_run_plugins_step(cp_context_t *ctx) CP_GCC_NONNULL(1);
/**
* Sets startup arguments for the specified plug-in context. Like for usual
* C main functions, the first argument is expected to be the name of the
* program being executed or an empty string and the argument array should be
* terminated by NULL entry. If the main program is
* about to pass startup arguments to plug-ins it should call this function
* before starting any plug-ins in the context. The arguments are not copied
* and the caller is responsible for keeping the argument data available once
* the arguments have been set until the context is destroyed. Plug-ins can
* access the startup arguments using ::cp_get_context_args.
*
* @param ctx the plug-in context
* @param argv a NULL-terminated array of arguments
*/
CP_C_API void cp_set_context_args(cp_context_t *ctx, char **argv) CP_GCC_NONNULL(1, 2);
/**
* Returns the startup arguments associated with the specified
* plug-in context. This function is intended to be used by a plug-in runtime.
* Startup arguments are set by the main program using ::cp_set_context_args.
* The returned argument count is zero and the array pointer is NULL if no
* arguments have been set.
*
* @param ctx the plug-in context
* @param argc a pointer to a location where the number of startup arguments is stored, or NULL for none
* @return an argument array terminated by NULL or NULL if not set
*/
CP_C_API char **cp_get_context_args(cp_context_t *ctx, int *argc) CP_GCC_NONNULL(1);
/*@}*/
/**
* @defgroup cFuncsSymbols Dynamic symbols
* @ingroup cFuncs
*
* These functions can be used to dynamically access symbols exported by the
* plug-ins. They are intended to be used by a plug-in runtime or by the main
* program.
*/
/*@{*/
/**
* Defines a context specific symbol. If a plug-in has symbols which have
* a plug-in instance specific value then the plug-in should define those
* symbols when it is started. The defined symbols are cleared
* automatically when the plug-in instance is stopped. Symbols can not be
* redefined.
*
* @param ctx the plug-in context
* @param name the name of the symbol
* @param ptr pointer value for the symbol
* @return @ref CP_OK (zero) on success or a status code on failure
*/
CP_C_API cp_status_t cp_define_symbol(cp_context_t *ctx, const char *name, void *ptr) CP_GCC_NONNULL(1, 2, 3);
/**
* Resolves a symbol provided by the specified plug-in. The plug-in is started
* automatically if it is not already active. The symbol may be context
* specific or global. The framework first looks for a context specific
* symbol and then falls back to resolving a global symbol exported by the
* plug-in runtime library. The symbol can be released using
* ::cp_release_symbol when it is not needed anymore. Pointers obtained from
* this function must not be passed on to other plug-ins or the main
* program.
*
* When a plug-in runtime calls this function the plug-in framework creates
* a dynamic dependency from the symbol using plug-in to the symbol
* defining plug-in. The symbol using plug-in is stopped automatically if the
* symbol defining plug-in is about to be stopped. If the symbol using plug-in
* does not explicitly release the symbol then it is automatically released
* after a call to the stop function. It is not safe to refer to a dynamically
* resolved symbol in the stop function except to release it using
* ::cp_release_symbol.
*
* When the main program calls this function it is the responsibility of the
* main program to always release the symbol before the symbol defining plug-in
* is stopped. It is a fatal error if the symbol is not released before the
* symbol defining plug-in is stopped.
*
* @param ctx the plug-in context
* @param id the identifier of the symbol defining plug-in
* @param name the name of the symbol
* @param status a pointer to the location where the status code is to be stored, or NULL
* @return the pointer associated with the symbol or NULL on failure
*/
CP_C_API void *cp_resolve_symbol(cp_context_t *ctx, const char *id, const char *name, cp_status_t *status) CP_GCC_NONNULL(1, 2, 3);
/**
* Releases a previously obtained symbol. The pointer must not be used after
* the symbol has been released. The symbol is released
* only after as many calls to this function as there have been for
* ::cp_resolve_symbol for the same plug-in and symbol.
*
* @param ctx the plug-in context
* @param ptr the pointer associated with the symbol
*/
CP_C_API void cp_release_symbol(cp_context_t *ctx, const void *ptr) CP_GCC_NONNULL(1, 2);
/*@}*/
#ifdef __cplusplus
}
#endif /*__cplusplus*/
#endif /*CPLUFF_H_*/
|