From 03aefbc6e95d094a6de231e1f5264c0946e209a3 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Thu, 18 Nov 2010 00:24:02 +0000 Subject: [PATCH] Added support for the D programming languge. It is still a bit rough around some edges, particularly with regard to multi-threading and operator overloading, and there are some documentation bits missing, but it should be fine for basic use. The test-suite should build and run fine with the current versions of DMD, LDC and Tango (at least) on Linux x86_64 and Mac OS X 10.6. git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@12299 626c5289-ae23-0410-ae9c-e8d60b6d4f22 --- Doc/Manual/D.html | 401 ++ Doc/Manual/Sections.html | 1 + Doc/Manual/chapters | 1 + Examples/Makefile.in | 89 +- Examples/d/callback/Makefile | 28 + Examples/d/callback/d1/runme.d | 36 + Examples/d/callback/d2/runme.d | 36 + Examples/d/callback/example.cxx | 4 + Examples/d/callback/example.h | 24 + Examples/d/callback/example.i | 13 + Examples/d/check.list | 9 + Examples/d/class/Makefile | 28 + Examples/d/class/d1/runme.d | 58 + Examples/d/class/d2/runme.d | 58 + Examples/d/class/example.cxx | 28 + Examples/d/class/example.h | 34 + Examples/d/class/example.i | 10 + Examples/d/constants/Makefile | 28 + Examples/d/constants/d1/runme.d | 28 + Examples/d/constants/d2/runme.d | 28 + Examples/d/constants/example.d | 23 + Examples/d/constants/example.i | 32 + Examples/d/enum/Makefile | 28 + Examples/d/enum/d1/runme.d | 28 + Examples/d/enum/d2/runme.d | 28 + Examples/d/enum/example.cxx | 37 + Examples/d/enum/example.h | 13 + Examples/d/enum/example.i | 11 + Examples/d/extend/Makefile | 28 + Examples/d/extend/d1/runme.d | 75 + Examples/d/extend/d2/runme.d | 75 + Examples/d/extend/example.cxx | 4 + Examples/d/extend/example.h | 56 + Examples/d/extend/example.i | 14 + Examples/d/funcptr/Makefile | 28 + Examples/d/funcptr/d1/runme.d | 34 + Examples/d/funcptr/d2/runme.d | 34 + Examples/d/funcptr/example.c | 19 + Examples/d/funcptr/example.h | 9 + Examples/d/funcptr/example.i | 16 + Examples/d/simple/Makefile | 28 + Examples/d/simple/d1/runme.d | 27 + Examples/d/simple/d2/runme.d | 27 + Examples/d/simple/example.c | 18 + Examples/d/simple/example.i | 7 + Examples/d/variables/Makefile | 28 + Examples/d/variables/d1/runme.d | 71 + Examples/d/variables/d2/runme.d | 71 + Examples/d/variables/example.c | 91 + Examples/d/variables/example.h | 6 + Examples/d/variables/example.i | 49 + Examples/test-suite/d/Makefile.in | 80 + Examples/test-suite/d/README | 7 + Examples/test-suite/d/aggregate_runme.1.d | 25 + Examples/test-suite/d/aggregate_runme.2.d | 25 + Examples/test-suite/d/allprotected_runme.1.d | 65 + Examples/test-suite/d/allprotected_runme.2.d | 65 + Examples/test-suite/d/apply_strings_runme.1.d | 12 + Examples/test-suite/d/apply_strings_runme.2.d | 12 + Examples/test-suite/d/bools_runme.1.d | 20 + Examples/test-suite/d/bools_runme.2.d | 20 + Examples/test-suite/d/catches_runme.1.d | 33 + Examples/test-suite/d/catches_runme.2.d | 33 + Examples/test-suite/d/char_strings_runme.1.d | 151 + Examples/test-suite/d/char_strings_runme.2.d | 123 + Examples/test-suite/d/constover_runme.1.d | 31 + Examples/test-suite/d/constover_runme.2.d | 16 + .../test-suite/d/d_nativepointers_runme.1.d | 23 + .../test-suite/d/d_nativepointers_runme.2.d | 23 + Examples/test-suite/d/default_args_runme.1.d | 127 + Examples/test-suite/d/default_args_runme.2.d | 84 + .../d/default_constructor_runme.1.d | 30 + .../d/default_constructor_runme.2.d | 25 + .../test-suite/d/director_basic_runme.1.d | 59 + .../test-suite/d/director_basic_runme.2.d | 46 + .../test-suite/d/director_classes_runme.1.d | 168 + .../test-suite/d/director_classes_runme.2.d | 169 + .../test-suite/d/director_classic_runme.1.d | 207 + .../test-suite/d/director_classic_runme.2.d | 202 + .../test-suite/d/director_ignore_runme.1.d | 39 + .../test-suite/d/director_ignore_runme.2.d | 38 + .../d/director_primitives_runme.1.d | 122 + .../d/director_primitives_runme.2.d | 123 + .../test-suite/d/director_protected_runme.1.d | 50 + .../test-suite/d/director_protected_runme.2.d | 36 + .../test-suite/d/director_string_runme.1.d | 46 + .../test-suite/d/director_string_runme.2.d | 42 + Examples/test-suite/d/enum_thorough_runme.1.d | 424 ++ Examples/test-suite/d/enum_thorough_runme.2.d | 425 ++ .../d/inherit_target_language_runme.1.d | 29 + .../d/inherit_target_language_runme.2.d | 29 + Examples/test-suite/d/li_attribute_runme.1.d | 75 + Examples/test-suite/d/li_attribute_runme.2.d | 58 + .../d/li_boost_shared_ptr_bits_runme.1.d | 21 + .../d/li_boost_shared_ptr_bits_runme.2.d | 19 + .../d/li_boost_shared_ptr_runme.1.d | 604 +++ .../d/li_boost_shared_ptr_runme.2.d | 602 +++ Examples/test-suite/d/li_std_except_runme.1.d | 40 + Examples/test-suite/d/li_std_except_runme.2.d | 34 + Examples/test-suite/d/li_std_string_runme.1.d | 97 + Examples/test-suite/d/li_std_string_runme.2.d | 86 + Examples/test-suite/d/li_std_vector_runme.1.d | 219 + Examples/test-suite/d/li_std_vector_runme.2.d | 207 + Examples/test-suite/d/li_typemaps_runme.1.d | 94 + Examples/test-suite/d/li_typemaps_runme.2.d | 91 + Examples/test-suite/d/long_long_runme.1.d | 35 + Examples/test-suite/d/long_long_runme.2.d | 32 + .../test-suite/d/member_pointer_runme.1.d | 43 + .../test-suite/d/member_pointer_runme.2.d | 42 + .../d/overload_complicated_runme.1.d | 50 + .../d/overload_complicated_runme.2.d | 34 + .../test-suite/d/overload_template_runme.1.d | 146 + .../test-suite/d/overload_template_runme.2.d | 80 + .../test-suite/d/pointer_reference_runme.1.d | 13 + .../test-suite/d/pointer_reference_runme.2.d | 14 + .../d/preproc_constants_c_runme.1.d | 63 + .../d/preproc_constants_c_runme.2.d | 63 + .../test-suite/d/preproc_constants_runme.1.d | 62 + .../test-suite/d/preproc_constants_runme.2.d | 62 + Examples/test-suite/d/sizet_runme.1.d | 15 + Examples/test-suite/d/sizet_runme.2.d | 14 + Examples/test-suite/d/sneaky1_runme.1.d | 21 + Examples/test-suite/d/sneaky1_runme.2.d | 11 + .../d/special_variable_macros_runme.1.d | 39 + .../d/special_variable_macros_runme.2.d | 21 + Examples/test-suite/d/threads_runme.1.d | 70 + Examples/test-suite/d/threads_runme.2.d | 55 + .../test-suite/d/throw_exception_runme.1.d | 30 + .../test-suite/d/throw_exception_runme.2.d | 30 + .../test-suite/d/typemap_namespace_runme.1.d | 13 + .../test-suite/d/typemap_namespace_runme.2.d | 9 + .../d/typemap_out_optimal_runme.1.d | 9 + .../d/typemap_out_optimal_runme.2.d | 9 + Examples/test-suite/d/varargs_runme.1.d | 20 + Examples/test-suite/d/varargs_runme.2.d | 13 + Examples/test-suite/d/virtual_poly_runme.1.d | 27 + Examples/test-suite/d/virtual_poly_runme.2.d | 22 + Examples/test-suite/d_nativepointers.i | 18 + Lib/allkw.swg | 1 + Lib/d/boost_shared_ptr.i | 201 + Lib/d/carrays.i | 111 + Lib/d/cpointer.i | 171 + Lib/d/d.swg | 46 + Lib/d/dclassgen.swg | 172 + Lib/d/ddirectives.swg | 11 + Lib/d/denums.swg | 60 + Lib/d/dexception.swg | 30 + Lib/d/dhead.swg | 310 ++ Lib/d/director.swg | 46 + Lib/d/dkw.swg | 126 + Lib/d/dmemberfunctionpointers.swg | 92 + Lib/d/doperators.swg | 77 + Lib/d/dprimitives.swg | 158 + Lib/d/dstrings.swg | 80 + Lib/d/dswigtype.swg | 177 + Lib/d/dvoid.swg | 18 + Lib/d/std_common.i | 5 + Lib/d/std_deque.i | 1 + Lib/d/std_except.i | 30 + Lib/d/std_map.i | 59 + Lib/d/std_pair.i | 34 + Lib/d/std_shared_ptr.i | 2 + Lib/d/std_string.i | 98 + Lib/d/std_vector.i | 591 +++ Lib/d/stl.i | 12 + Lib/d/typemaps.i | 298 ++ Lib/d/wrapperloader.swg | 303 ++ Lib/exception.i | 36 +- Lib/std_except.i | 2 +- Lib/swig.swg | 4 +- Makefile.in | 17 +- Source/Include/swigwarn.h | 21 +- Source/Makefile.am | 1 + Source/Modules/d.cxx | 4359 +++++++++++++++++ Source/Modules/swigmain.cxx | 2 + configure.in | 43 + 176 files changed, 16449 insertions(+), 29 deletions(-) create mode 100644 Doc/Manual/D.html create mode 100644 Examples/d/callback/Makefile create mode 100644 Examples/d/callback/d1/runme.d create mode 100644 Examples/d/callback/d2/runme.d create mode 100644 Examples/d/callback/example.cxx create mode 100644 Examples/d/callback/example.h create mode 100644 Examples/d/callback/example.i create mode 100644 Examples/d/check.list create mode 100644 Examples/d/class/Makefile create mode 100644 Examples/d/class/d1/runme.d create mode 100644 Examples/d/class/d2/runme.d create mode 100644 Examples/d/class/example.cxx create mode 100644 Examples/d/class/example.h create mode 100644 Examples/d/class/example.i create mode 100644 Examples/d/constants/Makefile create mode 100644 Examples/d/constants/d1/runme.d create mode 100644 Examples/d/constants/d2/runme.d create mode 100644 Examples/d/constants/example.d create mode 100644 Examples/d/constants/example.i create mode 100644 Examples/d/enum/Makefile create mode 100644 Examples/d/enum/d1/runme.d create mode 100644 Examples/d/enum/d2/runme.d create mode 100644 Examples/d/enum/example.cxx create mode 100644 Examples/d/enum/example.h create mode 100644 Examples/d/enum/example.i create mode 100644 Examples/d/extend/Makefile create mode 100644 Examples/d/extend/d1/runme.d create mode 100644 Examples/d/extend/d2/runme.d create mode 100644 Examples/d/extend/example.cxx create mode 100644 Examples/d/extend/example.h create mode 100644 Examples/d/extend/example.i create mode 100644 Examples/d/funcptr/Makefile create mode 100644 Examples/d/funcptr/d1/runme.d create mode 100644 Examples/d/funcptr/d2/runme.d create mode 100644 Examples/d/funcptr/example.c create mode 100644 Examples/d/funcptr/example.h create mode 100644 Examples/d/funcptr/example.i create mode 100644 Examples/d/simple/Makefile create mode 100644 Examples/d/simple/d1/runme.d create mode 100644 Examples/d/simple/d2/runme.d create mode 100644 Examples/d/simple/example.c create mode 100644 Examples/d/simple/example.i create mode 100644 Examples/d/variables/Makefile create mode 100644 Examples/d/variables/d1/runme.d create mode 100644 Examples/d/variables/d2/runme.d create mode 100644 Examples/d/variables/example.c create mode 100644 Examples/d/variables/example.h create mode 100644 Examples/d/variables/example.i create mode 100644 Examples/test-suite/d/Makefile.in create mode 100644 Examples/test-suite/d/README create mode 100644 Examples/test-suite/d/aggregate_runme.1.d create mode 100644 Examples/test-suite/d/aggregate_runme.2.d create mode 100644 Examples/test-suite/d/allprotected_runme.1.d create mode 100644 Examples/test-suite/d/allprotected_runme.2.d create mode 100644 Examples/test-suite/d/apply_strings_runme.1.d create mode 100644 Examples/test-suite/d/apply_strings_runme.2.d create mode 100644 Examples/test-suite/d/bools_runme.1.d create mode 100644 Examples/test-suite/d/bools_runme.2.d create mode 100644 Examples/test-suite/d/catches_runme.1.d create mode 100644 Examples/test-suite/d/catches_runme.2.d create mode 100644 Examples/test-suite/d/char_strings_runme.1.d create mode 100644 Examples/test-suite/d/char_strings_runme.2.d create mode 100644 Examples/test-suite/d/constover_runme.1.d create mode 100644 Examples/test-suite/d/constover_runme.2.d create mode 100644 Examples/test-suite/d/d_nativepointers_runme.1.d create mode 100644 Examples/test-suite/d/d_nativepointers_runme.2.d create mode 100644 Examples/test-suite/d/default_args_runme.1.d create mode 100644 Examples/test-suite/d/default_args_runme.2.d create mode 100644 Examples/test-suite/d/default_constructor_runme.1.d create mode 100644 Examples/test-suite/d/default_constructor_runme.2.d create mode 100644 Examples/test-suite/d/director_basic_runme.1.d create mode 100644 Examples/test-suite/d/director_basic_runme.2.d create mode 100644 Examples/test-suite/d/director_classes_runme.1.d create mode 100644 Examples/test-suite/d/director_classes_runme.2.d create mode 100644 Examples/test-suite/d/director_classic_runme.1.d create mode 100644 Examples/test-suite/d/director_classic_runme.2.d create mode 100644 Examples/test-suite/d/director_ignore_runme.1.d create mode 100644 Examples/test-suite/d/director_ignore_runme.2.d create mode 100644 Examples/test-suite/d/director_primitives_runme.1.d create mode 100644 Examples/test-suite/d/director_primitives_runme.2.d create mode 100644 Examples/test-suite/d/director_protected_runme.1.d create mode 100644 Examples/test-suite/d/director_protected_runme.2.d create mode 100644 Examples/test-suite/d/director_string_runme.1.d create mode 100644 Examples/test-suite/d/director_string_runme.2.d create mode 100644 Examples/test-suite/d/enum_thorough_runme.1.d create mode 100644 Examples/test-suite/d/enum_thorough_runme.2.d create mode 100644 Examples/test-suite/d/inherit_target_language_runme.1.d create mode 100644 Examples/test-suite/d/inherit_target_language_runme.2.d create mode 100644 Examples/test-suite/d/li_attribute_runme.1.d create mode 100644 Examples/test-suite/d/li_attribute_runme.2.d create mode 100644 Examples/test-suite/d/li_boost_shared_ptr_bits_runme.1.d create mode 100644 Examples/test-suite/d/li_boost_shared_ptr_bits_runme.2.d create mode 100644 Examples/test-suite/d/li_boost_shared_ptr_runme.1.d create mode 100644 Examples/test-suite/d/li_boost_shared_ptr_runme.2.d create mode 100644 Examples/test-suite/d/li_std_except_runme.1.d create mode 100644 Examples/test-suite/d/li_std_except_runme.2.d create mode 100644 Examples/test-suite/d/li_std_string_runme.1.d create mode 100644 Examples/test-suite/d/li_std_string_runme.2.d create mode 100644 Examples/test-suite/d/li_std_vector_runme.1.d create mode 100644 Examples/test-suite/d/li_std_vector_runme.2.d create mode 100644 Examples/test-suite/d/li_typemaps_runme.1.d create mode 100644 Examples/test-suite/d/li_typemaps_runme.2.d create mode 100644 Examples/test-suite/d/long_long_runme.1.d create mode 100644 Examples/test-suite/d/long_long_runme.2.d create mode 100644 Examples/test-suite/d/member_pointer_runme.1.d create mode 100644 Examples/test-suite/d/member_pointer_runme.2.d create mode 100644 Examples/test-suite/d/overload_complicated_runme.1.d create mode 100644 Examples/test-suite/d/overload_complicated_runme.2.d create mode 100644 Examples/test-suite/d/overload_template_runme.1.d create mode 100644 Examples/test-suite/d/overload_template_runme.2.d create mode 100644 Examples/test-suite/d/pointer_reference_runme.1.d create mode 100644 Examples/test-suite/d/pointer_reference_runme.2.d create mode 100644 Examples/test-suite/d/preproc_constants_c_runme.1.d create mode 100644 Examples/test-suite/d/preproc_constants_c_runme.2.d create mode 100644 Examples/test-suite/d/preproc_constants_runme.1.d create mode 100644 Examples/test-suite/d/preproc_constants_runme.2.d create mode 100644 Examples/test-suite/d/sizet_runme.1.d create mode 100644 Examples/test-suite/d/sizet_runme.2.d create mode 100644 Examples/test-suite/d/sneaky1_runme.1.d create mode 100644 Examples/test-suite/d/sneaky1_runme.2.d create mode 100644 Examples/test-suite/d/special_variable_macros_runme.1.d create mode 100644 Examples/test-suite/d/special_variable_macros_runme.2.d create mode 100644 Examples/test-suite/d/threads_runme.1.d create mode 100644 Examples/test-suite/d/threads_runme.2.d create mode 100644 Examples/test-suite/d/throw_exception_runme.1.d create mode 100644 Examples/test-suite/d/throw_exception_runme.2.d create mode 100644 Examples/test-suite/d/typemap_namespace_runme.1.d create mode 100644 Examples/test-suite/d/typemap_namespace_runme.2.d create mode 100644 Examples/test-suite/d/typemap_out_optimal_runme.1.d create mode 100644 Examples/test-suite/d/typemap_out_optimal_runme.2.d create mode 100644 Examples/test-suite/d/varargs_runme.1.d create mode 100644 Examples/test-suite/d/varargs_runme.2.d create mode 100644 Examples/test-suite/d/virtual_poly_runme.1.d create mode 100644 Examples/test-suite/d/virtual_poly_runme.2.d create mode 100644 Examples/test-suite/d_nativepointers.i create mode 100644 Lib/d/boost_shared_ptr.i create mode 100644 Lib/d/carrays.i create mode 100644 Lib/d/cpointer.i create mode 100644 Lib/d/d.swg create mode 100644 Lib/d/dclassgen.swg create mode 100644 Lib/d/ddirectives.swg create mode 100644 Lib/d/denums.swg create mode 100644 Lib/d/dexception.swg create mode 100644 Lib/d/dhead.swg create mode 100644 Lib/d/director.swg create mode 100644 Lib/d/dkw.swg create mode 100644 Lib/d/dmemberfunctionpointers.swg create mode 100644 Lib/d/doperators.swg create mode 100644 Lib/d/dprimitives.swg create mode 100644 Lib/d/dstrings.swg create mode 100644 Lib/d/dswigtype.swg create mode 100644 Lib/d/dvoid.swg create mode 100644 Lib/d/std_common.i create mode 100644 Lib/d/std_deque.i create mode 100644 Lib/d/std_except.i create mode 100644 Lib/d/std_map.i create mode 100644 Lib/d/std_pair.i create mode 100644 Lib/d/std_shared_ptr.i create mode 100644 Lib/d/std_string.i create mode 100644 Lib/d/std_vector.i create mode 100644 Lib/d/stl.i create mode 100644 Lib/d/typemaps.i create mode 100644 Lib/d/wrapperloader.swg create mode 100644 Source/Modules/d.cxx diff --git a/Doc/Manual/D.html b/Doc/Manual/D.html new file mode 100644 index 000000000..2b563788f --- /dev/null +++ b/Doc/Manual/D.html @@ -0,0 +1,401 @@ + + + +SWIG and D + + + + +

