Revision: 10796
http://swig.svn.sourceforge.net/swig/?rev=10796&view=rev
Author: maciekd
Date: 2008-08-24 12:39:30 +0000 (Sun, 24 Aug 2008)
Log Message:
-----------
1. char_strings runtime test
2. next chapters of HTML doc
3. minor bugfixes
Modified Paths:
--------------
branches/gsoc2008-maciekd/Doc/Manual/C.html
branches/gsoc2008-maciekd/Examples/test-suite/c/Makefile.in
branches/gsoc2008-maciekd/Lib/c/c.swg
branches/gsoc2008-maciekd/Source/Modules/c.cxx
Added Paths:
-----------
branches/gsoc2008-maciekd/Examples/test-suite/c/char_strings_runme.c
Modified: branches/gsoc2008-maciekd/Doc/Manual/C.html
===================================================================
--- branches/gsoc2008-maciekd/Doc/Manual/C.html 2008-08-19 07:43:48 UTC (rev 10795)
+++ branches/gsoc2008-maciekd/Doc/Manual/C.html 2008-08-24 12:39:30 UTC (rev 10796)
@@ -54,7 +54,7 @@
</p>
<p>
-Flattening C++ language constructs into a set of C-style functions obviously comes with many limitations and inconveniences. All data and functions becomes global. Manipulating objects requires explicit calls to special functions. We are losing the high level abstraction and have to work around it.
+Flattening C++ language constructs into a set of C-style functions obviously comes with many limitations and inconveniences. All data and functions become global. Manipulating objects requires explicit calls to special functions. We are losing the high level abstraction and have to work around it.
</p>
<H2><a name="c_preliminaries"></a>36.2 Preliminaries</H2>
@@ -132,7 +132,9 @@
<H3><a name="c_dynamic"></a>36.2.3 Compiling dynamic module</H3>
+<p>
The next step is to build dynamically loadable module, which we can link to our application. This can be done easily, for example using <tt>gcc</tt> compiler (Linux, MINGW, etc.):
+</p>
<div class="code"><pre>
$ swig -c example.i
@@ -172,18 +174,207 @@
<H2><a name="c_basic_c_wrapping"></a>36.3 Basic C wrapping</H2>
+<p>
+Wrapping C functions and variables is obviously performed in straightforward way. There is no need to perform type conversions, and all language constructs can be preserved in their original form. However, SWIG allows you to enchance the code with some additional elements, for instance using <tt>check</tt> typemap or <tt>%extend</tt> directive.
+</p>
+
<H3><a name="c_c_functions"></a>36.3.1 Functions</H3>
+<p>
+For each C function declared in the interface file a wrapper function is created. Basically, the wrapper function performs a call to the original function, and returns its result.
+</p>
+
+<p>
+For example, for function declaration:
+</p>
+
+<div class="code"><pre>
+int gcd(int x, int y);
+</pre></div>
+
+<p>
+The output is simply:
+</p>
+
+<div class="code"><pre>
+int _wrap_gcd(int arg1, int arg2) {
+ int result;
+ result = gcd(arg1,arg2);
+ return result;
+}
+</pre></div>
+
+<p>
+Then again, this wrapper function is usually called from C using helper function declared in proxy file, preserving the original name:
+</p>
+
+<div class="code"><pre>
+int gcd(int arg1, int arg2) {
+ return _wrap_gcd(arg1,arg2);
+}
+</pre></div>
+
+<p>
+Now one might think, what's the use of creating such functions in C? The answer is, you can apply special rules to the generated code. Take for example constraint checking. You can write a "check" typemap in your interface file:
+</p>
+
+<div class="code"><pre>
+%typemap(check) int POSITIVE {
+ if ($1 <= 0)
+ fprintf(stderr, "Expected positive value in $name.\n");
+}
+
+int gcd(int POSITIVE, int POSITIVE);
+</pre></div>
+
+<p>
+And now the generated result looks like:
+</p>
+
+<div class="code"><pre>
+int _wrap_gcd(int arg1, int arg2) {
+ {
+ if (arg1 <= 0)
+ fprintf(stderr, "Expected positive value in gcd.\n");
+ }
+ {
+ if (arg1 <= 0)
+ fprintf(stderr, "Expected positive value in gcd.\n");
+ }
+ int result;
+ result = gcd(arg1,arg2);
+ return result;
+}
+</pre></div>
+
+<p>
+This time calling <tt>gcd</tt> with negative value argument will trigger an error message. This can save you time writing all the constraint checking code by hand.
+</p>
+
<H3><a name="c_c_variables"></a>36.3.2 Variables</H3>
+<p>
+Wrapping variables comes also without any special issues. All global variables are directly accessible from application code. There is a difference in the semantics of <tt>struct</tt> definition in C and C++. When handling C <tt>struct</tt>, SWIG simply rewrites its declaration. In C++ <tt>struct</tt> is handled as class declaration.
+</p>
+
+<p>
+You can still apply some of the SWIG features when handling structs, e.g. <tt>%extend</tt> directive. Suppose, you have a C struct declaration:
+</p>
+
+<div class="code"><pre>
+typedef struct {
+ int x;
+ char *str;
+} my_struct;
+</pre></div>
+
+<p>
+You can redefine it to have an additional fields, like:
+</p>
+
+<div class="code"><pre>
+%extend my_struct {
+ double d;
+};
+</pre></div>
+
+<p>
+In application code:
+</p>
+
+<div class="targetlang"><pre>
+struct my_struct ms;
+ms.x = 123;
+ms.d = 123.123;
+</pre></div>
+
<H2><a name="c_basic_cpp_wrapping"></a>36.4 Basic C++ wrapping</H2>
+<p>
+The main reason of having the C module in SWIG is to be able to access C++ from C. In this chapter we will take a look at the rules of wrapping elements of C++ language.
+</p>
+
<H3><a name="c_classes"></a>36.4.1 Classes</H3>
+<p>
+Consider the following example. We have a C++ class, and want to refer to it in C.
+</p>
+
+<div class="code"><pre>
+class Circle {
+public:
+ double radius;
+
+ Circle(double r) : radius(r) { };
+ double area(void);
+};
+</pre></div>
+
+<p>
+What we need to do is to create an object of the class, then to be able to manipulate on it, and finally, to be able to destroy it. SWIG generates C functions for this purpose each time a class declaration is encountered in the interface file.
+</p>
+
+<p>
+The first two generated functions are used to create and destroy instances of class <tt>Circle</tt>. Such an instances are represented on the C side as pointers to special structs, called <tt>SwigObj</tt>. They are all "renamed" (via typedef) to the original class names, so that you can refer to the object instances on the C side using pointers like:
+</p>
+
+<div class="targetlang"><pre>
+Circle *circle;
+</pre></div>
+
+<p>
+The generated functions make calls to class' constructors and destructors, respectively. They also do all the necessary things required by the SWIG object management system in C.
+</p>
+
+<div class="code"><pre>
+Circle * new_Circle(double r);
+void delete_Circle(Circle * self);
+</pre></div>
+
+<p>
+The class <tt>Circle</tt> has a public variable called <tt>radius</tt>. SWIG generates a pair of setters and getters for each such variable:
+</p>
+
+<div class="code"><pre>
+void Circle_radius_set(Circle * self, double radius);
+double Circle_radius_get(Circle * self);
+</pre></div>
+
+<p>
+For each public method, an appropriate function is generated:
+</p>
+
+<div class="code"><pre>
+double Circle_area(Circle * self);
+</pre></div>
+
+<p>
+You can see that in order to refer to the generated object we need to provide a pointer to the object instance (struct <tt>Circle</tt> in this case) as the first function argument. In fact, this struct is basically wrapping pointer to the "real" C++ object.
+</p>
+
+<p>
+Our application code could look like this:
+</p>
+
+<div class="targetlang"><pre>
+ Circle *c = new_Circle(1.5);
+ printf("radius: %f\narea: %f\n", Circle_radius_get(c), Circle_area(c));
+ delete_Circle(c);
+</pre></div>
+
+<p>
+After running this we'll get:
+</p>
+
+<div class="shell"><pre>
+radius: 1.500000
+area: 7.068583
+</pre></div>
+
<H2><a name="c_exceptions"></a>36.5 Exception handling</H2>
Modified: branches/gsoc2008-maciekd/Examples/test-suite/c/Makefile.in
===================================================================
--- branches/gsoc2008-maciekd/Examples/test-suite/c/Makefile.in 2008-08-19 07:43:48 UTC (rev 10795)
+++ branches/gsoc2008-maciekd/Examples/test-suite/c/Makefile.in 2008-08-24 12:39:30 UTC (rev 10796)
@@ -13,10 +13,12 @@
C_TEST_CASES =
CPP_TEST_CASES = \
- exception_order \
- exception_partial_info \
- enums \
- enum_plus \
+ cast_operator \
+ char_strings \
+ exception_order \
+ exception_partial_info \
+ enums \
+ enum_plus \
include $(srcdir)/../common.mk
Added: branches/gsoc2008-maciekd/Examples/test-suite/c/char_strings_runme.c
===================================================================
--- branches/gsoc2008-maciekd/Examples/test-suite/c/char_strings_runme.c (rev 0)
+++ branches/gsoc2008-maciekd/Examples/test-suite/c/char_strings_runme.c 2008-08-24 12:39:30 UTC (rev 10796)
@@ -0,0 +1,198 @@
+#include <stdio.h>
+
+#include "char_strings/char_strings_proxy.h"
+
+int main() {
+ char *CPLUSPLUS_MSG = "A message from the deep dark world of C++, where anything is possible.";
+ char *OTHERLAND_MSG = "Little message from the safe world.";
+
+ long count = 10000;
+ long i = 0;
+
+ // get functions
+ for (i=0; i<count; i++) {
+ char *str = GetCharHeapString();
+ if (strcmp(str, CPLUSPLUS_MSG) != 0) {
+ fprintf(stderr, "Test char get 1 failed, iteration %d\n", i);
+ SWIG_exit(1);
+ }
+ DeleteCharHeapString();
+ }
+
+ for (i=0; i<count; i++) {
+ const char *str = GetConstCharProgramCodeString();
+ if (strcmp(str, CPLUSPLUS_MSG) != 0) {
+ fprintf(stderr, "Test char get 2 failed, iteration %d\n", i);
+ SWIG_exit(1);
+ }
+ DeleteCharHeapString();
+ }
+
+ for (i=0; i<count; i++) {
+ char *str = GetCharStaticString();
+ if (strcmp(str, CPLUSPLUS_MSG) != 0) {
+ fprintf(stderr, "Test char get 3 failed, iteration %d\n", i);
+ SWIG_exit(1);
+ }
+ }
+
+ for (i=0; i<count; i++) {
+ char *str = GetCharStaticStringFixed();
+ if (strcmp(str, CPLUSPLUS_MSG) != 0) {
+ fprintf(stderr, "Test char get 4 failed, iteration %d\n", i);
+ SWIG_exit(1);
+ }
+ }
+
+ for (i=0; i<count; i++) {
+ const char *str = GetConstCharStaticStringFixed();
+ if (strcmp(str, CPLUSPLUS_MSG) != 0) {
+ fprintf(stderr, "Test char get 5 failed, iteration %d\n", i);
+ SWIG_exit(1);
+ }
+ }
+
+ // set functions
+ for (i=0; i<count; i++) {
+ char str[256];
+ sprintf(str, "%s%d", OTHERLAND_MSG, i);
+ if (!SetCharHeapString(str, i)) {
+ fprintf(stderr, "Test char set 1 failed, iteration %d\n", i);
+ SWIG_exit(1);
+ }
+ }
+
+
+ for (i=0; i<count; i++) {
+ char str[256];
+ sprintf(str, "%s%d", OTHERLAND_MSG, i);
+ if (!SetCharStaticString(str, i)) {
+ fprintf(stderr, "Test char set 2 failed, iteration %d\n", i);
+ SWIG_exit(1);
+ }
+ }
+
+ for (i=0; i<count; i++) {
+ char str[256];
+ sprintf(str, "%s%d", OTHERLAND_MSG, i);
+ if (!SetCharArrayStaticString(str, i)) {
+ fprintf(stderr, "Test char set 3 failed, iteration %d\n", i);
+ SWIG_exit(1);
+ }
+ }
+
+ for (i=0; i<count; i++) {
+ char str[256];
+ sprintf(str, "%s%d", OTHERLAND_MSG, i);
+ if (!SetConstCharHeapString(str, i)) {
+ fprintf(stderr, "Test char set 4 failed, iteration %d\n", i);
+ SWIG_exit(1);
+ }
+ }
+
+ for (i=0; i<count; i++) {
+ char str[256];
+ sprintf(str, "%s%d", OTHERLAND_MSG, i);
+ if (!SetConstCharStaticString(str, i)) {
+ fprintf(stderr, "Test char set 5 failed, iteration %d\n", i);
+ SWIG_exit(1);
+ }
+ }
+
+ for (i=0; i<count; i++) {
+ char str[256];
+ sprintf(str, "%s%d", OTHERLAND_MSG, i);
+ if (!SetConstCharArrayStaticString(str, i)) {
+ fprintf(stderr, "Test char set 6 failed, iteration %d\n", i);
+ SWIG_exit(1);
+ }
+ }
+
+ // get set function
+ for (i=0; i<count; i++) {
+ char ping[256];
+ sprintf(ping, "%s%d", OTHERLAND_MSG, i);
+ char *pong = CharPingPong(ping);
+ if (strcmp(ping, pong) != 0) {
+ fprintf(stderr, "Test PingPong 1 failed.\nExpected:%d\nReceived:%d\n", ping, pong);
+ SWIG_exit(1);
+ }
+ }
+
+ // variables
+
+ for (i=0; i<count; i++) {
+ char str[256];
+ sprintf(str, "%s%d", OTHERLAND_MSG, i);
+ global_char = str;
+ if (strcmp(global_char, str) != 0) {
+ fprintf(stderr, "Test variables 1 failed, iteration %d\n", i);
+ SWIG_exit(1);
+ }
+ }
+
+ for (i=0; i<count; i++) {
+ char str[256];
+ sprintf(str, "%s%d", OTHERLAND_MSG, i);
+ sprintf(global_char_array1, "%s%d", OTHERLAND_MSG, i);
+ if (strcmp(global_char_array1, str) != 0) {
+ fprintf(stderr, "Test variables 2 failed, iteration %d\n", i);
+ SWIG_exit(1);
+ }
+ }
+
+ for (i=0; i<count; i++) {
+ char str[256];
+ sprintf(str, "%s%d", OTHERLAND_MSG, i);
+ sprintf(global_char_array2, "%s%d", OTHERLAND_MSG, i);
+ if (strcmp(global_char_array2, str) != 0) {
+ fprintf(stderr, "Test variables 3 failed, iteration %d\n", i);
+ SWIG_exit(1);
+ }
+ }
+
+ for (i=0; i<count; i++) {
+ if (strcmp(global_const_char, CPLUSPLUS_MSG) != 0) {
+ fprintf(stderr, "Test variables 3 failed, iteration %d\n", i);
+ SWIG_exit(1);
+ }
+ }
+
+ /*
+ for (i=0; i<count; i++) {
+ if (strcmp(global_const_char_array1, CPLUSPLUS_MSG) != 0) {
+ fprintf(stderr, "Test variables 5 failed, iteration %d\n", i);
+ SWIG_exit(1);
+ }
+ }
+
+ for (i=0; i<count; i++) {
+ if (strcmp(global_const_char_array2, CPLUSPLUS_MSG) != 0) {
+ fprintf(stderr, "Test variables 6 failed, iteration %d\n", i);
+ SWIG_exit(1);
+ }
+ }
+ */
+
+ // char *& tests
+
+ for (i=0; i<count; i++) {
+ char **str = GetConstCharPointerRef();
+ if (strcmp(*str, CPLUSPLUS_MSG) != 0) {
+ fprintf(stderr, "Test char pointer ref get failed, iteration %d\n",i);
+ SWIG_exit(1);
+ }
+ }
+
+ for (i=0; i<count; i++) {
+ char *str = (char*) malloc(sizeof(char) * 256);
+ sprintf(str, "%s%d", OTHERLAND_MSG, i);
+ if (!SetConstCharPointerRef((char **) &str, i)) {
+ fprintf(stderr, "Test char pointer ref set failed, iteration %d\n", i);
+ SWIG_exit(1);
+ }
+ }
+
+ SWIG_exit(0);
+}
+
Modified: branches/gsoc2008-maciekd/Lib/c/c.swg
===================================================================
--- branches/gsoc2008-maciekd/Lib/c/c.swg 2008-08-19 07:43:48 UTC (rev 10795)
+++ branches/gsoc2008-maciekd/Lib/c/c.swg 2008-08-24 12:39:30 UTC (rev 10796)
@@ -31,6 +31,8 @@
%typemap(ctype) const short, const int, const long, const char, const float, const double "$1_type"
%typemap(ctype) const unsigned short, const unsigned int, const unsigned long, const unsigned char "$1_type"
%typemap(ctype) const void *, const short *, const int *, const long *, const char *, const float *, const double * "$1_type"
+%typemap(ctype) short *&, int *&, long *&, char *&, float *&, double *& "$1_basetype **"
+%typemap(ctype) const short *&, const int *&, const long *&, const char *&, const float *&, const double *& "$1_basetype **"
%typemap(ctype) short [ANY], int [ANY], long [ANY], char [ANY], float [ANY], double [ANY] "$1_basetype *"
%typemap(ctype) void * [ANY], short * [ANY], int * [ANY], long * [ANY], char * [ANY], float * [ANY], double * [ANY] "$1_basetype **"
%typemap(ctype) void [ANY][ANY], short [ANY][ANY], int [ANY][ANY], long [ANY][ANY], char [ANY][ANY], float [ANY][ANY], double [ANY][ANY] "$1_basetype **"
@@ -39,6 +41,7 @@
%typemap(ctype) SWIGTYPE & "SwigObj *"
%typemap(ctype) SWIGTYPE * [ANY], SWIGTYPE ** "SwigObj **"
%typemap(ctype) SWIGTYPE * [ANY][ANY], SWIGTYPE *** "SwigObj ***"
+%typemap(ctype) SWIGTYPE *& "SwigObj **"
%typemap(ctype) enum SWIGTYPE "$1_type"
%fragment("stdbool_inc", "proxy_header") {#include <stdbool.h>}
@@ -58,6 +61,9 @@
%typemap(in) const short &, const int &, const long &, const char &, const float &, const double & "$1 = ($1_basetype *) $input;"
%typemap(in) unsigned short &, unsigned int &, unsigned long &, unsigned char & "$1 = ($1_basetype *) $input;"
%typemap(in) const unsigned short &, const unsigned int &, const unsigned long &, const unsigned char & "$1 = ($1_basetype *) $input;"
+
+%typemap(in) short *&, int *&, long *&, char *&, float *&, double *& "$1 = ($1_ltype) $input;"
+%typemap(in) const short *&, const int *&, const long *&, const char *&, const float *&, const double *& "$1 = ($1_ltype) $input;"
%typemap(in) short [ANY], int [ANY], long [ANY], char [ANY], float [ANY], double [ANY] "$1 = ($1_basetype *) $input;"
%typemap(in) void * [ANY], short * [ANY], int * [ANY], long * [ANY], char * [ANY], float * [ANY], double * [ANY] "$1 = ($1_basetype *) $input;"
@@ -119,6 +125,13 @@
$1 = ($1_basetype *) 0;
}
+%typemap(in) SWIGTYPE *& {
+ if ($input)
+ $1 = ($1_basetype **) &(*$input)->obj;
+ else
+ $1 = ($1_basetype **) 0;
+}
+
// typemaps for return values
%typemap(couttype) void, short, int, long, char, float, double "$1_type"
@@ -127,6 +140,8 @@
%typemap(couttype) const void *, const short *, const int *, const long *, const char *, const float *, const double * "$1_type"
%typemap(couttype) short &, int &, long &, char &, float &, double & "$1_basetype *"
%typemap(couttype) const short &, const int &, const long &, const char &, const float &, const double & "$1_basetype const *"
+%typemap(couttype) short *&, int *&, long *&, char *&, float *&, double *& "$1_basetype **"
+%typemap(couttype) const short *&, const int *&, const long *&, const char *&, const float *&, const double *& "$1_basetype **"
%typemap(couttype) short [ANY], int [ANY], long [ANY], char [ANY], float [ANY], double [ANY] "$1_basetype *"
%typemap(couttype) SWIGTYPE "SwigObj *"
%typemap(couttype) SWIGTYPE * "SwigObj *"
@@ -149,6 +164,8 @@
%typemap(out) unsigned short &, unsigned int &, unsigned long &, unsigned char & "$result = $1;"
%typemap(out) const short &, const int &, const long &, const char &, const float &, const double & "$result = $1;"
%typemap(out) const unsigned short &, const unsigned int &, const unsigned long &, const unsigned char & "$result = $1;"
+%typemap(out) short *&, int *&, long *&, char *&, float *&, double *& "$result = $1;"
+%typemap(out) const short *&, const int *&, const long *&, const char *&, const float *&, const double *& "$result = $1;"
%typemap(out) short [ANY], int [ANY], long [ANY], char [ANY], float [ANY], double [ANY] "$result = $1;"
%typemap(out) void ""
@@ -202,6 +219,7 @@
$result = (SwigObj***) 0;
}
+
#ifdef SWIG_C_EXCEPT
%insert("runtime") %{
typedef struct {
Modified: branches/gsoc2008-maciekd/Source/Modules/c.cxx
===================================================================
--- branches/gsoc2008-maciekd/Source/Modules/c.cxx 2008-08-19 07:43:48 UTC (rev 10795)
+++ branches/gsoc2008-maciekd/Source/Modules/c.cxx 2008-08-24 12:39:30 UTC (rev 10796)
@@ -78,6 +78,9 @@
}
}
+ if (!CPlusPlus)
+ except_flag = false;
+
// add a symbol to the parser for conditional compilation
Preprocessor_define("SWIGC 1", 0);
Preprocessor_define("SWIG_C_RUNTME 1", 0);
@@ -256,8 +259,19 @@
SwigType *type = Getattr(n, "type");
if (SwigType_isenum(type))
type = make_enum_type(n, type);
- String *type_str = SwigType_str(type, 0);
- Printv(f_proxy_header, "SWIGIMPORT ", type_str, " ", name, ";\n\n", NIL);
+ String *type_str = Copy(SwigType_str(type, 0));
+ if (SwigType_isarray(type)) {
+ String *dims = Strchr(type_str, '[');
+ char *c = Char(type_str);
+ c[Len(type_str) - Len(dims) - 1] = '\0';
+ String *bare_type = NewStringf("%s", c);
+ //Printv(f_proxy_header, "SWIGIMPORT ", bare_type, " *", name, ";\n\n", NIL);
+ Printv(f_proxy_header, "SWIGIMPORT ", bare_type, " ", name, "[];\n\n", NIL);
+ Delete(bare_type);
+ }
+ else
+ Printv(f_proxy_header, "SWIGIMPORT ", type_str, " ", name, ";\n\n", NIL);
+ Delete(type_str);
return SWIG_OK;
}
@@ -452,6 +466,23 @@
gencomma = 1;
}
Printv(wrapper->def, return_type, " ", wname, "(", proto, ") {\n", NIL);
+
+ // attach 'check' typemaps
+ Swig_typemap_attach_parms("check", parms, wrapper);
+
+ // insert constraint checking
+ for (p = parms; p; ) {
+ if ((tm = Getattr(p, "tmap:check"))) {
+ Replaceall(tm, "$target", Getattr(p, "lname"));
+ Replaceall(tm, "$name", name);
+ Printv(wrapper->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:check:next");
+ }
+ else {
+ p = nextSibling(p);
+ }
+ }
+
Append(wrapper->code, prepend_feature(n));
if (!is_void_return) {
Printv(wrapper->code, return_type, " result;\n", NIL);
@@ -538,6 +569,9 @@
return_var_type = SwigType_base(type);
SwigType_add_pointer(return_var_type);
}
+ if (SwigType_ispointer(type)) {
+ SwigType_add_pointer(return_var_type);
+ }
SwigType_add_reference(type);
}
else if (SwigType_isarray(type)) {
@@ -562,6 +596,8 @@
else if (SwigType_isreference(type)) {
return_var_type = SwigType_base(type);
SwigType_add_pointer(return_var_type);
+ if (SwigType_ispointer(type))
+ SwigType_add_pointer(return_var_type);
}
else if (SwigType_isarray(type)) {
return_var_type = SwigType_base(type);
@@ -682,6 +718,19 @@
// emit variable for holding function return value
emit_return_variable(n, return_type, wrapper);
+ // insert constraint checking
+ for (p = parms; p; ) {
+ if ((tm = Getattr(p, "tmap:check"))) {
+ Replaceall(tm, "$target", Getattr(p, "lname"));
+ Replaceall(tm, "$name", name);
+ Printv(wrapper->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:check:next");
+ }
+ else {
+ p = nextSibling(p);
+ }
+ }
+
// emit action code
String *action = emit_action(n);
String *except = Getattr(n, "feature:except");
@@ -724,18 +773,6 @@
Append(wrapper->code, action);
}
- // insert constraint checking
- for (p = parms; p; ) {
- if ((tm = Getattr(p, "tmap:check"))) {
- Replaceall(tm, "$target", Getattr(p, "lname"));
- Printv(wrapper->code, tm, "\n", NIL);
- p = Getattr(p, "tmap:check:next");
- }
- else {
- p = nextSibling(p);
- }
- }
-
// insert cleanup code
for (p = parms; p; ) {
if ((tm = Getattr(p, "tmap:freearg"))) {
@@ -823,6 +860,24 @@
}
/* ---------------------------------------------------------------------
+ * emit_c_struct_def()
+ * --------------------------------------------------------------------- */
+
+ void emit_c_struct_def(Node *node) {
+ for ( ; node; node = nextSibling(node)) {
+ String* kind = Getattr(node, "kind");
+ if ((Cmp(kind, "variable") == 0) || (Cmp(kind, "function") == 0)) {
+ String* type = NewString("");
+ Printv(type, Getattr(node, "decl"), Getattr(node, "type"), NIL);
+ Printv(f_proxy_header, " ", SwigType_str(type, 0), " ", Getattr(node, "name"), ";\n", NIL);
+ Delete(type);
+ }
+ if (Cmp(nodeType(node), "extend") == 0)
+ emit_c_struct_def(firstChild(node));
+ }
+ }
+
+ /* ---------------------------------------------------------------------
* classHandler()
* --------------------------------------------------------------------- */
@@ -877,16 +932,8 @@
// this is C struct, just declare it in proxy
if (proxy_flag) {
Printv(f_proxy_header, "struct ", name, " {\n", NIL);
- Node* node;
- for (node = firstChild(n); node; node = nextSibling(node)) {
- String* kind = Getattr(node, "kind");
- if ((Cmp(kind, "variable") == 0) || (Cmp(kind, "function") == 0)) {
- String* type = NewString("");
- Printv(type, Getattr(node, "decl"), Getattr(node, "type"), NIL);
- Printv(f_proxy_header, " ", SwigType_str(type, 0), " ", Getattr(node, "name"), ";\n", NIL);
- Delete(type);
- }
- }
+ Node *node = firstChild(n);
+ emit_c_struct_def(node);
Append(f_proxy_header, "};\n\n");
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|