diff options
author | Lubos Lunak <l.lunak@ suse.cz> | 2006-03-15 14:46:02 +0000 |
---|---|---|
committer | Lubos Lunak <l.lunak@ suse.cz> | 2006-03-15 14:46:02 +0000 |
commit | abaf1823ae29cd333c53a80f56ca98f412b6c7c3 (patch) | |
tree | abe8fb5d9468105458c85f1ebdf56c95da9a3a35 | |
parent | 42973bd25b205abd97eedd63687c4179b6fede43 (diff) |
Some silly attempt at C bindings docs.
-rw-r--r-- | portland/dapi/BUILD | 1 | ||||
-rw-r--r-- | portland/dapi/doc/API.txt | 9 | ||||
-rw-r--r-- | portland/dapi/doc/C-API.txt | 214 | ||||
-rw-r--r-- | portland/dapi/doc/C-HOWTO.txt | 204 | ||||
-rw-r--r-- | portland/dapi/lib/callbacks.c | 2 | ||||
-rw-r--r-- | portland/dapi/lib/callbacks.h | 2 | ||||
-rw-r--r-- | portland/dapi/tests/test_callbacks.c | 2 |
7 files changed, 431 insertions, 3 deletions
diff --git a/portland/dapi/BUILD b/portland/dapi/BUILD index 7383cf6..46c9fdd 100644 --- a/portland/dapi/BUILD +++ b/portland/dapi/BUILD @@ -8,6 +8,7 @@ cd kde make -f Makefile.cvs ./configure make +make install If you have a serious problem with the -Werror flag, edit configure.ac and kde/configure.in.in (sorry, but plain C accepts unbelievable nonsense diff --git a/portland/dapi/doc/API.txt b/portland/dapi/doc/API.txt index 536180d..bc73023 100644 --- a/portland/dapi/doc/API.txt +++ b/portland/dapi/doc/API.txt @@ -1,3 +1,12 @@ +============================================================================== + Description of the API +============================================================================== + +This file is a complete list and description of all API calls. It doesn't +contain any information specific to any language bindings. + + + Conventions: ============ diff --git a/portland/dapi/doc/C-API.txt b/portland/dapi/doc/C-API.txt new file mode 100644 index 0000000..cb16ff7 --- /dev/null +++ b/portland/dapi/doc/C-API.txt @@ -0,0 +1,214 @@ +============================================================================== + Description of C API bindings +============================================================================== + +This file contains information specific to the C bindings. Refer to the generic +API documentation for information that is not specific to C bindings. See also +C-HOWTO.txt . + + + + +Data types +========== + + +C allows only a limited set of data types. Types from the abstract API that +are not available in C are used as follows: + +bool - int with values 1 for true and 0 for false + +string - char* NUL-terminated string; calls that return char* allocate it dynamically +and the caller must deallocate it by calling free() + +arrays ( int[], string[] ) - intarr, stringarr (see below) + +windowinfo - DapiWindowInfo (see below) + + +DapiConnection +-------------- + +Opaque data type that contains all internal data. Most calls require it +as the first argument. + + +DapiWindowInfo +-------------- + +Some call require information about a window related to the call. This structure +holds data about such window. Call dapi_windowInfoInitWindow() to fill in the info +or use the convenience _Window functions. + + +void dapi_windowInfoInitWindow( DapiWindowInfo* winfo, long window ) +-------------------------------------------------------------------- + +Initializes DapiWindowInfo with data about given window. + +winfo: DapiWindowInfo data structure to initialize +window: Window handle (as used with X Window System) + + +void dapi_freeWindowInfo( DapiWindowInfo winfo ) +------------------------------------------------ + +Frees DapiWindowInfo structure data. + +winfo: DapiWindowInfo data structure to free data from. + + +intarr +------ + +A structure representing an integer array. +typedef struct + { + int count; + int* data; + } intarr; +'count' is number of elements, 'data' is array of elements. + + +void dapi_freeintarr( intarr arr ) +---------------------------------- + +Convenience function that frees dynamically allocated data from intarr. +All DAPI functions that return intarr allocate the data dynamically +and the caller must free it. + + +stringarr +--------- + +A structure representing a string array. +typedef struct + { + int count; + char** data; + } stringarr; +'count' is number of elements, 'data' is array of char* strings. + + +void dapi_freestringarr( stringarr arr ) +---------------------------------------- + +Convenience function that frees dynamically allocated data from stringarr. +All DAPI functions that return stringarr allocate the data dynamically +and the caller must free it. + + + + + + +Utility functions +================= + + +DapiConnection* dapi_connect( void ) +------------------------------------ + +Tries to connect to a running backend daemon. + +Returns: NULL if failed, opaque connection handle if success. + + +DapiConnection* dapi_connectAndInit( void ) +------------------------------------------- + +Convenience function that calls dapi_connect() and if successful +also performs initialization by calling dapi_Init() (see later). + + +DapiConnection* dapi_namedConnect( const char* name ) +----------------------------------------------------- + +Tries to connect to a named fallback daemon. + +name: name of the fallback daemon +Returns: NULL if failed, opaque connection handle if success. + + +DapiConnection* dapi_namedConnectAndInit( const char* name ) +------------------------------------------------------------ + +Convenience function that calls dapi_namedConnect() and if successful +also performs initialization by calling dapi_Init() (see later). + + +void dapi_close( DapiConnection* conn ) +--------------------------------------- + +Closes a connection to a backend daemon. + +conn: Opaque connection handle. + + +int dapi_socket( DapiConnection* conn ) +--------------------------------------- + +Returns a file descriptor that can be used with system functions such as select() +to watch activity. + +conn: Opaque connection handle. +Returns: file descriptor + + +void dapi_processData( DapiConnection* conn ) +--------------------------------------------- + +Processes pending incoming data on the connection socket. + +conn: Opaque connection handle. + + +int dapi_readCommand( DapiConnection* conn, int* comm, int* seq ) +----------------------------------------------------------------- + +Reads a command header of the next incoming command request/reply. + +conn: Opaque connection handle. +comm: Id number of the incomming command. +seq: Sequence number of the incoming command. +Returns: 1 if successful, 0 if failure + + +TBD: +typedef void (*DapiGenericCallback)( DapiConnection* conn, int command, int seq ); +DapiGenericCallback dapi_setGenericCallback( DapiConnection* conn, DapiGenericCallback callback ); +void dapi_genericCallback( DapiConnection* conn, int command, int seq ); + + + + + + +Calls functions +=============== + + +There are several ways to invoke the API calls. For call XYZ there is: + +- lowlevel dapi_writeCommandXYZ(), dapi_readReplyXYZ() calls that write a command + request resp. read a command reply. + + dapi_writeCommandXYZ() writes a command header and all command arguments and + returns either 0 if failure or sequence number of the command. Each command request + has a specific sequence number assigned and is used to identify replies. + + dapi_readCommandXYZ() reads all reply arguments. It doesn't read command header, + dapi_readCommand() must be called first to identify a command. Returns 1 if success + or 0 if failure. + + Include file dapi/comm_generated.h contains all function prototypes. + +- blocking dapi_XYZ() call that writes a command request and waits for a reply. + Include file dapi/calls_generated.h contains all function prototypes. + +- non-blocking dapi_callbackXYZ() call that writes a command and invokes the passed + callback when a reply comes. + + dapi_callbackXYZ() returns a sequence number if success or 0 if failure + + Include file dapi/callbacks_generated.h contains all function prototypes. diff --git a/portland/dapi/doc/C-HOWTO.txt b/portland/dapi/doc/C-HOWTO.txt new file mode 100644 index 0000000..3425377 --- /dev/null +++ b/portland/dapi/doc/C-HOWTO.txt @@ -0,0 +1,204 @@ +============================================================================== + C API bindings HOWTO +============================================================================== + +This file contains HOWTO information specific to the C bindings. Refer to the generic +API documentation for information that is not specific to C bindings and to +C-API.txt for description of C bindings. + + +Note: Most test programs in tests/ can be also used as examples. + + +Linking with the library +======================== + + +Use #include <dapi/headerfile.h> and add proper include path flags for the compiler +if necessary. + +Add -ldapi and proper library path flags for the linker if necessary. + + + +Handling the DAPI connection +============================ + + +Before using any API calls it is necessary to initialize the DAPI connection first. + +static DapiConnection* my_dapi_connection = NULL; +... +int initializeDapi() + { + my_dapi_connection = dapi_connectAndInit(); + if( my_dapi_connection == NULL ) + return 0; /* oops, failure */ + return 1; + } + +If you want to do more than just perform a simple blocking call, you need to watch +the connection for activity. Use dapi_socket() to get the file descriptor to watch +and call dapi_processData(). + +void mainloop() + { + fd_set in; + FD_ZERO( &in ); + ... all file descriptors the app wants to watch + FD_SET( dapi_socket( my_dapi_connection ), &in ); + ... select() call here + if( FD_ISSET( dapi_socket( my_dapi_connection ), &in )) + dapi_processData( my_dapi_connection ); + ... + } + +Closing of the connection is done using dapi_close(); + + + +Blocking calls +============== + + +For blocking calls, just simply call the matching API function. For example, to open +URL in a browser: + +int openURL( const char* url ) + { + if( dapi_OpenUrl_Window( my_dapi_connection, url, XWINDOW_HANDLE( toplevel_widget ))) + return 1; + ... failure + } + + +OpenUrl call needs a toplevel window in which the request originated (to handle properly +window relations and focus). It is strongly discouraged to omit this information. +If the application has no window at all, use 0. Note a convenience _Window function is +used instead of DapiWindowInfo and dapi_windowInfoInitWindow(). + + +Functions are responsible for freeing resources allocated by the call. For example +when converting KDE's media:/ URL to a local file: + +void handle_media_url( const char* url ) + { + char* local; + /* convert to local file, don't allow download to a temporary file */ + local = dapi_LocalFile_Window( my_dapi_connection, url, NULL, 0, XWINDOW_HANDLE( toplevel_widget )); + if( local != NULL ) /* success */ + { + handle_local_file( local ); + free( local ); + return; + } + } + + +Callbacks +========= + + +Some calls such as downloading a remote file to a temporary local file may take long time +and as such should be processed asynchronously. It is possible to do so using the lowlevel +dapi_read/write function or using callbacks. + +int start_downloading_remote_url( const char* url ) + { + int seq = dapi_callbackLocalFile_Window( my_dapi_connection, url, NULL, 1, XWINDOW_HANDLE( toplevel_widget ), + download_remote_url_callback ); + if( seq != 0 ) + return seq; + ... failure + } + +void download_remote_url_callback( DapiConnection* conn, int seq, const char* result ) + { + /* if this callback is used for more calls, use seq and the value returned from dapi_callbackLocalFile_Window + to identify matching command and reply */ + if( result[ 0 ] != '\0' ) + ... success + else + ... failed to download + } + + +NOTE: Callbacks should not deallocate any of its arguments, callback handling will perform this +automatically after the callback returns. + + +Fallbacks +========= + + +API calls may fail for various reasons: No backend daemon is running or it doesn't implement +the required functionality. + +No backend daemon running +------------------------- + +A backend daemon should be provided by the desktop environment in which the application is running. +If dapi_connectAndInit() call fails, it is most probably because the daemon is not available. +In such case the application may consider shipping its own fallback daemon. + + +int initializeDapi() + { + my_dapi_connection = dapi_connectAndInit(); + if( my_dapi_connection == NULL ) + { /* failure, try a fallback */ + run_fallback_daemon(); + my_dapi_connection = dapi_namedConnectAndInit( "MyAppFooInc" ); + if( my_dapi_connection == NULL ) + return 0; /* still no luck */ + } + return 1; + } + +This approach allows silently expecting all following calls to succeed and not caring about fallback +code at all. (NOTE: still experimental, not sure if it's worth it) + +The provided generic daemon accepts --dapiname argument that specifies the fallback name it should +use. In this specific case run_fallback_daemon() could run "dapi_generic --dapiname MyAppFooInc". + + +Some functionality not available +-------------------------------- + +It is possible to query functionality provided by the backend daemon. + +int is_openurl_supported() + { + intarr capabilities; + int i; + if( dapi_Capabilities( conn, &capabilities )) + { + int has_openurl = 0; + for( i = 0; + i < capabilities.count; + ++i ) + { + if( capabilities.data[ i ] == DAPI_COMMAND_OPENURL ) + has_openurl = 1; + } + } + return has_openurl; + } + +See dapi/comm_generated.h for list of command ids (DAPI_COMMAND_MAILTO for MailTo call etc.) + +Applications may perform one Capabilities call after initializing connection and query for all +required functionality. If they don't find it available they may as well close this connection +and use a fallback daemon in order to expect all calls to succeed. + + +Fallback code +------------- + +Another approach is to just initialize connection and test for failure after every call. + +void openURL( const char* url ) + { + if( !dapi_OpenUrl_Window( my_dapi_connection, url, XWINDOW_HANDLE( toplevel_widget ))) + openInHardcodedBrowser( url ); + } diff --git a/portland/dapi/lib/callbacks.c b/portland/dapi/lib/callbacks.c index 2ac8f47..62f402d 100644 --- a/portland/dapi/lib/callbacks.c +++ b/portland/dapi/lib/callbacks.c @@ -14,7 +14,7 @@ DapiGenericCallback dapi_setGenericCallback( DapiConnection* conn, DapiGenericCa return ret; } -void dapi_processCallbacks( DapiConnection* conn ) +void dapi_processData( DapiConnection* conn ) { while( dapi_hasData( conn )) { diff --git a/portland/dapi/lib/callbacks.h b/portland/dapi/lib/callbacks.h index 81f8c01..333ee82 100644 --- a/portland/dapi/lib/callbacks.h +++ b/portland/dapi/lib/callbacks.h @@ -13,7 +13,7 @@ typedef void (*DapiGenericCallback)( DapiConnection* conn, int command, int seq DapiGenericCallback dapi_setGenericCallback( DapiConnection* conn, DapiGenericCallback callback ); -void dapi_processCallbacks( DapiConnection* conn ); +void dapi_processData( DapiConnection* conn ); void dapi_genericCallback( DapiConnection* conn, int command, int seq ); diff --git a/portland/dapi/tests/test_callbacks.c b/portland/dapi/tests/test_callbacks.c index c682a54..6f4cd40 100644 --- a/portland/dapi/tests/test_callbacks.c +++ b/portland/dapi/tests/test_callbacks.c @@ -24,7 +24,7 @@ int main() seq = dapi_callbackButtonOrder( conn, callback ); printf( "Order call2: %d\n", seq ); sleep( 1 ); /* give time to process */ - dapi_processCallbacks( conn ); + dapi_processData( conn ); dapi_close( conn ); return 0; } |