20 SWIG and D

+ +
+ +
+ + + + +

20.1 Introduction

+ + +

From the D Programming Language web site: »D is a systems programming language. Its focus is on combining the power and high performance of C and C++ with the programmer productivity of modern languages like Ruby and Python. […] The D language is statically typed and compiles directly to machine code.« As such, it is not very surprising that D is able to directly interface with C libraries. Why would a SWIG module for D be needed then in the first place?

+ +

Well, besides the obvious downside that the C header files have to be manually converted to D modules for this to work, there is one major inconvenience with this approach: D code usually is on a higher abstraction level than C, and many of the features that make D interesting are simply not available when dealing with C libraries, requiring you e.g. to manually convert strings between pointers to \0-terminated char arrays and D char arrays, making the algorithms from the D2 standard library unusable with C arrays and data structures, and so on.

+ +

While these issues can be worked around relatively easy by hand-coding a thin wrapper layer around the C library in question, there is another issue where writing wrapper code per hand is not feasible: C++ libraries. D did not support interfacing to C++ in version 1 at all, and even if extern(C++) has been added to D2, the support is still very limited, and a custom wrapper layer is still required in many cases.

+ +

To help addressing these issues, the SWIG C# module has been forked to support D. Is has evolved quite a lot since then, but there are still many similarities, so if you do not find what you are looking for on this page, it might be worth having a look at the chapter on C# (and also on Java, since the C# module was in turn forked from it).

+ + +

20.2 Command line invocation

+ + +

To activate the D module, pass the -d option to SWIG at the command line. The same standard command line switches as with any other language module are available, plus the following D specific ones:

+ +
+
-splitproxy
+
+

By default, SWIG generates two D modules: the proxy module, named like the source module (either specified via the %module directive or via the module command line switch), which contains all the proxy classes, functions, enums, etc., and the wrap module (named like the proxy module, but suffixed with _wrap), which contains all the extern(C) function declarations and other private parts only used internally by the proxy module.

+

If the split proxy mode is enabled by passing this switch at the command line, all proxy classes and enums are emitted to their own D module instead. The main proxy module only contains free functions and constants in this case.

+
+ +
-package <pkg>
+
+

By default, the proxy D modules and the wrap D module are written to the root package. Using this option, you can specify another target package instead.

+
+ +
-wrapperlibrary <wl>
+
+

The code SWIG generates to dynamically load the C/C++ wrapper layer looks for a library called $module_wrap, just like the wrap D module is. With this switch, you can override the name of the file the wrapper code loads at runtime (the lib prefix and the suffix for shared libraries are appended automatically, depending on the OS).

+

This might especially be useful if you want to invoke SWIG several times on separate modules, but compile the resulting code into a single shared library.

+
+
+ + +

20.3 Typemaps

+ + +

20.3.1 C# <-> D name comparison

+ + +
+ ctype                  <->  cwtype
+ imtype                 <->  dwtype
+ cstype                 <->  dptype
+ csin                   <->  din
+ csout                  <->  dout
+ csdirectorin           <->  ddirectorin
+ csdirectorout          <->  ddirectorout
+ csinterfaces           <->  dinterfaces
+ csinterfaces_derived   <->  dinterfaces_derived
+ csbase                 <->  dbase
+ csclassmodifiers       <->  dclassmodifiers
+ cscode                 <->  dcode
+ csimports              <->  dimports
+ csbody                 <->  dbody
+ csfinalize             <->  ddestructor
+ csdestruct             <->  ddispose
+ csdestruct_derived     <->  ddispose_derived
+
+ + +

20.3.2 cwtype, dwtype, dptype

+ + +

Mapping of types between the C/C++ library, the C/C++ library wrapper exposing the C functions, the D wrapper module importing these functions and the D proxy code.

+ +

The cwtype typemap is used to determine the types to use in the C wrapper functions. The types from the dwtype typemap are used in the extern(C) declarations of these functions in the D wrap module. The dptype typemap contains the D types used in the D proxy module/class.

+ + +

20.3.3 in, out, directorin, directorout

+ + +

Used for converting between the types for C/C++ and D when generating the code for the wrapper functions (on the C++ side).

+ +

The code from the in typemap is used to convert arguments to the C wrapper function to the type used in the wrapped code (cwtype->original C++ type), the out typemap is utilized to convert values from the wrapped code to wrapper function return types (original C++ type->cwtype).

+ +

The directorin typemap is used to convert parameters to the type used in the D director callback function, its return value is processed by directorout (see below).

+ + +

20.3.4 din, dout, ddirectorin, ddirectorout

+ + +

Typemaps for code generation in D proxy and type wrapper classes.

+ +

The din typemap is used for converting function parameter types from the type used in the proxy module or class to the type used in the D wrap module (the $dinput macro is replaced).

+ +

The dout typemap is used for converting function return values from the return type used in the wrap D module to the type returned by the proxy function. The $excode special variable in dout typemaps is replaced by the excode typemap attribute code if the method can throw any exceptions from unmanaged code, otherwise by nothing (the $wcall and $owner macros are replaced).

+ +

The code from the ddirectorin and ddirectorout typemaps is used for conversion in director callback functions. Arguments are converted to the type used in the proxy class method they are calling by using the code from ddirectorin, the proxy class method return value is converted to the type the C++ code expects via the ddirectorout typemap (the $dpcall and $winput macros are replaced).

+ +

The full chain of type conversions when a director callback is invoked looks like this:

+ +
      type CPPClass::method(type a)
+        ↑                     ↓
+   <directorout>         <directorin>
+        ↑                     ↓
+     cwtype methodCallback(cwtype a)    C++
+ ::::::::::::::::::::::::::::::::::::::::::
+     dwtype methodCallback(dwtype a)    D
+        ↑                     ↓
+  <ddirectorout>       <ddirectorin>
+        ↑                     ↓
+      dptype DClass.method(dptype a)
+ + +

20.3.5 typecheck typemaps

+ + +

Because, unlike many scripting languages supported by SWIG, D does not need any dynamic dispatch helper to access an overloaded function, the purpose of these is merely to issue a warning for overloaded C++ functions that cannot be overloaded in D (as more than one C++ type maps to a single D type).

+ + +

20.3.6 Code injection typemaps

+ + +

These typemaps are used for generating the skeleton of proxy classes for C++ types.

+ +

By overriding dbase, dinterfaces or dinterfaces_derived, the inheritance chain of the generated proxy class for a type can be modified. dclassmodifiers allows you to add any custom modifiers around the class keyword.

+ +

Using dcode and dimports, you can specify additional D code which will be emitted into the class body respectively the imports section of the D module the class is written to.

+ +

dconstructor, ddestructor, ddispose and ddispose_derived are used to generate the class constructor, destructor and dispose() method, respectively. The auxiliary code for handling the pointer to the C++ object is stored in dbody and dbody_derived. You can override them for specific types.

+ + +

20.3.7 Special variable macros

+ + +

The standard SWIG special variables are available for use within typemaps as described in the Typemaps documentation, for example $1, $input, $result etc.

+ +

When generating D wrappers, a few additional macros are available:

