| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html><head><title>Axis2/C - Axis2/C Developer Guide</title><style type="text/css" media="all"> |
| @import url("../style/maven-base.css"); |
| |
| @import url("../style/maven-classic.css");</style><link rel="stylesheet" href="../style/print.css" type="text/css" media="print"></link><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"></meta></head><body class="composite"><div id="banner"><a href="http://www.apache.org/" id="organizationLogo"><img alt="Apache Software Foundation" src="http://www.apache.org/images/asf-logo.gif"></img></a><a href="http://ws.apache.org/axis2/c" id="projectLogo"><img alt="Apache Axis2 C" src="http://ws.apache.org/axis2/images/axis.jpg"></img></a><div class="clear"><hr></hr></div></div><div id="breadcrumbs"><div class="xleft"> |
| Last published: 22 December 2006 |
| | Doc for 0.96</div><div class="xright"></div><div class="clear"><hr></hr></div></div><div id="leftColumn"><div id="navcolumn"><div id="menuAxis2_C"><h5>Axis2/C</h5><ul><li class="none"><a href="../index.html">Home</a></li><li class="expanded"><a href="../download.cgi">Download Axis2/C</a><ul><li class="none"><a href="../download.cgi">Releases</a></li><li class="none"><a href="http://svn.apache.org/viewcvs.cgi/webservices/axis2/trunk/c/" class="externalLink" title="External Link">View Source Code Online</a></li><li class="none"><a href="../svn.html">Checkout Source Code</a></li></ul></li><li class="expanded"><a href="../docs/index.html">Documentation</a><ul><li class="none"><a href="../docs/installationguide.html">Installation Guide</a></li><li class="none"><a href="../docs/developerguide.html">Developer Guide</a></li><li class="none"><a href="../docs/userguide.html">User Guide</a></li><li class="none"><a href="../docs/axis2c_manual.html">Axis2/C manual</a></li></ul></li><li class="expanded"><a href="../mail-lists.html">Get Involved</a><ul><li class="none"><a href="../mail-lists.html">Mailing Lists</a></li></ul></li><li class="expanded"><a href="../team-list.html">Project Information</a><ul><li class="none"><a href="../team-list.html">Project Team</a></li><li class="none"><a href="../issue-tracking.html">Issue Tracking</a></li></ul></li></ul></div><a href="http://maven.apache.org/" title="Built by Maven" id="poweredBy"><img alt="Built by Maven" src="../images/logos/maven-button-1.png"></img></a></div></div><div id="bodyColumn"><div class="contentBox"><div class="section"><a name="Axis2_C_Developer_Guide"></a><h2>Axis2/C Developer Guide</h2><p>Please send your feedback to developer mailing list: <a href="mailto:axis-c-dev@ws.apache.org">axis-c-dev@ws.apache.org</a> (Please |
| remember to prefix the subject with [Axis2]). To subscribe to developer |
| mailing lists see <a href="../mail-lists.html">here</a>.</p><div class="subsection"><a name="Content"></a><h3>Content</h3><p>This guide walks you through the following topics with the aim of helping you get |
| familiar with the Axis2/C project and its development norms quickly.</p><ul> |
| <li><a href="#Programming_Model">Programming model</a></li> |
| <li><a href="#Memory_Management">Memory management</a></li> |
| <li><a href="#Coding_Conventions">Coding conventions</a></li> |
| <li><a href="#Unit_Tests">Unit tests</a></li> |
| </ul><p><a id="Programming_Model"></a></p></div><div class="subsection"><a name="Programming_Model"></a><h3>Programming Model</h3><p>Axis2/C programming model uses a pseudo object oriented model to achieve |
| data hiding. The following example illustrates how this is done. |
| Each struct corresponds to the "class" concept in object oriented |
| programming. Hence, each struct has its own header file, that exposes the API |
| for that struct and a source file, that contains the functional |
| implementation.</p><p>Operations associated with a struct are bundled into an operations struct |
| ('ops' struct), and this ops struct is exposed in the header file. The real |
| implementation struct ('impl' struct) with the data fields is hidden from the |
| user, and lives in the source file. To ease the user from the complex syntax |
| required to access the functions in a given ops struct, macros are provided |
| to access them. Since the data is hidden, it is the usual practice to provide |
| *getter* and *setter* methods for the data fields of the struct, in addition to |
| the other processing functionality. The actual functional implementations in |
| the source file are mapped to the ops struct functions declared in the header |
| file by means of function pointer assignments.</p><p>Here is a sample header file associated with the "foo" struct. (Imagine a |
| class called "foo" in the proper object oriented programming model.)</p><strong>/* axis2_ foo.h */</strong> |
| <div class="source"><pre> |
| typedef struct axis2_foo_ops axis2_foo_ops_t; |
| typedef struct axis2_foo axis2_foo_t; |
| |
| struct axis2_foo_ops |
| { |
| void (AXIS2_CALL *bar)(axis2_foo_t *foo, const axis2_env_t *env, void *data); |
| axis2_status_t (AXIS2_CALL *free)(axis2_foo_t *foo, const axis2_env_t *env); |
| }; |
| |
| struct axis2_foo |
| { |
| axis2_foo_ops_t *ops; |
| } |
| |
| |
| axis2_foo_t * axis2_foo_create(const axis2_env_t *env); |
| |
| /* Macros are provided to access functions defined in the ops structure */ |
| |
| #define AXIS2_FOO_BAR(foo, env, data)\ |
| ((foo)->ops->bar(foo, env, data)) |
| #define AXIS2_FOO_FREE(foo, env)\ |
| ((foo)->ops->free(foo, env)) |
| |
| </pre></div> |
| <p></p><p>The implementation file for "foo" struct is shown below.</p> |
| <div class="source"><pre> |
| #include <axis2_foo.h> |
| |
| typedef struct axis2_foo_impl axis2_foo_impl_t; |
| |
| struct axis2_foo_impl |
| { |
| axis2_foo_t foo; |
| my_type my_data; /*private data*/ |
| }; |
| |
| |
| /* Function Headers */ |
| |
| void AXIS2_CALL axis2_foo_bar(axis2_foo_t *foo, const axis2_env_t *env, void *data); |
| axis2_status_t AXIS2_CALL axis2_foo_free(axis2_foo_t *foo, const axis2_env_t *env); |
| |
| /* Function Implementations */ |
| axis2_foo_t * AXIS2_CALL axis2_foo_create(const axis2_env_t *env) |
| { |
| axis2_foo_impl_t * foo_impl = NULL; |
| /* create axis2_foo_impl_t structure and initialize private data */ |
| |
| /* create ops structure of foo */ |
| |
| /* bind ops to functions */ |
| foo_impl->foo.ops->bar = axis2_foo_bar; |
| foo_impl->foo.ops->free = axis2_foo_free; |
| |
| return &(foo_impl->foo); |
| } |
| |
| void AXIS2_CALL axis2_foo_bar(axis2_foo_t *foo, const axis2_env_t *env, void *data) |
| { |
| /* do something */ |
| } |
| |
| axis2_status_t AXIS2_CALL axis2_foo_free(axis2_foo_t *foo, const axis2_env_t *env) |
| { |
| /* do the dirty work of cleaning the allocated memory */ |
| } |
| </pre></div> |
| <p><a id="Memory_Management"></a></p><p>If you take a closer look at the sample above, you will see that |
| almost all functions take a double pointer to the axis2_env struct. To learn |
| more about the Axis2/C environment, please have a look at the <a href="architecture_notes.html">architecture notes</a>.</p></div><div class="subsection"><a name="Memory_Management"></a><h3>Memory Management</h3><p>When writing services as well as client programs, you have to ensure that |
| you do proper memory management. You need to be careful to deallocate the |
| memory you have allocated in order to avoid memory leaks (and to avoid those |
| nasty segmentation faults ;-) ). Remebering where you allocate memory is a |
| good practice, which will help you to properly free such allocated memory.</p></div><div class="subsection"><a name="Memory_Management_Guidelines_for_Developing_Services"></a><h3>Memory Management Guidelines for Developing Services</h3><p>To understand how the allocated memory is reclaimed, it is worth looking |
| at the service skeleton interface which is defined in : |
| <strong>axis2_svc_skeleton.h</strong></p> |
| <div class="source"><pre> |
| AXIS2_DECLARE_DATA struct axis2_svc_skeleton_ops |
| { |
| int (AXIS2_CALL * free)(axis2_svc_skeleton_t *svc_skeli, const axis2_env_t *env); |
| ... |
| }; |
| |
| AXIS2_DECLARE_DATA struct axis2_svc_skeleton |
| { |
| axis2_svc_skeleton_ops_t *ops; |
| axis2_array_list_t *func_array; |
| }; |
| |
| </pre></div> |
| <p></p><p>The service skeleton implementation should implement the <code>free</code> |
| function and attach that to the ops struct of |
| <code>axis2_svc_skeleton_t</code> struct. This <code>free</code> function is |
| called each time after a web services request is served.</p><p>Let's try to understand this through an example.</p><p></p><p>Example: <b>Service skeleton implementation for math service.</b></p><p>The following code shows the implementation of <code>math_free</code> |
| function which is to be attached to the ops of |
| <code>axis2_svc_skeleton_t</code> struct. Usually the memory allocated for |
| the operations struct, the function array and the service skeleton struct are |
| cleaned inside this. You may clean additional memory here if you have |
| allocated any specific memory blocks in <code>math_create</code> function or |
| elsewhere, depending on your implementation specifics.</p><p></p> |
| <div class="source"><pre>int AXIS2_CALL math_free(axis2_svc_skeleton_t *svc_skeleton, const axis2_env_t *env) |
| { |
| if(svc_skeleton->ops) |
| { |
| AXIS2_FREE(env->allocator, svc_skeleton->ops); |
| svc_skeleton->ops = NULL; |
| } |
| if(svc_skeleton->func_array) |
| { |
| AXIS2_ARRAY_LIST_FREE(svc_skeleton->func_array, env); |
| svc_skeleton->func_array = NULL; |
| } |
| if(svc_skeleton) |
| { |
| AXIS2_FREE(env->allocator, svc_skeleton); |
| svc_skeleton = NULL; |
| } |
| return AXIS2_SUCCESS; |
| } |
| |
| </pre></div> |
| <p></p><p>In the <code>axis2_math_create</code> function, you assign the function |
| pointer of <code>math_free</code> function to the <code>free</code> function |
| of the operations struct. As you can see, now the SOAP engine has a function |
| reference to perform garbage collection after each service request.</p><p></p> |
| <div class="source"><pre>AXIS2_EXTERN axis2_svc_skeleton_t * AXIS2_CALL axis2_math_create(const axis2_env_t *env) |
| { |
| axis2_svc_skeleton_t *svc_skeleton = NULL; |
| svc_skeleton = AXIS2_MALLOC(env->allocator, sizeof(axis2_svc_skeleton_t)); |
| |
| svc_skeleton->ops = AXIS2_MALLOC(env->allocator, sizeof(axis2_svc_skeleton_ops_t)); |
| |
| svc_skeleton->ops->free = math_free; |
| ... |
| return svc_skeleton; |
| } |
| |
| |
| </pre></div> |
| <p>SOAP engine frees the memory allocated for the <code>axiom_node_t</code> |
| struct that is used to form the response SOAP message. However, it is the |
| responsibility of the service developer to clean any additional memory |
| allocated.</p><p></p></div><div class="subsection"><a name="Memory_Management_Guidelines_for_Developing_Clients"></a><h3>Memory Management Guidelines for Developing Clients</h3><p> |
| Most of the memory allocated in the client side (including SOAP request and |
| reply messges), should be cleaned in the client side itself. Memory allocated |
| for properties are taken care of by the SOAP engine. SOAP engine reclaims the |
| memory allocated for properties based on the scope (Request, Session or |
| Application) that you set for each property. |
| |
| <a id="Coding_Conventions"></a></p></div><div class="subsection"><a name="Coding_Conventions"></a><h3>Coding Conventions</h3><p>Coding conventions used with the Axis2 project is listed in <a href="../coding_conventions.html">this</a> document.</p><p><a id="Unit_Tests"></a></p></div><div class="subsection"><a name="Unit_Tests"></a><h3>Unit Tests</h3><p><a href="http://cutest.sourceforge.net/" class="externalLink" title="External Link">CuTest</a> library is used to |
| write unit tests in Axis2/C.</p><p>You need to follow two steps to write a unit test for a module.</p><p> |
| 1. Add the unit test to the module's test suite. |
| |
| </p><p>2. Add the module's test suite to the main unit test suite.</p><p></p></div><div class="subsection"><a name="Step1:_Adding_a_unit_test_to_a_module_s_unit_test_suite"></a><h3>Step1: Adding a unit test to a module's unit test suite</h3><p>This section illustrates how to add a unit test case to the util module. |
| Let's take, for example, the unit tests for axis2 stream. There are two files |
| named <code>util_stream_test.c/.h</code> placed into modules/util/test folder. Here's a |
| sample code written to test the operation |
| <code>axis2_stream_ops_read</code>.</p> |
| <div class="source"><pre> |
| #include "util_stream_test.h" |
| |
| void Testaxis2_stream_ops_read(CuTest *tc) |
| { |
| char actual[10]; |
| axis2_allocator_t *allocator = axis2_allocator_init(NULL); |
| axis2_env_t *env = axis2_environment_create(allocator, NULL, NULL, NULL, NULL); |
| axis2_stream_read(env->stream, actual, 10); |
| char *expected = strdup("aaaaaaaaa"); |
| CuAssertStrEquals(tc, expected, actual); |
| } |
| |
| |
| </pre></div> |
| <p>The prototype of the function should be added to the header file. The test |
| suite is defined in <code>util_test.c</code>. You need to add the above defined test case |
| to the test suite as shown below.</p> |
| <div class="source"><pre>#include "util_test.h" |
| #include <axis2_allocator.h> |
| #include <axis2_environment.h> |
| |
| CuSuite* axis2_utilGetSuite() |
| { |
| CuSuite* suite = CuSuiteNew(); |
| |
| SUITE_ADD_TEST(suite, Testaxis2_stream_ops_read); |
| SUITE_ADD_TEST(suite, Testaxis2_log_ops_write); |
| SUITE_ADD_TEST(suite, Testaxis2_hash_ops_get); |
| |
| return suite; |
| } |
| |
| |
| </pre></div> |
| </div><div class="subsection"><a name="Step2:_Adding_the_Module_test_suite_to_the_Main_Unit_Test_Suite"></a><h3>Step2: Adding the Module test suite to the Main Unit Test Suite</h3><p>Now, you need to add the util module test suite to the main test suite.</p> |
| <div class="source"><pre>#include <CuTest.h> |
| #include "../../util/test/util_test.h" |
| #include "../../common/test/common_test.h" |
| |
| void RunAllTests(void) |
| { |
| CuString *output = CuStringNew(); |
| CuSuite* suite = CuSuiteNew(); |
| |
| CuSuiteAddSuite(suite, axis2_utilGetSuite()); |
| CuSuiteAddSuite(suite, axis2_commonGetSuite()); |
| CuSuiteRun(suite); |
| CuSuiteSummary(suite, output); |
| CuSuiteDetails(suite, output); |
| printf("%s\n", output->buffer); |
| } |
| |
| int main(void) |
| { |
| RunAllTests(); |
| return 0; |
| } |
| |
| |
| </pre></div> |
| <p>You can either run only the unit tests written for the util module or |
| all the tests.</p></div></div></div></div><div class="clear"><hr></hr></div><div id="footer"><div class="xright">© 2005-2006, Apache Software Foundation</div><div class="clear"><hr></hr></div></div></body></html> |