+
+
$dclassname (C#: $csclassname)
+
+

This special variable works similar to $n_type in that it returns the name of a type – it expands to the D proxy class name of the type being wrapped. If the type does not have an associated proxy class, it expands to the type wrapper class name, for example, SWIGTYPE_p_p_SomeCppClass is generated when wrapping SomeCppClass **.

+

There are two other variants available, $&dclassname and $*dclassname. The former adds a level of indirection, while the latter removes one. For instance, when wrapping Foo **, $*dclassname would be replaced by the proxy class name corresponding to Foo *.

+
+ +
$null
+

In code inserted into the generated C/C++ wrapper functions, this variable is replaced by either 0 or nothing at all, depending on whether the function has a return value or not. It can be used to bail out early e.g. in case of errors (return $null;).

+ +
$dinput (C#: $csinput)
+
+

This variable is used in din typemaps and is replaced by the expression which is to be passed to C/C++.

+

For example, this input

+
+%typemap(din) SomeClass * "SomeClass.getCPointer($dinput)"
+
+%inline %{
+  class SomeClass {};
+  void foo(SomeClass *arg);
+%}
+

leads to the following D proxy code being generated:

+
+void foo(SomeClass arg) {
+  example_wrap.foo(SomeClass.getCPointer(arg));
+}
+ +
$wcall and $owner (C#: $imcall)
+
+

These variables are used in dout typemaps. $wcall contains the call to the wrapper layer which provides the value to be used, and $owner signals if the caller is responsible for managing the object lifetime (that is, if the called method is a constructor or has been marked via %newobject).

+

Consider the following example:

+
+%typemap(dout) SomeClass * {
+  return new SomeClass($wcall, $owner);
+}
+
+%inline %{
+  class SomeClass;
+  SomeClass *foo();
+
+  %newobject bar();
+  SomeClass *bar();
+%}
+

The code generated for foo() and bar() looks like this:

+
+SomeClass foo() {
+  return new SomeClass(example_wrap.foo(), false);
+}
+
+SomeClass bar() {
+  return new SomeClass(example_wrap.bar(), true);
+}
+
+
+ +
$dpcall and $winput (C#: $cscall, $iminput)
+

These variables are used in the director-specific typemaps ddirectorin and ddirectorout. They are more or less the reverse of the $wcall and $dinput macros: $dpcall contains the invocation of the D proxy method of which the return value is to be passed back to C++, $winput contains the parameter value from C++.

+ +
$excode
+

This variable is used in dout and dconstructor typemaps and is filled with the contents of the excode typemap attribute if an exception could be thrown from the C++ side. See the C# documentation for details.

+ +
$dbaseclass
+

Currently for internal use only, it contains the D name of the C++ base class (if any) inside proxy classes.

+ +
$directorconnect
+
+

This macro is only valid inside the dconstructor typemap and contains the value of the dconstructor typemap attribute if the currently wrapped class has directors enabled.

+

This is how the default dconstructor typemap looks like (you usually do not want to specify a custom one):

+
+%typemap(dconstructor, excode=SWIGEXCODE,directorconnect="\n  swigDirectorConnect();") SWIGTYPE {
+  this($wcall, true);$excode$directorconnect
+}
+
+
+ +
$importtype(SomeDType)
+
+

This macro is used in the dimports typemap if a dependency on another D type generated by SWIG is added by a custom typemap.

+

Consider the following code snippet:

+
+%typemap(dinterfaces) SomeClass "AnInterface, AnotherInterface";
+
+

This causes SWIG to add AnInterface and AnotherInterface to the base class list of SomeClass:

+
+class SomeClass : AnInterface, AnotherInterface {
+  …
+}
+
+

For this to work, AnInterface and AnotherInterface have to be in scope. If SWIG is not in split proxy mode, this is already the case, but it it is, they have to be added to the import list via the dimports typemap. Additionally, the import statement depends on the package SWIG is configured to emit the modules to.

+

The $importtype macro helps you to elegantly solve this problem:

+
+%typemap(dimports) RemoteMpe %{
+$importtype(AnInterface)
+$importtype(AnotherInterface)
+%}
+
+

If SWIG is in split proxy mode, it expands to an import statement for the specified type, to nothing if not.

+
+ +
$module
+

Expands to the name of the main proxy D module.

+ +
$wrapdmodule
+

Contains the fully qualified name of the wrap D module.

+
+ + +

20.4 %features

+ + +

The D module defines a number of directives which modify the SWIG features set globally or for a specific declaration:

+ + +
+
%dnativeconst and %dconstvalue(value)
+
+

Out of the box, SWIG generates accessor methods for C #defines and C++ constants. The %dnativeconst directive enables wrapping these constants as D manifest constants (const in D1, enum in D2).

+

For this to work, the C/C++ code for the constant value must directly compile as D code, though. If this is not the case, you can manually override the expression written to the D wrapper using the %dconstvalue directive, passing the new value as parameter.

+

For enums, again %dconstvalue can be used to override the value of an enum item if the initializer should not compile in D.

+
+ +
%dmethodmodifiers
+
+

This directive can be used to override the modifiers for a proxy function. For instance, you could make a public C++ member function private in D like this:

+
+%dmethodmodifiers A::foo "private";
+
+%inline %{
+struct A {
+  void foo();
+};
+%}
+
+
+
+ + +

20.5 Pragmas

+ + +

There are a few SWIG pragmas specific to the D module, which you can use to influence the D code SWIG generates:

+ +
+
%pragma(d) wrapdmodulecode
+

The passed text (D code) is copied verbatim to the wrap D module. For example, it can be (and is, internally) used to emit additional private helper code for the use by proxy typemaps.

+ +
%pragma(d) wrapdmoduleimports
+

Additional code to be emitted to the imports section of the wrap D module (the $importtype macro can be used here). You probably want to use this in conjunction with the wrapdmodulecode pragma.

+ +
%pragma(d) proxydmodulecode
+

Just like proxydmodulecode, the argument is copied to the proxy D module (if SWIG is in split proxy mode, it is emitted to the main proxy D module only).

+ +
%pragma(d) globalproxyimports
+
+

The D module currently does not support specifying dependencies on external modules (e.g. from the standard library) for the D typemaps. To add the import statements to the proxy modules (resp. to all proxy modules if in split proxy mode), you can use the globalproxyimports directive.

+

For example:

+
+%typemap(din) char[] "($dinput ? tango.stdc.stringz.toStringz($dinput) : null)"
+%pragma(d) globalproxyimports = "static import tango.stdc.stringz;";
+
+
+ +
%pragma(d) wrapperloadercode
+
+

The D code for loading the wrapper library (it is copied to the wrap D module). The $wrapperloaderbindcode variable is replaced by the list of commands for binding the functions from the wrapper library to the symbols in the wrap D module.

+

Each time this pragma is specified, the previous value is overwritten.

+
+ +
%pragma(d) wrapperloaderbindcommand
+
+

The D command to use for binding the wrapper functions from the C/C++ library to the symbols in the wrap D module. The $function variable contains the name of the D function in the wrap module, the $symbol variable is replaced by the name of the symbol in the library.

+

Each time this pragma is specified, the previous value is overwritten.

+
+
+ + +

20.6 D Exceptions

+ + +

Out of the box, C++ exceptions are fundamentally incompatible to their equivalent in the D world and cannot simply be propagated to a calling D method. There is, however, an easy way to solve this problem: Just catch the exception in the C/C++ wrapper layer, pass the contents to D, and make the wrapper code rethrow the exception in the D world.

+ +

The implementation details of this are a bit crude, but the SWIG D module automatically takes care of this, as long as it is able to detect that an exception could potentially be thrown (e.g. because the C++ method has a throw(…) exception specification).

+ +

As this feature is implemented in exactly the same way it is for C#, please see the C# documentation for a more detailed explanation.

+ + +

20.7 D Directors

+ + +

When the directors feature is activated, SWIG generates extra code on both the C++ and the D side to enable cross-language polymorphism. Essentially, this means that if you subclass a proxy class in D, C++ code can access any overridden virtual methods just as if you created a derived class in C++.

+ +

There is no D specific documentation yet, but the way the feature is implemented is very similar to how it is done in Java and C#. +

+ + +

20.8 Other features

+ + +

The nspace feature of SWIG is not yet supported for D – all class modules are written to the same package, regardless of which C++ namespace they are in.

+ +

Support of pointers to primitive types.

+ + +

20.9 D Typemap examples

+ + +

There are no D-specific typemap examples yet. However, with the above name comparison table, you should be able to get an idea what can be done by looking at the corresponding C# section.

+ + + +

20.10 Work in progress and planned features

+ + +

There are a couple of features which are not implemented yet, but would be very useful and might be added in the near future:

+ + + +

Some generated code might also be a bit rough around the edges, particularly in the following areas:

+ + + + + + + diff --git a/Doc/Manual/Sections.html b/Doc/Manual/Sections.html index 855244790..a44571992 100644 --- a/Doc/Manual/Sections.html +++ b/Doc/Manual/Sections.html @@ -52,6 +52,7 @@ Last update : SWIG-2.0.2 (in progress)
  • R support
  • Ruby support
  • Tcl support
  • +
  • D support
  • Developer Documentation

    diff --git a/Doc/Manual/chapters b/Doc/Manual/chapters index e918e234a..924c8cfde 100644 --- a/Doc/Manual/chapters +++ b/Doc/Manual/chapters @@ -17,6 +17,7 @@ CCache.html Allegrocl.html CSharp.html Chicken.html +D.html Go.html Guile.html Java.html diff --git a/Examples/Makefile.in b/Examples/Makefile.in index 582c75f29..5d5590311 100644 --- a/Examples/Makefile.in +++ b/Examples/Makefile.in @@ -69,7 +69,7 @@ IOBJS = $(IWRAP:.i=.@OBJEXT@) CPP_DLLIBS = #-L/usr/local/lib/gcc-lib/sparc-sun-solaris2.5.1/2.7.2 \ -L/usr/local/lib -lg++ -lstdc++ -lgcc -# Solaris workshop 5.0 +# Solaris workshop 5.0 # CPP_DLLIBS = -L/opt/SUNWspro/lib -lCrun # Symbols used for using shared libraries @@ -159,7 +159,7 @@ tcl_cpp: $(SRCS) # ----------------------------------------------------------------- tcl_clean: - rm -f *_wrap* *~ .~* mytclsh@EXEEXT@ + rm -f *_wrap* *~ .~* mytclsh@EXEEXT@ rm -f core @EXTRA_CLEAN@ rm -f *.@OBJEXT@ *@SO@ @@ -296,9 +296,9 @@ python_static_cpp: $(SRCS) $(CXX) $(CFLAGS) $(ICXXSRCS) $(SRCS) $(CXXSRCS) $(INCLUDES) \ $(PYTHON_INCLUDE) $(LIBS) -L$(PYTHON_LIB) $(PYTHON_LIBOPTS) -o $(TARGET) -# ----------------------------------------------------------------- +# ----------------------------------------------------------------- # Running a Python example -# ----------------------------------------------------------------- +# ----------------------------------------------------------------- ifeq (,$(PY3)) PYSCRIPT = runme.py @@ -313,7 +313,7 @@ python_run: $(PYSCRIPT) runme3.py: runme.py cp $< $@ - $(PY2TO3) -w $@ >/dev/null 2>&1 + $(PY2TO3) -w $@ >/dev/null 2>&1 # ----------------------------------------------------------------- # Cleaning the python examples @@ -332,7 +332,7 @@ python_clean: # Make sure these locate your Octave installation OCTAVE_INCLUDE= $(DEFS) @OCTAVEEXT@ -OCTAVE_LIB = +OCTAVE_LIB = # Extra Octave specific dynamic linking options OCTAVE_DLNK = @OCTAVEDYNAMICLINKING@ @@ -548,14 +548,14 @@ mzscheme: $(SRCS) mzscheme_cpp: $(SRCS) $(SWIG) -mzscheme -c++ $(SWIGOPT) $(INTERFACEPATH) $(COMPILETOOL) $(MZC) `echo $(INCLUDES) | sed 's/-I/++ccf -I/g'` --cc $(ICXXSRCS) $(SRCS) $(CXXSRCS) - $(CXXSHARED) $(CFLAGS) -o $(LIBPREFIX)$(TARGET)$(MZSCHEME_SO) $(OBJS) $(IOBJS) $(MZDYNOBJ) $(CPP_DLLIBS) + $(CXXSHARED) $(CFLAGS) -o $(LIBPREFIX)$(TARGET)$(MZSCHEME_SO) $(OBJS) $(IOBJS) $(MZDYNOBJ) $(CPP_DLLIBS) # ----------------------------------------------------------------- # Cleaning the mzscheme examples # ----------------------------------------------------------------- mzscheme_clean: - rm -f *_wrap* *~ .~* + rm -f *_wrap* *~ .~* rm -f core @EXTRA_CLEAN@ rm -f *.@OBJEXT@ *@SO@ @@ -643,7 +643,7 @@ ocaml_static_cpp: $(SRCS) $(INTERFACE:%.i=%.cmo) \ $(PROGFILE:%.ml=%.cmo) \ $(INTERFACE:%.i=%_wrap.@OBJEXT@) $(OBJS) \ - -cclib "$(LIBS)" -cc '$(CXX)' + -cclib "$(LIBS)" -cc '$(CXX)' ocaml_static_cpp_toplevel: $(SRCS) $(OCAMLCORE) @@ -661,7 +661,7 @@ ocaml_static_cpp_toplevel: $(SRCS) -g -ccopt -g -cclib -g -custom -o $(TARGET)_top \ $(INTERFACE:%.i=%.cmo) \ $(INTERFACE:%.i=%_wrap.@OBJEXT@) $(OBJS) \ - -cclib "$(LIBS)" -cc '$(CXX)' + -cclib "$(LIBS)" -cc '$(CXX)' ocaml_dynamic_cpp: $(SRCS) $(OCAMLCORE) @@ -844,7 +844,7 @@ pike_cpp_static: $(SRCS) # ----------------------------------------------------------------- pike_clean: - rm -f *_wrap* *~ .~* mypike@EXEEXT@ + rm -f *_wrap* *~ .~* mypike@EXEEXT@ rm -f core @EXTRA_CLEAN@ rm -f *.@OBJEXT@ *@SO@ @@ -861,7 +861,7 @@ CHICKEN_CFLAGS = @CHICKENOPTS@ CHICKENOPTS = -quiet CHICKEN_MAIN = -# SWIG produces $(ISRCS) (the C wrapper file) +# SWIG produces $(ISRCS) (the C wrapper file) # and $(CHICKEN_GENERATED_SCHEME) (the Scheme wrapper file): CHICKEN_GENERATED_SCHEME = $(INTERFACE:.i=.scm) CHICKEN_COMPILED_SCHEME = $(INTERFACE:.i=_chicken.c) @@ -1053,12 +1053,12 @@ lua_clean: allegrocl: $(SRCS) $(SWIG) -allegrocl -cwrap $(SWIGOPT) $(INTERFACEPATH) - $(CC) -c $(CCSHARED) $(CFLAGS) $(ISRCS) $(INCLUDES) $(SRCS) + $(CC) -c $(CCSHARED) $(CFLAGS) $(ISRCS) $(INCLUDES) $(SRCS) $(LDSHARED) $(CFLAGS) $(OBJS) $(IOBJS) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(SO) allegrocl_cpp: $(SRCS) $(SWIG) -c++ -allegrocl $(SWIGOPT) $(INTERFACEPATH) - $(CXX) -c $(CCSHARED) $(CFLAGS) $(ICXXSRCS) $(SRCS) $(CXXSRCS) $(INCLUDES) + $(CXX) -c $(CCSHARED) $(CFLAGS) $(ICXXSRCS) $(SRCS) $(CXXSRCS) $(INCLUDES) $(CXXSHARED) $(CFLAGS) $(OBJS) $(IOBJS) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(SO) allegrocl_clean: @@ -1087,12 +1087,12 @@ clisp_clean: cffi: $(SRCS) $(SWIG) -cffi $(SWIGOPT) $(INTERFACEPATH) -# $(CC) -c $(CCSHARED) $(CFLAGS) $(ISRCS) $(INCLUDES) $(SRCS) +# $(CC) -c $(CCSHARED) $(CFLAGS) $(ISRCS) $(INCLUDES) $(SRCS) # $(LDSHARED) $(CFLAGS) $(OBJS) $(IOBJS) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(SO) cffi_cpp: $(SRCS) $(SWIG) -c++ -cffi $(SWIGOPT) $(INTERFACEPATH) - $(CXX) -c $(CCSHARED) $(CFLAGS) $(ICXXSRCS) $(SRCS) $(CXXSRCS) $(INCLUDES) + $(CXX) -c $(CCSHARED) $(CFLAGS) $(ICXXSRCS) $(SRCS) $(CXXSRCS) $(INCLUDES) $(CXXSHARED) $(CFLAGS) $(OBJS) $(IOBJS) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(SO) cffi_clean: @@ -1106,12 +1106,12 @@ cffi_clean: uffi: $(SRCS) $(SWIG) -uffi $(SWIGOPT) $(INTERFACEPATH) -# $(CC) -c $(CCSHARED) $(CFLAGS) $(ISRCS) $(INCLUDES) $(SRCS) +# $(CC) -c $(CCSHARED) $(CFLAGS) $(ISRCS) $(INCLUDES) $(SRCS) # $(LDSHARED) $(CFLAGS) $(OBJS) $(IOBJS) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(SO) uffi_cpp: $(SRCS) $(SWIG) -c++ -uffi $(SWIGOPT) $(INTERFACEPATH) -# $(CXX) -c $(CCSHARED) $(CFLAGS) $(ICXXSRCS) $(SRCS) $(CXXSRCS) $(INCLUDES) +# $(CXX) -c $(CCSHARED) $(CFLAGS) $(ICXXSRCS) $(SRCS) $(CXXSRCS) $(INCLUDES) # $(CXXSHARED) $(CFLAGS) $(OBJS) $(IOBJS) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(SO) uffi_clean: @@ -1212,3 +1212,56 @@ go_clean: rm -f *_wrap* *_gc* .~* runme rm -f core @EXTRA_CLEAN@ rm -f *.@OBJEXT@ *.[568] *.a *@SO@ + +################################################################## +##### D ###### +################################################################## + +DLIBPREFIX = @DLIBPREFIX@ + +ifeq (2,$(D_VERSION)) + SWIGD = $(SWIG) -d -d2 + DCOMPILER = @D2COMPILER@ +else + SWIGD = $(SWIG) -d + DCOMPILER = @D1COMPILER@ +endif + +ifeq (dmd,$(DCOMPILER)) + # DMD is 32bit only by now + CFLAGS += -m32 +endif + +# ---------------------------------------------------------------- +# Build a dynamically loadable D wrapper for a C module +# ---------------------------------------------------------------- + +d: $(SRCS) + $(SWIGD) $(SWIGOPT) $(INTERFACEPATH) + $(CC) -c $(CCSHARED) $(CFLAGS) $(EXTRA_CFLAGS) $(SRCS) $(ISRCS) $(INCLUDES) + $(LDSHARED) $(CFLAGS) $(EXTRA_LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) -o $(DLIBPREFIX)$(TARGET)$(SO) + +# ---------------------------------------------------------------- +# Build a dynamically loadable D wrapper for a C++ module +# ---------------------------------------------------------------- + +d_cpp: $(SRCS) + $(SWIGD) -c++ $(SWIGOPT) $(INTERFACEPATH) + $(CXX) -c $(CCSHARED) $(CFLAGS) $(EXTRA_CFLAGS) $(SRCS) $(CXXSRCS) $(ICXXSRCS) $(INCLUDES) + $(CXXSHARED) $(CFLAGS) $(EXTRA_LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) $(CPP_DLLIBS) -o $(DLIBPREFIX)$(TARGET)$(SO) + +# ---------------------------------------------------------------- +# Compile D files +# ---------------------------------------------------------------- + +d_compile: $(SRCS) + $(COMPILETOOL) $(DCOMPILER) $(DFLAGS) $(DSRCS) + +# ----------------------------------------------------------------- +# Clean the D examples +# ----------------------------------------------------------------- + +d_clean: + rm -f *_wrap* *~ .~* runme runme.exe `find . -name \*.d | grep -v runme.d` + rm -f core @EXTRA_CLEAN@ + rm -f *.@OBJEXT@ *@SO@ diff --git a/Examples/d/callback/Makefile b/Examples/d/callback/Makefile new file mode 100644 index 000000000..bc16dd0fc --- /dev/null +++ b/Examples/d/callback/Makefile @@ -0,0 +1,28 @@ +ifeq (2,$(D_VERSION)) + WORKING_DIR = d2/ +else + WORKING_DIR = d1/ +endif + +TOP = ../../.. +SWIG = $(TOP)/../preinst-swig +EXTRA_CFLAGS = -I../ ../example.cxx example_wrap.cxx +EXTRA_LDFLAGS = example.o example_wrap.o +TARGET = example_wrap +SWIGOPT = +DSRCS = *.d +DFLAGS = -ofrunme + + +all:: d + +d:: + cd $(WORKING_DIR); \ + $(MAKE) -f $(TOP)/Makefile EXTRA_CFLAGS='$(EXTRA_CFLAGS)' EXTRA_LDFLAGS='$(EXTRA_LDFLAGS)' SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT) -outcurrentdir ../example.i' TARGET='$(TARGET)' d_cpp; \ + $(MAKE) -f $(TOP)/Makefile DSRCS='$(DSRCS)' DFLAGS='$(DFLAGS)' d_compile + +clean:: + cd $(WORKING_DIR); \ + $(MAKE) -f $(TOP)/Makefile d_clean + +check: all diff --git a/Examples/d/callback/d1/runme.d b/Examples/d/callback/d1/runme.d new file mode 100644 index 000000000..e34e09603 --- /dev/null +++ b/Examples/d/callback/d1/runme.d @@ -0,0 +1,36 @@ +module runme; + +import tango.io.Stdout; +import example; + +public class DCallback : Callback { + public override void run() { + Stdout( "DCallback.run()" ).newline; + } +} + +void main() { + auto caller = new Caller(); + + Stdout( "Adding and calling a normal C++ callback" ).newline; + Stdout( "----------------------------------------" ).newline; + { + scope auto callback = new Callback(); + caller.setCallback(callback); + caller.call(); + caller.resetCallback(); + } + + Stdout.newline; + Stdout( "Adding and calling a D callback" ).newline; + Stdout( "-------------------------------" ).newline; + { + scope auto callback = new DCallback(); + caller.setCallback(callback); + caller.call(); + caller.resetCallback(); + } + + Stdout.newline; + Stdout( "D exit" ).newline; +} diff --git a/Examples/d/callback/d2/runme.d b/Examples/d/callback/d2/runme.d new file mode 100644 index 000000000..88ffcdefd --- /dev/null +++ b/Examples/d/callback/d2/runme.d @@ -0,0 +1,36 @@ +module runme; + +import std.stdio; +import example; + +public class DCallback : Callback { + public override void run() { + writeln( "DCallback.run()" ); + } +} + +void main() { + auto caller = new Caller(); + + writeln( "Adding and calling a normal C++ callback" ); + writeln( "----------------------------------------" ); + { + scope auto callback = new Callback(); + caller.setCallback(callback); + caller.call(); + caller.resetCallback(); + } + + writeln(); + writeln( "Adding and calling a D callback" ); + writeln( "-------------------------------" ); + { + scope auto callback = new DCallback(); + caller.setCallback(callback); + caller.call(); + caller.resetCallback(); + } + + writeln(); + writeln( "D exit" ); +} diff --git a/Examples/d/callback/example.cxx b/Examples/d/callback/example.cxx new file mode 100644 index 000000000..450d75608 --- /dev/null +++ b/Examples/d/callback/example.cxx @@ -0,0 +1,4 @@ +/* File : example.cxx */ + +#include "example.h" + diff --git a/Examples/d/callback/example.h b/Examples/d/callback/example.h new file mode 100644 index 000000000..38d25a043 --- /dev/null +++ b/Examples/d/callback/example.h @@ -0,0 +1,24 @@ +/* File : example.h */ + +#include +#include + +class Callback { +public: + virtual ~Callback() { std::cout << "Callback::~Callback()" << std:: endl; } + virtual void run() { std::cout << "Callback::run()" << std::endl; } +}; + + +class Caller { +private: + Callback *_callback; +public: + Caller(): _callback(0) {} + ~Caller() { delCallback(); } + void delCallback() { delete _callback; _callback = 0; } + void setCallback(Callback *cb) { delCallback(); _callback = cb; } + void resetCallback() { _callback = 0; } + void call() { if (_callback) _callback->run(); } +}; + diff --git a/Examples/d/callback/example.i b/Examples/d/callback/example.i new file mode 100644 index 000000000..90beda01a --- /dev/null +++ b/Examples/d/callback/example.i @@ -0,0 +1,13 @@ +/* File : example.i */ +%module(directors="1") example +%{ +#include "example.h" +%} + +%include "std_string.i" + +/* turn on director wrapping Callback */ +%feature("director") Callback; + +%include "example.h" + diff --git a/Examples/d/check.list b/Examples/d/check.list new file mode 100644 index 000000000..010e7bbfc --- /dev/null +++ b/Examples/d/check.list @@ -0,0 +1,9 @@ +# See top-level Makefile.in. +callback +class +constants +enum +extend +funcptr +simple +variables diff --git a/Examples/d/class/Makefile b/Examples/d/class/Makefile new file mode 100644 index 000000000..bc16dd0fc --- /dev/null +++ b/Examples/d/class/Makefile @@ -0,0 +1,28 @@ +ifeq (2,$(D_VERSION)) + WORKING_DIR = d2/ +else + WORKING_DIR = d1/ +endif + +TOP = ../../.. +SWIG = $(TOP)/../preinst-swig +EXTRA_CFLAGS = -I../ ../example.cxx example_wrap.cxx +EXTRA_LDFLAGS = example.o example_wrap.o +TARGET = example_wrap +SWIGOPT = +DSRCS = *.d +DFLAGS = -ofrunme + + +all:: d + +d:: + cd $(WORKING_DIR); \ + $(MAKE) -f $(TOP)/Makefile EXTRA_CFLAGS='$(EXTRA_CFLAGS)' EXTRA_LDFLAGS='$(EXTRA_LDFLAGS)' SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT) -outcurrentdir ../example.i' TARGET='$(TARGET)' d_cpp; \ + $(MAKE) -f $(TOP)/Makefile DSRCS='$(DSRCS)' DFLAGS='$(DFLAGS)' d_compile + +clean:: + cd $(WORKING_DIR); \ + $(MAKE) -f $(TOP)/Makefile d_clean + +check: all diff --git a/Examples/d/class/d1/runme.d b/Examples/d/class/d1/runme.d new file mode 100644 index 000000000..b0c4263a2 --- /dev/null +++ b/Examples/d/class/d1/runme.d @@ -0,0 +1,58 @@ +// This example illustrates how C++ classes can be used from D using SWIG. +// The D class gets mapped onto the C++ class and behaves as if it is a D class. +module runme; + +import tango.io.Stdout; +import example; + +void main() { + // ----- Object creation ----- + + Stdout( "Creating some objects:" ).newline; + + { + scope Square s = new Square(10); + scope Circle c = new Circle(10); + + // ----- Access a static member ----- + Stdout.format( "{} shapes were created.", Shape.nshapes ).newline; + + // ----- Member data access ----- + + // Notice how we can do this using functions specific to + // the 'Circle' class. + c.x = 20; + c.y = 30; + + // Now use the same functions in the base class + Shape shape = s; + shape.x = -10; + shape.y = 5; + + Stdout( "\nHere is their current position:" ).newline; + Stdout.format( " Circle = ( {}, {} )", c.x, c.y ).newline; + Stdout.format( " Square = ( {}, {} )", s.x, s.y ).newline; + + // ----- Call some methods ----- + + Stdout( "\nHere are some properties of the shapes:" ).newline; + Shape[] shapes = [ cast(Shape) c, cast(Shape) s ]; + foreach ( currentShape; shapes ) + { + Stdout.format( " {}", currentShape.classinfo.name ).newline; + Stdout.format( " area = {}", currentShape.area() ).newline; + Stdout.format( " perimeter = {}", currentShape.perimeter() ).newline; + } + + // Notice how the area() and perimeter() functions really + // invoke the appropriate virtual method on each object. + + // ----- Delete everything ----- + Stdout( "\nGuess I'll clean up now:" ).newline; + // Note: when this using scope is exited the D destructors are called which + // in turn call the C++ destructors. + } + + Stdout.format( "{} shapes remain", Shape.nshapes ).newline; + Stdout( "\nGoodbye!" ).newline; +} diff --git a/Examples/d/class/d2/runme.d b/Examples/d/class/d2/runme.d new file mode 100644 index 000000000..2e86c5fc7 --- /dev/null +++ b/Examples/d/class/d2/runme.d @@ -0,0 +1,58 @@ +// This example illustrates how C++ classes can be used from D using SWIG. +// The D class gets mapped onto the C++ class and behaves as if it is a D class. +module runme; + +import std.stdio; +import example; + +void main() { + // ----- Object creation ----- + + writeln( "Creating some objects:" ); + + { + scope Square s = new Square(10); + scope Circle c = new Circle(10); + + // ----- Access a static member ----- + writefln( "%s shapes were created.", Shape.nshapes ); + + // ----- Member data access ----- + + // Notice how we can do this using functions specific to + // the 'Circle' class. + c.x = 20; + c.y = 30; + + // Now use the same functions in the base class + Shape shape = s; + shape.x = -10; + shape.y = 5; + + writeln( "\nHere is their current position:" ); + writefln( " Circle = ( %s, %s )", c.x, c.y ); + writefln( " Square = ( %s, %s )", s.x, s.y ); + + // ----- Call some methods ----- + + writeln( "\nHere are some properties of the shapes:" ); + Shape[] shapes = [ cast(Shape) c, cast(Shape) s ]; + foreach ( currentShape; shapes ) + { + writefln( " %s", currentShape.classinfo.name ); + writefln( " area = %s", currentShape.area() ); + writefln( " perimeter = %s", currentShape.perimeter() ); + } + + // Notice how the area() and perimeter() functions really + // invoke the appropriate virtual method on each object. + + // ----- Delete everything ----- + writeln( "\nGuess I'll clean up now:" ); + // Note: when this using scope is exited the D destructors are called which + // in turn call the C++ destructors. + } + + writefln( "%s shapes remain", Shape.nshapes ); + writeln( "\nGoodbye!" ); +} diff --git a/Examples/d/class/example.cxx b/Examples/d/class/example.cxx new file mode 100644 index 000000000..1e8e203dd --- /dev/null +++ b/Examples/d/class/example.cxx @@ -0,0 +1,28 @@ +/* File : example.c */ + +#include "example.h" +#define M_PI 3.14159265358979323846 + +/* Move the shape to a new location */ +void Shape::move(double dx, double dy) { + x += dx; + y += dy; +} + +int Shape::nshapes = 0; + +double Circle::area(void) { + return M_PI*radius*radius; +} + +double Circle::perimeter(void) { + return 2*M_PI*radius; +} + +double Square::area(void) { + return width*width; +} + +double Square::perimeter(void) { + return 4*width; +} diff --git a/Examples/d/class/example.h b/Examples/d/class/example.h new file mode 100644 index 000000000..0d4527e92 --- /dev/null +++ b/Examples/d/class/example.h @@ -0,0 +1,34 @@ +/* File : example.h */ + +class Shape { +public: + Shape() { + nshapes++; + } + virtual ~Shape() { + nshapes--; + }; + double x, y; + void move(double dx, double dy); + virtual double area(void) = 0; + virtual double perimeter(void) = 0; + static int nshapes; +}; + +class Circle : public Shape { +private: + double radius; +public: + Circle(double r) : radius(r) { }; + virtual double area(void); + virtual double perimeter(void); +}; + +class Square : public Shape { +private: + double width; +public: + Square(double w) : width(w) { }; + virtual double area(void); + virtual double perimeter(void); +}; diff --git a/Examples/d/class/example.i b/Examples/d/class/example.i new file mode 100644 index 000000000..75700b305 --- /dev/null +++ b/Examples/d/class/example.i @@ -0,0 +1,10 @@ +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + +/* Let's just grab the original header file here */ +%include "example.h" + diff --git a/Examples/d/constants/Makefile b/Examples/d/constants/Makefile new file mode 100644 index 000000000..ce17134ec --- /dev/null +++ b/Examples/d/constants/Makefile @@ -0,0 +1,28 @@ +ifeq (2,$(D_VERSION)) + WORKING_DIR = d2/ +else + WORKING_DIR = d1/ +endif + +TOP = ../../.. +SWIG = $(TOP)/../preinst-swig +EXTRA_CFLAGS = -I../ example_wrap.c +EXTRA_LDFLAGS = example_wrap.o +TARGET = example_wrap +SWIGOPT = +DSRCS = *.d +DFLAGS = -ofrunme + + +all:: d + +d:: + cd $(WORKING_DIR); \ + $(MAKE) -f $(TOP)/Makefile EXTRA_CFLAGS='$(EXTRA_CFLAGS)' EXTRA_LDFLAGS='$(EXTRA_LDFLAGS)' SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT) -outcurrentdir ../example.i' TARGET='$(TARGET)' d; \ + $(MAKE) -f $(TOP)/Makefile DSRCS='$(DSRCS)' DFLAGS='$(DFLAGS)' d_compile + +clean:: + cd $(WORKING_DIR); \ + $(MAKE) -f $(TOP)/Makefile d_clean + +check: all diff --git a/Examples/d/constants/d1/runme.d b/Examples/d/constants/d1/runme.d new file mode 100644 index 000000000..47362cbf3 --- /dev/null +++ b/Examples/d/constants/d1/runme.d @@ -0,0 +1,28 @@ +module runme; + +import tango.io.Stdout; +static import example; + +void main() { + Stdout.formatln("ICONST = {} (should be 42)", example.ICONST); + Stdout.formatln("FCONST = {} (should be 2.18)", example.FCONST); + Stdout.formatln("CCONST = {} (should be 'x')", example.CCONST); + Stdout.formatln("CCONST2 = {} (this should be on a new line)", example.CCONST2); + Stdout.formatln("SCONST = {} (should be 'Hello World')", example.SCONST); + Stdout.formatln("SCONST2 = {} (should be '\"Hello World\"')", example.SCONST2); + Stdout.formatln("EXPR = {} (should be 48.55)", example.EXPR); + Stdout.formatln("iconst = {} (should be 37)", example.iconst); + Stdout.formatln("fconst = {} (should be 3.14)", example.fconst); + + static if (is(typeof(example.EXTERN))) { + Stdout.formatln("EXTERN should not be defined, but is: {}.", example.EXTERN ); + } else { + Stdout.formatln("EXTERN isn't defined (good)"); + } + + static if (is(typeof(example.FOO))) { + Stdout.formatln("FOO should not be defined, but is: {}.", example.FOO); + } else { + Stdout.formatln("FOO isn't defined (good)"); + } +} diff --git a/Examples/d/constants/d2/runme.d b/Examples/d/constants/d2/runme.d new file mode 100644 index 000000000..4be510d16 --- /dev/null +++ b/Examples/d/constants/d2/runme.d @@ -0,0 +1,28 @@ +module runme; + +import std.stdio; +static import example; + +void main() { + writefln("ICONST = %s (should be 42)", example.ICONST); + writefln("FCONST = %s (should be 2.1828)", example.FCONST); + writefln("CCONST = %s (should be 'x')", example.CCONST); + writefln("CCONST2 = %s (this should be on a new line)", example.CCONST2); + writefln("SCONST = %s (should be 'Hello World')", example.SCONST); + writefln("SCONST2 = %s (should be '\"Hello World\"')", example.SCONST2); + writefln("EXPR = %s (should be 48.5484)", example.EXPR); + writefln("iconst = %s (should be 37)", example.iconst); + writefln("fconst = %s (should be 3.14)", example.fconst); + + static if (is(typeof(example.EXTERN))) { + writefln("EXTERN should not be defined, but is: %s.", example.EXTERN ); + } else { + writeln("EXTERN isn't defined (good)"); + } + + static if (is(typeof(example.FOO))) { + writefln("FOO should not be defined, but is: %s.", example.FOO); + } else { + writeln("FOO isn't defined (good)"); + } +} diff --git a/Examples/d/constants/example.d b/Examples/d/constants/example.d new file mode 100644 index 000000000..7448d0ad9 --- /dev/null +++ b/Examples/d/constants/example.d @@ -0,0 +1,23 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 1.3.41 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +module example; + +static import example_wrap; + +static import tango.stdc.stringz; + +public const int ICONST = 42; +public const double FCONST = 2.1828; +public const char CCONST = 'x'; +public const char CCONST2 = '\n'; +public const char[] SCONST = "Hello World"; +public const char[] SCONST2 = "\"Hello World\""; +public const double EXPR = 42+3*(2.1828); +public const int iconst = 37; +public const double fconst = 3.14; diff --git a/Examples/d/constants/example.i b/Examples/d/constants/example.i new file mode 100644 index 000000000..5eb541919 --- /dev/null +++ b/Examples/d/constants/example.i @@ -0,0 +1,32 @@ +/* File : example.i */ +%module example + +/* Force the generated D code to use the C constant values rather than + retrieving them at runtime. You can also try disabling the feature and + compare the generated code. */ +%dnativeconst; + + +/* A few preprocessor macros */ + +#define ICONST 42 +#define FCONST 2.1828 +#define CCONST 'x' +#define CCONST2 '\n' +#define SCONST "Hello World" +#define SCONST2 "\"Hello World\"" + +/* This should work just fine */ +#define EXPR ICONST + 3*(FCONST) + +/* This shouldn't do anything */ +#define EXTERN extern + +/* Neither should this (BAR isn't defined) */ +#define FOO (ICONST + BAR) + + +/* The following directives also produce constants */ + +%constant int iconst = 37; +%constant double fconst = 3.14; diff --git a/Examples/d/enum/Makefile b/Examples/d/enum/Makefile new file mode 100644 index 000000000..bc16dd0fc --- /dev/null +++ b/Examples/d/enum/Makefile @@ -0,0 +1,28 @@ +ifeq (2,$(D_VERSION)) + WORKING_DIR = d2/ +else + WORKING_DIR = d1/ +endif + +TOP = ../../.. +SWIG = $(TOP)/../preinst-swig +EXTRA_CFLAGS = -I../ ../example.cxx example_wrap.cxx +EXTRA_LDFLAGS = example.o example_wrap.o +TARGET = example_wrap +SWIGOPT = +DSRCS = *.d +DFLAGS = -ofrunme + + +all:: d + +d:: + cd $(WORKING_DIR); \ + $(MAKE) -f $(TOP)/Makefile EXTRA_CFLAGS='$(EXTRA_CFLAGS)' EXTRA_LDFLAGS='$(EXTRA_LDFLAGS)' SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT) -outcurrentdir ../example.i' TARGET='$(TARGET)' d_cpp; \ + $(MAKE) -f $(TOP)/Makefile DSRCS='$(DSRCS)' DFLAGS='$(DFLAGS)' d_compile + +clean:: + cd $(WORKING_DIR); \ + $(MAKE) -f $(TOP)/Makefile d_clean + +check: all diff --git a/Examples/d/enum/d1/runme.d b/Examples/d/enum/d1/runme.d new file mode 100644 index 000000000..d986986d1 --- /dev/null +++ b/Examples/d/enum/d1/runme.d @@ -0,0 +1,28 @@ +module runme; + +import tango.io.Stdout; +import example; + +void main() { + Stdout( "Printing out some enum values:" ).newline; + Stdout(" color:").newline; + Stdout.formatln(" {} = {}", color.RED, cast(int)color.RED); + Stdout.formatln(" {} = {}", color.BLUE, cast(int)color.BLUE); + Stdout.formatln(" {} = {}", color.GREEN, cast(int)color.GREEN); + + Stdout("\n Foo.speed:").newline; + Stdout.formatln(" Foo.{} = {}", Foo.speed.IMPULSE, cast(int)Foo.speed.IMPULSE); + Stdout.formatln(" Foo.{} = {}", Foo.speed.WARP, cast(int)Foo.speed.WARP); + Stdout.formatln(" Foo.{} = {}", Foo.speed.LUDICROUS , cast(int)Foo.speed.LUDICROUS); + + Stdout("\nTesting use of enums with functions:").newline; + example.enum_test(color.RED, Foo.speed.IMPULSE); + example.enum_test(color.BLUE, Foo.speed.WARP); + example.enum_test(color.GREEN, Foo.speed.LUDICROUS); + + Stdout( "\nTesting use of enum with class method:" ).newline; + scope f = new Foo(); + f.enum_test(Foo.speed.IMPULSE); + f.enum_test(Foo.speed.WARP); + f.enum_test(Foo.speed.LUDICROUS); +} diff --git a/Examples/d/enum/d2/runme.d b/Examples/d/enum/d2/runme.d new file mode 100644 index 000000000..acaec8ae8 --- /dev/null +++ b/Examples/d/enum/d2/runme.d @@ -0,0 +1,28 @@ +module runme; + +import std.stdio; +import example; + +void main() { + writeln( "Printing out some enum values:" ); + writeln(" color:"); + writefln(" %s = %s", color.RED, cast(int)color.RED); + writefln(" %s = %s", color.BLUE, cast(int)color.BLUE); + writefln(" %s = %s", color.GREEN, cast(int)color.GREEN); + + writeln("\n Foo.speed:"); + writefln(" Foo.%s = %s", Foo.speed.IMPULSE, cast(int)Foo.speed.IMPULSE); + writefln(" Foo.%s = %s", Foo.speed.WARP, cast(int)Foo.speed.WARP); + writefln(" Foo.%s = %s", Foo.speed.LUDICROUS , cast(int)Foo.speed.LUDICROUS); + + writeln("\nTesting use of enums with functions:"); + example.enum_test(color.RED, Foo.speed.IMPULSE); + example.enum_test(color.BLUE, Foo.speed.WARP); + example.enum_test(color.GREEN, Foo.speed.LUDICROUS); + + writeln( "\nTesting use of enum with class method:" ); + scope f = new Foo(); + f.enum_test(Foo.speed.IMPULSE); + f.enum_test(Foo.speed.WARP); + f.enum_test(Foo.speed.LUDICROUS); +} diff --git a/Examples/d/enum/example.cxx b/Examples/d/enum/example.cxx new file mode 100644 index 000000000..df7bb6328 --- /dev/null +++ b/Examples/d/enum/example.cxx @@ -0,0 +1,37 @@ +/* File : example.cxx */ + +#include "example.h" +#include + +void Foo::enum_test(speed s) { + if (s == IMPULSE) { + printf("IMPULSE speed\n"); + } else if (s == WARP) { + printf("WARP speed\n"); + } else if (s == LUDICROUS) { + printf("LUDICROUS speed\n"); + } else { + printf("Unknown speed\n"); + } +} + +void enum_test(color c, Foo::speed s) { + if (c == RED) { + printf("color = RED, "); + } else if (c == BLUE) { + printf("color = BLUE, "); + } else if (c == GREEN) { + printf("color = GREEN, "); + } else { + printf("color = Unknown color!, "); + } + if (s == Foo::IMPULSE) { + printf("speed = IMPULSE speed\n"); + } else if (s == Foo::WARP) { + printf("speed = WARP speed\n"); + } else if (s == Foo::LUDICROUS) { + printf("speed = LUDICROUS speed\n"); + } else { + printf("speed = Unknown speed!\n"); + } +} diff --git a/Examples/d/enum/example.h b/Examples/d/enum/example.h new file mode 100644 index 000000000..9119cd9fc --- /dev/null +++ b/Examples/d/enum/example.h @@ -0,0 +1,13 @@ +/* File : example.h */ + +enum color { RED, BLUE, GREEN }; + +class Foo { + public: + Foo() { } + enum speed { IMPULSE=10, WARP=20, LUDICROUS=30 }; + void enum_test(speed s); +}; + +void enum_test(color c, Foo::speed s); + diff --git a/Examples/d/enum/example.i b/Examples/d/enum/example.i new file mode 100644 index 000000000..23ee8a822 --- /dev/null +++ b/Examples/d/enum/example.i @@ -0,0 +1,11 @@ +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + +/* Let's just grab the original header file here */ + +%include "example.h" + diff --git a/Examples/d/extend/Makefile b/Examples/d/extend/Makefile new file mode 100644 index 000000000..bc16dd0fc --- /dev/null +++ b/Examples/d/extend/Makefile @@ -0,0 +1,28 @@ +ifeq (2,$(D_VERSION)) + WORKING_DIR = d2/ +else + WORKING_DIR = d1/ +endif + +TOP = ../../.. +SWIG = $(TOP)/../preinst-swig +EXTRA_CFLAGS = -I../ ../example.cxx example_wrap.cxx +EXTRA_LDFLAGS = example.o example_wrap.o +TARGET = example_wrap +SWIGOPT = +DSRCS = *.d +DFLAGS = -ofrunme + + +all:: d + +d:: + cd $(WORKING_DIR); \ + $(MAKE) -f $(TOP)/Makefile EXTRA_CFLAGS='$(EXTRA_CFLAGS)' EXTRA_LDFLAGS='$(EXTRA_LDFLAGS)' SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT) -outcurrentdir ../example.i' TARGET='$(TARGET)' d_cpp; \ + $(MAKE) -f $(TOP)/Makefile DSRCS='$(DSRCS)' DFLAGS='$(DFLAGS)' d_compile + +clean:: + cd $(WORKING_DIR); \ + $(MAKE) -f $(TOP)/Makefile d_clean + +check: all diff --git a/Examples/d/extend/d1/runme.d b/Examples/d/extend/d1/runme.d new file mode 100644 index 000000000..96501d1a4 --- /dev/null +++ b/Examples/d/extend/d1/runme.d @@ -0,0 +1,75 @@ +/// This file illustrates the cross language polymorphism using directors. +module runme; + +import example; +import tango.io.Stdout; + +// CEO class, which overrides Employee.getPosition(). +class CEO : Manager { +public: + this( char[] name ) { + super( name ); + } + + override char[] getPosition() { + return "CEO"; + } + + // Public method to stop the SWIG proxy base class from thinking it owns the underlying C++ memory. + void disownMemory() { + swigCMemOwn = false; + } +} + +void main() { + // Create an instance of CEO, a class derived from the D proxy of the + // underlying C++ class. The calls to getName() and getPosition() are standard, + // the call to getTitle() uses the director wrappers to call CEO.getPosition(). + + auto e = new CEO( "Alice" ); + Stdout.formatln( "{} is a {}.", e.getName(), e.getPosition() ); + Stdout.formatln( "Just call her '{}'.", e.getTitle() ); + Stdout( "----------------------" ).newline; + + { + // Create a new EmployeeList instance. This class does not have a C++ + // director wrapper, but can be used freely with other classes that do. + scope auto list = new EmployeeList(); + + // EmployeeList owns its items, so we must surrender ownership of objects we add. + e.disownMemory(); + list.addEmployee(e); + Stdout( "----------------------" ).newline; + + // Now we access the first four items in list (three are C++ objects that + // EmployeeList's constructor adds, the last is our CEO). The virtual + // methods of all these instances are treated the same. For items 0, 1, and + // 2, all methods resolve in C++. For item 3, our CEO, getTitle calls + // getPosition which resolves in D. The call to getPosition is + // slightly different, however, because of the overidden getPosition() call, since + // now the object reference has been "laundered" by passing through + // EmployeeList as an Employee*. Previously, D resolved the call + // immediately in CEO, but now D thinks the object is an instance of + // class Employee. So the call passes through the + // Employee proxy class and on to the C wrappers and C++ director, + // eventually ending up back at the D CEO implementation of getPosition(). + // The call to getTitle() for item 3 runs the C++ Employee::getTitle() + // method, which in turn calls getPosition(). This virtual method call + // passes down through the C++ director class to the D implementation + // in CEO. All this routing takes place transparently. + + Stdout( "(position, title) for items 0-3:" ).newline; + Stdout.formatln( " {}, '{}'", list.getItem(0).getPosition(), list.getItem(0).getTitle() ); + Stdout.formatln( " {}, '{}'", list.getItem(1).getPosition(), list.getItem(1).getTitle() ); + Stdout.formatln( " {}, '{}'", list.getItem(2).getPosition(), list.getItem(2).getTitle() ); + Stdout.formatln( " {}, '{}'", list.getItem(3).getPosition(), list.getItem(3).getTitle() ); + Stdout( "----------------------" ).newline; + + // All Employees will be destroyed when the EmployeeList goes out of scope, + // including the CEO instance. + } + Stdout( "----------------------" ).newline; + + // All done. + Stdout( "Exiting cleanly from D code." ).newline; +} diff --git a/Examples/d/extend/d2/runme.d b/Examples/d/extend/d2/runme.d new file mode 100644 index 000000000..1ea6dfd21 --- /dev/null +++ b/Examples/d/extend/d2/runme.d @@ -0,0 +1,75 @@ +/// This file illustrates the cross language polymorphism using directors. +module runme; + +import std.stdio; +import example; + +// CEO class, which overrides Employee.getPosition(). +class CEO : Manager { +public: + this( string name ) { + super( name ); + } + + override string getPosition() const { + return "CEO"; + } + + // Public method to stop the SWIG proxy base class from thinking it owns the underlying C++ memory. + void disownMemory() { + swigCMemOwn = false; + } +} + +void main() { + // Create an instance of CEO, a class derived from the D proxy of the + // underlying C++ class. The calls to getName() and getPosition() are standard, + // the call to getTitle() uses the director wrappers to call CEO.getPosition(). + + auto e = new CEO( "Alice" ); + writefln( "%s is a %s.", e.getName(), e.getPosition() ); + writefln( "Just call her '%s'.", e.getTitle() ); + writeln( "----------------------" ); + + { + // Create a new EmployeeList instance. This class does not have a C++ + // director wrapper, but can be used freely with other classes that do. + scope auto list = new EmployeeList(); + + // EmployeeList owns its items, so we must surrender ownership of objects we add. + e.disownMemory(); + list.addEmployee(e); + writeln( "----------------------" ); + + // Now we access the first four items in list (three are C++ objects that + // EmployeeList's constructor adds, the last is our CEO). The virtual + // methods of all these instances are treated the same. For items 0, 1, and + // 2, all methods resolve in C++. For item 3, our CEO, getTitle calls + // getPosition which resolves in D. The call to getPosition is + // slightly different, however, because of the overidden getPosition() call, since + // now the object reference has been "laundered" by passing through + // EmployeeList as an Employee*. Previously, D resolved the call + // immediately in CEO, but now D thinks the object is an instance of + // class Employee. So the call passes through the + // Employee proxy class and on to the C wrappers and C++ director, + // eventually ending up back at the D CEO implementation of getPosition(). + // The call to getTitle() for item 3 runs the C++ Employee::getTitle() + // method, which in turn calls getPosition(). This virtual method call + // passes down through the C++ director class to the D implementation + // in CEO. All this routing takes place transparently. + + writeln( "(position, title) for items 0-3:" ); + writefln( " %s, '%s'", list.getItem(0).getPosition(), list.getItem(0).getTitle() ); + writefln( " %s, '%s'", list.getItem(1).getPosition(), list.getItem(1).getTitle() ); + writefln( " %s, '%s'", list.getItem(2).getPosition(), list.getItem(2).getTitle() ); + writefln( " %s, '%s'", list.getItem(3).getPosition(), list.getItem(3).getTitle() ); + writeln( "----------------------" ); + + // All Employees will be destroyed when the EmployeeList goes out of scope, + // including the CEO instance. + } + writeln( "----------------------" ); + + // All done. + writeln( "Exiting cleanly from D code." ); +} diff --git a/Examples/d/extend/example.cxx b/Examples/d/extend/example.cxx new file mode 100644 index 000000000..450d75608 --- /dev/null +++ b/Examples/d/extend/example.cxx @@ -0,0 +1,4 @@ +/* File : example.cxx */ + +#include "example.h" + diff --git a/Examples/d/extend/example.h b/Examples/d/extend/example.h new file mode 100644 index 000000000..7ad93fbc1 --- /dev/null +++ b/Examples/d/extend/example.h @@ -0,0 +1,56 @@ +/* File : example.h */ + +#include +#include +#include +#include +#include + +class Employee { +private: + std::string name; +public: + Employee(const char* n): name(n) {} + virtual std::string getTitle() { return getPosition() + " " + getName(); } + virtual std::string getName() { return name; } + virtual std::string getPosition() const { return "Employee"; } + virtual ~Employee() { printf("~Employee() @ %p\n", this); } +}; + + +class Manager: public Employee { +public: + Manager(const char* n): Employee(n) {} + virtual std::string getPosition() const { return "Manager"; } +}; + + +class EmployeeList { + std::vector list; +public: + EmployeeList() { + list.push_back(new Employee("Bob")); + list.push_back(new Employee("Jane")); + list.push_back(new Manager("Ted")); + } + void addEmployee(Employee *p) { + list.push_back(p); + std::cout << "New employee added. Current employees are:" << std::endl; + std::vector::iterator i; + for (i=list.begin(); i!=list.end(); i++) { + std::cout << " " << (*i)->getTitle() << std::endl; + } + } + const Employee *getItem(int i) { + return list[i]; + } + ~EmployeeList() { + std::vector::iterator i; + std::cout << "~EmployeeList, deleting " << list.size() << " employees." << std::endl; + for (i=list.begin(); i!=list.end(); i++) { + delete *i; + } + std::cout << "~EmployeeList empty." << std::endl; + } +}; + diff --git a/Examples/d/extend/example.i b/Examples/d/extend/example.i new file mode 100644 index 000000000..0647e1319 --- /dev/null +++ b/Examples/d/extend/example.i @@ -0,0 +1,14 @@ +/* File : example.i */ +%module(directors="1") example +%{ +#include "example.h" +%} + +%include "std_string.i" + +/* turn on director wrapping for Manager */ +%feature("director") Employee; +%feature("director") Manager; + +%include "example.h" + diff --git a/Examples/d/funcptr/Makefile b/Examples/d/funcptr/Makefile new file mode 100644 index 000000000..616102926 --- /dev/null +++ b/Examples/d/funcptr/Makefile @@ -0,0 +1,28 @@ +ifeq (2,$(D_VERSION)) + WORKING_DIR = d2/ +else + WORKING_DIR = d1/ +endif + +TOP = ../../.. +SWIG = $(TOP)/../preinst-swig +EXTRA_CFLAGS = -I../ ../example.c example_wrap.c +EXTRA_LDFLAGS = example.o example_wrap.o +TARGET = example_wrap +SWIGOPT = +DSRCS = *.d +DFLAGS = -ofrunme + + +all:: d + +d:: + cd $(WORKING_DIR); \ + $(MAKE) -f $(TOP)/Makefile EXTRA_CFLAGS='$(EXTRA_CFLAGS)' EXTRA_LDFLAGS='$(EXTRA_LDFLAGS)' EXTRA_LDFLAGS='$(EXTRA_LDFLAGS)' SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT) -outcurrentdir ../example.i' TARGET='$(TARGET)' d; \ + $(MAKE) -f $(TOP)/Makefile DSRCS='$(DSRCS)' DFLAGS='$(DFLAGS)' d_compile + +clean:: + cd $(WORKING_DIR); \ + $(MAKE) -f $(TOP)/Makefile d_clean + +check: all diff --git a/Examples/d/funcptr/d1/runme.d b/Examples/d/funcptr/d1/runme.d new file mode 100644 index 000000000..2947602a5 --- /dev/null +++ b/Examples/d/funcptr/d1/runme.d @@ -0,0 +1,34 @@ +module runme; + +import tango.io.Stdout; +static import example; + +extern(C) int add(int a, int b) { + return a + b; +} + +extern(C) int sub(int a, int b) { + return a - b; +} + +extern(C) int mul(int a, int b) { + return a * b; +} + +void main() { + int a = 37; + int b = 42; + + Stdout( "a = " )( a ).newline; + Stdout( "b = " )( b ).newline; + + Stdout( "Trying some C callback functions:" ).newline; + Stdout( " ADD(a,b) = " )( example.do_op( a, b, example.ADD ) ).newline; + Stdout( " SUB(a,b) = " )( example.do_op( a, b, example.SUB ) ).newline; + Stdout( " MUL(a,b) = " )( example.do_op( a, b, example.MUL ) ).newline; + + Stdout( "Now the same with callback functions defined in D:" ).newline; + Stdout( " add(a,b) = " )( example.do_op( a, b, &add ) ).newline; + Stdout( " sub(a,b) = " )( example.do_op( a, b, &sub ) ).newline; + Stdout( " mul(a,b) = " )( example.do_op( a, b, &mul ) ).newline; +} diff --git a/Examples/d/funcptr/d2/runme.d b/Examples/d/funcptr/d2/runme.d new file mode 100644 index 000000000..929911d6c --- /dev/null +++ b/Examples/d/funcptr/d2/runme.d @@ -0,0 +1,34 @@ +module runme; + +import std.stdio; +static import example; + +extern(C) int add(int a, int b) { + return a + b; +} + +extern(C) int sub(int a, int b) { + return a - b; +} + +extern(C) int mul(int a, int b) { + return a * b; +} + +void main() { + int a = 37; + int b = 42; + + writefln( "a = %s", a ); + writefln( "b = %s", b ); + + writeln( "Trying some C callback functions:" ); + writefln( " ADD(a,b) = %s", example.do_op( a, b, example.ADD ) ); + writefln( " SUB(a,b) = %s", example.do_op( a, b, example.SUB ) ); + writefln( " MUL(a,b) = %s", example.do_op( a, b, example.MUL ) ); + + writeln( "Now the same with callback functions defined in D:" ); + writefln( " add(a,b) = %s", example.do_op( a, b, &add ) ); + writefln( " sub(a,b) = %s", example.do_op( a, b, &sub ) ); + writefln( " mul(a,b) = %s", example.do_op( a, b, &mul ) ); +} diff --git a/Examples/d/funcptr/example.c b/Examples/d/funcptr/example.c new file mode 100644 index 000000000..5c4a3dabf --- /dev/null +++ b/Examples/d/funcptr/example.c @@ -0,0 +1,19 @@ +/* File : example.c */ + +int do_op(int a, int b, int (*op)(int,int)) { + return (*op)(a,b); +} + +int add(int a, int b) { + return a+b; +} + +int sub(int a, int b) { + return a-b; +} + +int mul(int a, int b) { + return a*b; +} + +int (*funcvar)(int,int) = add; diff --git a/Examples/d/funcptr/example.h b/Examples/d/funcptr/example.h new file mode 100644 index 000000000..9936e24fc --- /dev/null +++ b/Examples/d/funcptr/example.h @@ -0,0 +1,9 @@ +/* file: example.h */ + +extern int do_op(int,int, int (*op)(int,int)); +extern int add(int,int); +extern int sub(int,int); +extern int mul(int,int); + +extern int (*funcvar)(int,int); + diff --git a/Examples/d/funcptr/example.i b/Examples/d/funcptr/example.i new file mode 100644 index 000000000..8b3bef678 --- /dev/null +++ b/Examples/d/funcptr/example.i @@ -0,0 +1,16 @@ +/* File : example.i */ +%module example +%{ +#include "example.h" +%} + +/* Wrap a function taking a pointer to a function */ +extern int do_op(int a, int b, int (*op)(int, int)); + +/* Now install a bunch of "ops" as constants */ +%constant int (*ADD)(int,int) = add; +%constant int (*SUB)(int,int) = sub; +%constant int (*MUL)(int,int) = mul; + +extern int (*funcvar)(int,int); + diff --git a/Examples/d/simple/Makefile b/Examples/d/simple/Makefile new file mode 100644 index 000000000..312e6a9e9 --- /dev/null +++ b/Examples/d/simple/Makefile @@ -0,0 +1,28 @@ +ifeq (2,$(D_VERSION)) + WORKING_DIR = d2/ +else + WORKING_DIR = d1/ +endif + +TOP = ../../.. +SWIG = $(TOP)/../preinst-swig +EXTRA_CFLAGS = -I../ ../example.c example_wrap.c +EXTRA_LDFLAGS = example.o example_wrap.o +TARGET = example_wrap +SWIGOPT = +DSRCS = *.d +DFLAGS = -ofrunme + + +all:: d + +d:: + cd $(WORKING_DIR); \ + $(MAKE) -f $(TOP)/Makefile EXTRA_CFLAGS='$(EXTRA_CFLAGS)' EXTRA_LDFLAGS='$(EXTRA_LDFLAGS)' SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT) -outcurrentdir ../example.i' TARGET='$(TARGET)' d; \ + $(MAKE) -f $(TOP)/Makefile DSRCS='$(DSRCS)' DFLAGS='$(DFLAGS)' d_compile + +clean:: + cd $(WORKING_DIR); \ + $(MAKE) -f $(TOP)/Makefile d_clean + +check: all diff --git a/Examples/d/simple/d1/runme.d b/Examples/d/simple/d1/runme.d new file mode 100644 index 000000000..1293f1839 --- /dev/null +++ b/Examples/d/simple/d1/runme.d @@ -0,0 +1,27 @@ +module runme; + +import tango.io.Stdout; +static import example; + +void main() { + /* + * Call our gcd() function. + */ + int x = 42; + int y = 105; + int g = example.gcd( x, y ); + Stdout.format( "The gcd of {} and {} is {}.", x, y, g ).newline; + + /* + * Manipulate the Foo global variable. + */ + + // Output its current value + Stdout.format( "Foo = {}", example.Foo ).newline; + + // Change its value + example.Foo = 3.1415926; + + // See if the change took effect + Stdout.format( "Foo = {}", example.Foo ).newline; +} diff --git a/Examples/d/simple/d2/runme.d b/Examples/d/simple/d2/runme.d new file mode 100644 index 000000000..7f278923b --- /dev/null +++ b/Examples/d/simple/d2/runme.d @@ -0,0 +1,27 @@ +module runme; + +import std.stdio; +static import example; + +void main() { + /* + * Call our gcd() function. + */ + int x = 42; + int y = 105; + int g = example.gcd(x, y); + writefln("The gcd of %s and %s is %s.", x, y, g); + + /* + * Manipulate the Foo global variable. + */ + + // Output its current value + writefln("Foo = %s", example.Foo); + + // Change its value + example.Foo = 3.1415926; + + // See if the change took effect + writefln("Foo = %s", example.Foo); +} diff --git a/Examples/d/simple/example.c b/Examples/d/simple/example.c new file mode 100644 index 000000000..1c2af789c --- /dev/null +++ b/Examples/d/simple/example.c @@ -0,0 +1,18 @@ +/* File : example.c */ + +/* A global variable */ +double Foo = 3.0; + +/* Compute the greatest common divisor of positive integers */ +int gcd(int x, int y) { + int g; + g = y; + while (x > 0) { + g = x; + x = y % x; + y = g; + } + return g; +} + + diff --git a/Examples/d/simple/example.i b/Examples/d/simple/example.i new file mode 100644 index 000000000..24093b9bf --- /dev/null +++ b/Examples/d/simple/example.i @@ -0,0 +1,7 @@ +/* File : example.i */ +%module example + +%inline %{ +extern int gcd(int x, int y); +extern double Foo; +%} diff --git a/Examples/d/variables/Makefile b/Examples/d/variables/Makefile new file mode 100644 index 000000000..312e6a9e9 --- /dev/null +++ b/Examples/d/variables/Makefile @@ -0,0 +1,28 @@ +ifeq (2,$(D_VERSION)) + WORKING_DIR = d2/ +else + WORKING_DIR = d1/ +endif + +TOP = ../../.. +SWIG = $(TOP)/../preinst-swig +EXTRA_CFLAGS = -I../ ../example.c example_wrap.c +EXTRA_LDFLAGS = example.o example_wrap.o +TARGET = example_wrap +SWIGOPT = +DSRCS = *.d +DFLAGS = -ofrunme + + +all:: d + +d:: + cd $(WORKING_DIR); \ + $(MAKE) -f $(TOP)/Makefile EXTRA_CFLAGS='$(EXTRA_CFLAGS)' EXTRA_LDFLAGS='$(EXTRA_LDFLAGS)' SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT) -outcurrentdir ../example.i' TARGET='$(TARGET)' d; \ + $(MAKE) -f $(TOP)/Makefile DSRCS='$(DSRCS)' DFLAGS='$(DFLAGS)' d_compile + +clean:: + cd $(WORKING_DIR); \ + $(MAKE) -f $(TOP)/Makefile d_clean + +check: all diff --git a/Examples/d/variables/d1/runme.d b/Examples/d/variables/d1/runme.d new file mode 100644 index 000000000..35c896bdc --- /dev/null +++ b/Examples/d/variables/d1/runme.d @@ -0,0 +1,71 @@ +// This example illustrates global variable access from C#. +module runme; + +import tango.io.Stdout; +static import example; + +void main() { + // Try to set the values of some global variables + example.ivar = 42; + example.svar = -31000; + example.lvar = 65537; + example.uivar = 123456; + example.usvar = 61000; + example.ulvar = 654321; + example.scvar = -13; + example.ucvar = 251; + example.cvar = 'S'; + example.fvar = 3.14159f; + example.dvar = 2.1828; + example.strvar = "Hello World"; + example.iptrvar = example.new_int(37); + example.ptptr = example.new_Point(37,42); + example.name = "Bill"; + + // Now print out the values of the variables + Stdout.formatln( "Variables (printed from D):" ); + Stdout.formatln( "ivar = {}", example.ivar ); + Stdout.formatln( "svar = {}", example.svar ); + Stdout.formatln( "lvar = {}", example.lvar ); + Stdout.formatln( "uivar = {}", example.uivar ); + Stdout.formatln( "usvar = {}", example.usvar ); + Stdout.formatln( "ulvar = {}", example.ulvar ); + Stdout.formatln( "scvar = {}", example.scvar ); + Stdout.formatln( "ucvar = {}", example.ucvar ); + Stdout.formatln( "fvar = {}", example.fvar ); + Stdout.formatln( "dvar = {}", example.dvar ); + Stdout.formatln( "cvar = {}", example.cvar ); + Stdout.formatln( "strvar = {}", example.strvar ); + Stdout.formatln( "cstrvar = {}", example.cstrvar ); + Stdout.formatln( "iptrvar = {}", example.iptrvar ); + Stdout.formatln( "name = {}", example.name ); + Stdout.formatln( "ptptr = {} {}", example.ptptr, example.Point_print(example.ptptr) ); + Stdout.formatln( "pt = {} {}", example.pt, example.Point_print(example.pt) ); + Stdout.formatln( "status = {}", example.status ); + + Stdout.formatln( "\nVariables (printed from the C library):" ); + example.print_vars(); + + Stdout.formatln( "\nNow I'm going to try and modify some read only variables:" ); + Stdout.formatln( "Checking that the read only variables are readonly..." ); + + Stdout( " 'path'..." ); + static if ( is( typeof( example.path = "a" ) ) ) + Stdout.formatln("Oh dear, this variable is not read only!"); + else + Stdout.formatln("Good."); + + Stdout( " 'status'..." ); + static if ( is( typeof( example.status = 2 ) ) ) + Stdout.formatln("Oh dear, this variable is not read only!"); + else + Stdout.formatln("Good."); + + Stdout.formatln( "\nI'm going to try and update a structure variable:" ); + + example.pt = example.ptptr; + + Stdout( "The new value is " ).flush; + example.pt_print(); + Stdout.formatln( "You should see the value {}", example.Point_print(example.ptptr) ); +} diff --git a/Examples/d/variables/d2/runme.d b/Examples/d/variables/d2/runme.d new file mode 100644 index 000000000..f80b81819 --- /dev/null +++ b/Examples/d/variables/d2/runme.d @@ -0,0 +1,71 @@ +// This example illustrates global variable access from C#. +module runme; + +import std.stdio; +static import example; + +void main() { + // Try to set the values of some global variables + example.ivar = 42; + example.svar = -31000; + example.lvar = 65537; + example.uivar = 123456; + example.usvar = 61000; + example.ulvar = 654321; + example.scvar = -13; + example.ucvar = 251; + example.cvar = 'S'; + example.fvar = 3.14159f; + example.dvar = 2.1828; + example.strvar = "Hello World"; + example.iptrvar = example.new_int(37); + example.ptptr = example.new_Point(37,42); + example.name = "Bill"; + + // Now print out the values of the variables + writefln( "Variables (printed from D):" ); + writefln( "ivar = %s", example.ivar ); + writefln( "svar = %s", example.svar ); + writefln( "lvar = %s", example.lvar ); + writefln( "uivar = %s", example.uivar ); + writefln( "usvar = %s", example.usvar ); + writefln( "ulvar = %s", example.ulvar ); + writefln( "scvar = %s", example.scvar ); + writefln( "ucvar = %s", example.ucvar ); + writefln( "fvar = %s", example.fvar ); + writefln( "dvar = %s", example.dvar ); + writefln( "cvar = %s", example.cvar ); + writefln( "strvar = %s", example.strvar ); + writefln( "cstrvar = %s", example.cstrvar ); + writefln( "iptrvar = %s", example.iptrvar ); + writefln( "name = %s", example.name ); + writefln( "ptptr = %s %s", example.ptptr, example.Point_print(example.ptptr) ); + writefln( "pt = %s %s", example.pt, example.Point_print(example.pt) ); + writefln( "status = %s", example.status ); + + writefln( "\nVariables (printed from the C library):" ); + example.print_vars(); + + writefln( "\nNow I'm going to try and modify some read only variables:" ); + writefln( "Checking that the read only variables are readonly..." ); + + writeln( " 'path'..." ); + static if ( is( typeof( example.path = "a" ) ) ) + writefln("Oh dear, this variable is not read only!"); + else + writefln("Good."); + + writeln( " 'status'..." ); + static if ( is( typeof( example.status = 2 ) ) ) + writefln("Oh dear, this variable is not read only!"); + else + writefln("Good."); + + writefln( "\nI'm going to try and update a structure variable:" ); + + example.pt = example.ptptr; + + write( "The new value is " ); + example.pt_print(); + writefln( "You should see the value %s", example.Point_print(example.ptptr) ); +} diff --git a/Examples/d/variables/example.c b/Examples/d/variables/example.c new file mode 100644 index 000000000..1bf9c120f --- /dev/null +++ b/Examples/d/variables/example.c @@ -0,0 +1,91 @@ +/* File : example.c */ + +/* I'm a file containing some C global variables */ + +/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ +#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) +# define _CRT_SECURE_NO_DEPRECATE +#endif + +#include +#include +#include "example.h" + +int ivar = 0; +short svar = 0; +long lvar = 0; +unsigned int uivar = 0; +unsigned short usvar = 0; +unsigned long ulvar = 0; +signed char scvar = 0; +unsigned char ucvar = 0; +char cvar = 0; +float fvar = 0; +double dvar = 0; +char *strvar = 0; +const char cstrvar[] = "Goodbye"; +int *iptrvar = 0; +char name[256] = "Dave"; +char path[256] = "/home/beazley"; + + +/* Global variables involving a structure */ +Point *ptptr = 0; +Point pt = { 10, 20 }; + +/* A variable that we will make read-only in the interface */ +int status = 1; + +/* A debugging function to print out their values */ + +void print_vars() { + printf("ivar = %d\n", ivar); + printf("svar = %d\n", svar); + printf("lvar = %ld\n", lvar); + printf("uivar = %u\n", uivar); + printf("usvar = %u\n", usvar); + printf("ulvar = %lu\n", ulvar); + printf("scvar = %d\n", scvar); + printf("ucvar = %u\n", ucvar); + printf("fvar = %g\n", fvar); + printf("dvar = %g\n", dvar); + printf("cvar = %c\n", cvar); + printf("strvar = %s\n", strvar ? strvar : "(null)"); + printf("cstrvar = %s\n", cstrvar ? cstrvar : "(null)"); + printf("iptrvar = %p\n", iptrvar); + printf("name = %s\n", name); + printf("ptptr = %p (%d, %d)\n", ptptr, ptptr ? ptptr->x : 0, ptptr ? ptptr->y : 0); + printf("pt = (%d, %d)\n", pt.x, pt.y); + printf("status = %d\n", status); +} + +/* A function to create an integer (to test iptrvar) */ + +int *new_int(int value) { + int *ip = (int *) malloc(sizeof(int)); + *ip = value; + return ip; +} + +/* A function to create a point */ + +Point *new_Point(int x, int y) { + Point *p = (Point *) malloc(sizeof(Point)); + p->x = x; + p->y = y; + return p; +} + +char * Point_print(Point *p) { + static char buffer[256]; + if (p) { + sprintf(buffer,"(%d, %d)", p->x,p->y); + } else { + sprintf(buffer,"null"); + } + return buffer; +} + +void pt_print() { + printf("(%d, %d)\n", pt.x, pt.y); +} diff --git a/Examples/d/variables/example.h b/Examples/d/variables/example.h new file mode 100644 index 000000000..0f7e89594 --- /dev/null +++ b/Examples/d/variables/example.h @@ -0,0 +1,6 @@ +/* File: example.h */ + +typedef struct { + int x,y; +} Point; + diff --git a/Examples/d/variables/example.i b/Examples/d/variables/example.i new file mode 100644 index 000000000..591b871ed --- /dev/null +++ b/Examples/d/variables/example.i @@ -0,0 +1,49 @@ +/* File : example.i */ +%module example +%{ +#include "example.h" +%} + +/* Some global variable declarations */ +%inline %{ +extern int ivar; +extern short svar; +extern long lvar; +extern unsigned int uivar; +extern unsigned short usvar; +extern unsigned long ulvar; +extern signed char scvar; +extern unsigned char ucvar; +extern char cvar; +extern float fvar; +extern double dvar; +extern char *strvar; +extern const char cstrvar[]; +extern int *iptrvar; +extern char name[256]; + +extern Point *ptptr; +extern Point pt; +%} + + +/* Some read-only variables */ + +%immutable; + +%inline %{ +extern int status; +extern char path[256]; +%} + +%mutable; + +/* Some helper functions to make it easier to test */ +%inline %{ +extern void print_vars(); +extern int *new_int(int value); +extern Point *new_Point(int x, int y); +extern char *Point_print(Point *p); +extern void pt_print(); +%} + diff --git a/Examples/test-suite/d/Makefile.in b/Examples/test-suite/d/Makefile.in new file mode 100644 index 000000000..2e9eb827f --- /dev/null +++ b/Examples/test-suite/d/Makefile.in @@ -0,0 +1,80 @@ +####################################################################### +# Makefile for D test-suite +####################################################################### + +LANGUAGE = d +srcdir = @srcdir@ +top_srcdir = ../@top_srcdir@ +top_builddir = ../@top_builddir@ + +ifeq (2,$(D_VERSION)) + VERSIONSUFFIX = .2 +else + VERSIONSUFFIX = .1 +endif + +TESTSUFFIX = _runme$(VERSIONSUFFIX).d + +CPP_TEST_CASES = \ + d_nativepointers \ + exception_partial_info + +include $(srcdir)/../common.mk + +# Override some variables from common.mk: + +TARGETSUFFIX = _wrap + +SWIGOPT+=-splitproxy -package $* + +# Rules for the different types of tests +%.cpptest: + $(setup) + +(cd $*$(VERSIONSUFFIX) && $(swig_and_compile_cpp)) + +$(run_testcase) + +%.ctest: + $(setup) + +(cd $*$(VERSIONSUFFIX) && $(swig_and_compile_c)) + +$(run_testcase) + +%.multicpptest: + $(setup) + +(cd $*$(VERSIONSUFFIX) && $(swig_and_compile_multi_cpp)) + +$(run_testcase) + +# Makes a directory for the testcase if it does not exist +setup = \ + if [ -f $(srcdir)/$(TESTPREFIX)$*$(TESTSUFFIX) ]; then \ + echo "$(ACTION)ing testcase $* (with run test) under $(LANGUAGE)" ; \ + else \ + echo "$(ACTION)ing testcase $* under $(LANGUAGE)" ; \ + fi; \ + if [ ! -d $*$(VERSIONSUFFIX) ]; then \ + mkdir $*$(VERSIONSUFFIX); \ + fi; \ + if [ ! -d $*$(VERSIONSUFFIX)/$* ]; then \ + mkdir $*$(VERSIONSUFFIX)/$*; \ + fi + +# Compiles D files then runs the testcase. A testcase is only run if +# a file is found which has _runme.d appended after the testcase name. +run_testcase = \ + if [ -f $(srcdir)/$(TESTPREFIX)$*$(TESTSUFFIX) ]; then \ + cd $*$(VERSIONSUFFIX) && \ + $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile \ + DFLAGS='-of$*_runme' \ + DSRCS='../$(srcdir)/$(TESTPREFIX)$*$(TESTSUFFIX) $*/*.d' d_compile && \ + env LD_LIBRARY_PATH=".:$$LD_LIBRARY_PATH" $(RUNTOOL) ./$*_runme; \ + else \ + cd $*$(VERSIONSUFFIX) && \ + $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile \ + DFLAGS='-c' \ + DSRCS='$*/*.d' d_compile && cd .. ; \ + fi + +# Clean: remove testcase directories +%.clean: + @if [ -d $* ]; then \ + rm -rf $*; \ + fi diff --git a/Examples/test-suite/d/README b/Examples/test-suite/d/README new file mode 100644 index 000000000..bb5372882 --- /dev/null +++ b/Examples/test-suite/d/README @@ -0,0 +1,7 @@ +D language module testsuite +--------------------------- + +Please see ../README for the common readme file. + +By default the D1 version is built, set D_VERSION=2 (in the environment or at +the make command line) to run it for D2 instead. diff --git a/Examples/test-suite/d/aggregate_runme.1.d b/Examples/test-suite/d/aggregate_runme.1.d new file mode 100644 index 000000000..a00d34c25 --- /dev/null +++ b/Examples/test-suite/d/aggregate_runme.1.d @@ -0,0 +1,25 @@ +module aggregate_runme; + +import aggregate.aggregate; + +void main() { + // Confirm that move() returns correct results under normal use. + int result = move(UP); + if (result != UP) throw new Exception("UP failed"); + + result = move(DOWN); + if (result != DOWN) throw new Exception("DOWN failed"); + + result = move(LEFT); + if (result != LEFT) throw new Exception("LEFT failed"); + + result = move(RIGHT); + if (result != RIGHT) throw new Exception("RIGHT failed"); + + // Confirm that move() raises an exception when the contract is violated. + try { + move(0); + throw new Exception("0 test failed"); + } + catch (Exception e) {} +} diff --git a/Examples/test-suite/d/aggregate_runme.2.d b/Examples/test-suite/d/aggregate_runme.2.d new file mode 100644 index 000000000..a00d34c25 --- /dev/null +++ b/Examples/test-suite/d/aggregate_runme.2.d @@ -0,0 +1,25 @@ +module aggregate_runme; + +import aggregate.aggregate; + +void main() { + // Confirm that move() returns correct results under normal use. + int result = move(UP); + if (result != UP) throw new Exception("UP failed"); + + result = move(DOWN); + if (result != DOWN) throw new Exception("DOWN failed"); + + result = move(LEFT); + if (result != LEFT) throw new Exception("LEFT failed"); + + result = move(RIGHT); + if (result != RIGHT) throw new Exception("RIGHT failed"); + + // Confirm that move() raises an exception when the contract is violated. + try { + move(0); + throw new Exception("0 test failed"); + } + catch (Exception e) {} +} diff --git a/Examples/test-suite/d/allprotected_runme.1.d b/Examples/test-suite/d/allprotected_runme.1.d new file mode 100644 index 000000000..82a180e66 --- /dev/null +++ b/Examples/test-suite/d/allprotected_runme.1.d @@ -0,0 +1,65 @@ +module allprotected_runme; + +import allprotected.Klass; +import allprotected.ProtectedBase; + +void main() { + auto mpb = new MyProtectedBase("MyProtectedBase"); + mpb.accessProtected(); +} + +class MyProtectedBase : ProtectedBase { +public: + this(char[] name) { + super(name); + } + + void accessProtected() { + char[] s = virtualMethod(); + if (s != "ProtectedBase") + throw new Exception("Failed"); + + Klass k = instanceMethod(new Klass("xyz")); + if (k.getName() != "xyz") + throw new Exception("Failed"); + + k = instanceOverloaded(new Klass("xyz")); + if (k.getName() != "xyz") + throw new Exception("Failed"); + + k = instanceOverloaded(new Klass("xyz"), "abc"); + if (k.getName() != "abc") + throw new Exception("Failed"); + + k = staticMethod(new Klass("abc")); + if (k.getName() != "abc") + throw new Exception("Failed"); + + k = staticOverloaded(new Klass("xyz")); + if (k.getName() != "xyz") + throw new Exception("Failed"); + + k = staticOverloaded(new Klass("xyz"), "abc"); + if (k.getName() != "abc") + throw new Exception("Failed"); + + instanceMemberVariable = 30; + int i = instanceMemberVariable; + if (i != 30) + throw new Exception("Failed"); + + staticMemberVariable = 40; + i = staticMemberVariable; + if (i != 40) + throw new Exception("Failed"); + + i = staticConstMemberVariable; + if (i != 20) + throw new Exception("Failed"); + + anEnum = ProtectedBase.AnEnum.EnumVal1; + ProtectedBase.AnEnum ae = anEnum; + if (ae != ProtectedBase.AnEnum.EnumVal1) + throw new Exception("Failed"); + } +} diff --git a/Examples/test-suite/d/allprotected_runme.2.d b/Examples/test-suite/d/allprotected_runme.2.d new file mode 100644 index 000000000..799230291 --- /dev/null +++ b/Examples/test-suite/d/allprotected_runme.2.d @@ -0,0 +1,65 @@ +module allprotected_runme; + +import allprotected.Klass; +import allprotected.ProtectedBase; + +void main() { + auto mpb = new MyProtectedBase("MyProtectedBase"); + mpb.accessProtected(); +} + +class MyProtectedBase : ProtectedBase { +public: + this(string name) { + super(name); + } + + void accessProtected() { + string s = virtualMethod(); + if (s != "ProtectedBase") + throw new Exception("Failed"); + + Klass k = instanceMethod(new Klass("xyz")); + if (k.getName() != "xyz") + throw new Exception("Failed"); + + k = instanceOverloaded(new Klass("xyz")); + if (k.getName() != "xyz") + throw new Exception("Failed"); + + k = instanceOverloaded(new Klass("xyz"), "abc"); + if (k.getName() != "abc") + throw new Exception("Failed"); + + k = staticMethod(new Klass("abc")); + if (k.getName() != "abc") + throw new Exception("Failed"); + + k = staticOverloaded(new Klass("xyz")); + if (k.getName() != "xyz") + throw new Exception("Failed"); + + k = staticOverloaded(new Klass("xyz"), "abc"); + if (k.getName() != "abc") + throw new Exception("Failed"); + + instanceMemberVariable = 30; + int i = instanceMemberVariable; + if (i != 30) + throw new Exception("Failed"); + + staticMemberVariable = 40; + i = staticMemberVariable; + if (i != 40) + throw new Exception("Failed"); + + i = staticConstMemberVariable; + if (i != 20) + throw new Exception("Failed"); + + anEnum = ProtectedBase.AnEnum.EnumVal1; + ProtectedBase.AnEnum ae = anEnum; + if (ae != ProtectedBase.AnEnum.EnumVal1) + throw new Exception("Failed"); + } +} diff --git a/Examples/test-suite/d/apply_strings_runme.1.d b/Examples/test-suite/d/apply_strings_runme.1.d new file mode 100644 index 000000000..960caa4ca --- /dev/null +++ b/Examples/test-suite/d/apply_strings_runme.1.d @@ -0,0 +1,12 @@ +module apply_strings_runme; + +import apply_strings.apply_strings; + +const char[] TEST_MESSAGE = "A message from target language to the C++ world and back again."; + +void main() { + if (UCharFunction(TEST_MESSAGE) != TEST_MESSAGE) throw new Exception("UCharFunction failed"); + if (SCharFunction(TEST_MESSAGE) != TEST_MESSAGE) throw new Exception("SCharFunction failed"); + auto pChar = CharFunction(null); + if (pChar !is null) throw new Exception("CharFunction failed"); +} diff --git a/Examples/test-suite/d/apply_strings_runme.2.d b/Examples/test-suite/d/apply_strings_runme.2.d new file mode 100644 index 000000000..86183f8a3 --- /dev/null +++ b/Examples/test-suite/d/apply_strings_runme.2.d @@ -0,0 +1,12 @@ +module apply_strings_runme; + +import apply_strings.apply_strings; + +enum string TEST_MESSAGE = "A message from target language to the C++ world and back again."; + +void main() { + if (UCharFunction(TEST_MESSAGE) != TEST_MESSAGE) throw new Exception("UCharFunction failed"); + if (SCharFunction(TEST_MESSAGE) != TEST_MESSAGE) throw new Exception("SCharFunction failed"); + auto pChar = CharFunction(null); + if (pChar !is null) throw new Exception("CharFunction failed"); +} diff --git a/Examples/test-suite/d/bools_runme.1.d b/Examples/test-suite/d/bools_runme.1.d new file mode 100644 index 000000000..f501b0762 --- /dev/null +++ b/Examples/test-suite/d/bools_runme.1.d @@ -0,0 +1,20 @@ +/// This is the bool runtime testcase. It checks that the C++ bool type works. +module bools_runme; + +import bools.bools; + +void main() { + bool t = true; + bool f = false; + + check_bo(f); + check_bo(t); +} + +void check_bo(bool input) { + for (int i = 0; i < 1000; ++i) { + if (bo(input) != input) { + throw new Exception("Runtime test check_bo failed."); + } + } +} diff --git a/Examples/test-suite/d/bools_runme.2.d b/Examples/test-suite/d/bools_runme.2.d new file mode 100644 index 000000000..f501b0762 --- /dev/null +++ b/Examples/test-suite/d/bools_runme.2.d @@ -0,0 +1,20 @@ +/// This is the bool runtime testcase. It checks that the C++ bool type works. +module bools_runme; + +import bools.bools; + +void main() { + bool t = true; + bool f = false; + + check_bo(f); + check_bo(t); +} + +void check_bo(bool input) { + for (int i = 0; i < 1000; ++i) { + if (bo(input) != input) { + throw new Exception("Runtime test check_bo failed."); + } + } +} diff --git a/Examples/test-suite/d/catches_runme.1.d b/Examples/test-suite/d/catches_runme.1.d new file mode 100644 index 000000000..55b18132d --- /dev/null +++ b/Examples/test-suite/d/catches_runme.1.d @@ -0,0 +1,33 @@ +module catches_runme; + +import catches.catches; + +void main() { + test({ test_catches(1); }, "C++ int exception thrown, value: 1"); + test({ test_catches(2); }, "two"); + test({ test_catches(3); }, "C++ ThreeException const & exception thrown"); + + test({ test_exception_specification(1); }, "C++ int exception thrown, value: 1"); + test({ test_exception_specification(2); }, "unknown exception"); + test({ test_exception_specification(3); }, "unknown exception"); + + test({ test_catches_all(1); }, "unknown exception"); +} + +void test(void delegate() command, char[] expectedMessage) { + bool didntThrow; + try { + command(); + didntThrow = true; + } catch (Exception e) { + if (e.msg != expectedMessage) { + throw new Exception("Failed to propagate C++ exception. Expected '" ~ + expectedMessage ~ "', but received '" ~ e.msg ~ "'."); + } + } + + if (didntThrow) { + throw new Exception("Failed to propagate C++ exception. Expected '" ~ + expectedMessage ~ "', but no exception was thrown."); + } +} diff --git a/Examples/test-suite/d/catches_runme.2.d b/Examples/test-suite/d/catches_runme.2.d new file mode 100644 index 000000000..508558485 --- /dev/null +++ b/Examples/test-suite/d/catches_runme.2.d @@ -0,0 +1,33 @@ +module catches_runme; + +import catches.catches; + +void main() { + test({ test_catches(1); }, "C++ int exception thrown, value: 1"); + test({ test_catches(2); }, "two"); + test({ test_catches(3); }, "C++ ThreeException const & exception thrown"); + + test({ test_exception_specification(1); }, "C++ int exception thrown, value: 1"); + test({ test_exception_specification(2); }, "unknown exception"); + test({ test_exception_specification(3); }, "unknown exception"); + + test({ test_catches_all(1); }, "unknown exception"); +} + +void test(void delegate() command, string expectedMessage) { + bool didntThrow; + try { + command(); + didntThrow = true; + } catch (Exception e) { + if (e.msg != expectedMessage) { + throw new Exception("Failed to propagate C++ exception. Expected '" ~ + expectedMessage ~ "', but received '" ~ e.msg ~ "'."); + } + } + + if (didntThrow) { + throw new Exception("Failed to propagate C++ exception. Expected '" ~ + expectedMessage ~ "', but no exception was thrown."); + } +} diff --git a/Examples/test-suite/d/char_strings_runme.1.d b/Examples/test-suite/d/char_strings_runme.1.d new file mode 100644 index 000000000..cde6fe0f7 --- /dev/null +++ b/Examples/test-suite/d/char_strings_runme.1.d @@ -0,0 +1,151 @@ +module char_strings_runme; + +import tango.text.convert.Integer; +import char_strings.char_strings; + +const char[] CPLUSPLUS_MSG = "A message from the deep dark world of C++, where anything is possible."; +const char[] OTHERLAND_MSG = "Little message from the safe world."; + +void main() { + const uint count = 10000; + uint i = 0; + + // get functions + for (i=0; i