commit: 3e4833a2e7127bd4d9ff8717ed7fbdf0f13fbffc
parent 4cf6becac0768dff13d5c8ceccc272f9da0f1b4e
Author: shinichiro.h <hamaji@nii.ac.jp>
Date: Fri, 22 Mar 2024 22:01:32 +0100
extract http://shinh.skr.jp/d/d_cpp.tar.bz2
Diffstat:
9 files changed, 911 insertions(+), 0 deletions(-)
diff --git a/d_cpp/Makefile b/d_cpp/Makefile
@@ -0,0 +1,22 @@
+CXX=g++
+DMD=dmd
+PERL=perl
+CPPFLAGS=-g
+DFLAGS=-g
+
+all: cpp_test
+
+cpp_test: cpp.o cpp_test.o
+ $(DMD) cpp_test $(CPPFLAGS) cpp.o
+
+cpp.o: d_cpp_interface.h cpp.cpp
+ $(CXX) $(CPPFLAGS) -c cpp.cpp
+
+cpp_test.o: cpp_inter.d cpp_test.d
+ $(DMD) $(DFLAGS) -c cpp_test.d
+
+cpp_inter.d: cpp.cpp
+ $(PERL) create_d_import.pl cpp.cpp cpp_inter.d
+
+clean:
+ rm -f *.o cpp_test cpp_inter.d
diff --git a/d_cpp/Makefile.win32 b/d_cpp/Makefile.win32
@@ -0,0 +1,22 @@
+CXX=sc
+DMD=dmd
+PERL=perl
+CPPFLAGS=-g
+DFLAGS=-g
+
+all: cpp_test
+
+cpp_test: cpp.obj cpp_test.obj
+ $(DMD) cpp_test $(CPPFLAGS) cpp.obj
+
+cpp.obj: d_cpp_interface.h cpp.cpp
+ $(CXX) $(CPPFLAGS) -c cpp.cpp
+
+cpp_test.obj: cpp_inter.d cpp_test.d
+ $(DMD) $(DFLAGS) -c cpp_test.d
+
+cpp_inter.d: cpp.cpp
+ $(PERL) create_d_import.pl cpp.cpp cpp_inter.d
+
+clean:
+ rm -f *.obj cpp_test cpp_inter.d
diff --git a/d_cpp/README b/d_cpp/README
@@ -0,0 +1,113 @@
+from D to C++
+
+If you are more familiar English than Japanese, please read README.en.
+
+・説明。
+
+C++ の遺産(死んでない) を D から触るためのものです。
+extern(C++) がサポートされた時、無意味に帰ります。
+
+C++ からは C のインターフェイスを提供して、
+D からそれを触るためのインポートライブラリも作らなければならない、
+ということを理解して頂ければ何がやりたいかがわかるかと思います。
+
+C 関数の宣言/定義は C++ ソースからプリプロセッサで、
+D 関数の宣言は C++ ソースから perl スクリプトで生成されます。
+
+README.en で説明を放棄するために作った図。
+
+generating process
+
+C++ using d_cpp -----------------------> C wrapper
+(interface definition) | preprocesser
+ |
+ --------------------> D import interface
+ perl script
+
+accessing process
+
+D client code --> D import interface --> C wrapper -->
+C++ using d_cpp --> C++ library code
+
+・ファイルの説明
+
+README:
+ これ。
+
+Makefile:
+ サンプルであるところの cpp_test 実行ファイルを作る。
+
+Makefile.win32:
+ windows での Makefile。
+
+d_cpp_interface.h:
+ C++ から C の宣言を生成するためのヘッダ。
+
+create_d_import.pl:
+ D の宣言を自動生成する perl スクリプト。
+
+cpp.cc:
+ サンプル、ユーザが書かにゃならんのはこの部分です。
+
+cpp_test.d:
+ D から cpp.cc を実際にいじってみるサンプル。
+
+create_d_cpp_interface.pl:
+ おまけ。d_cpp_interface.h を生成する。改造したい場合にどうぞ。
+
+cpp.cc の前半が D から使いたいクラスライブラリ、
+後半部が D で import するのに必要な作業です。
+
+cpp.cc に C 関数の定義がマクロで生成されます。
+このマクロは雑な perl script でパースするため、
+途中で絶対改行しないで下さい。
+
+D による import は create_d_import.pl を用いて
+import するためのファイルを作成して下さい。
+このファイルには宣言しか含まれないので、
+コンパイル・リンクする必要はありません。
+
+こんなややこしいものの説明を書く自信が無いので、
+cpp.cc を眺めて適当に理解して下さい。
+
+・その他
+
+とてもとてもα版です。ご意見頂けるととても嬉しいです。
+
+以下が実際的な実例となっています。
+http://user.ecc.u-tokyo.ac.jp/~s31552/wp/bulletss/
+
+修正 BSD ライセンスに従って配布します。
+
+Copyright (c) 2003, shinichiro.h All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * The name of the author may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+------------------
+ shinichiro.h
+ s31552@mail.ecc.u-tokyo.ac.jp
+ http://user.ecc.u-tokyo.ac.jp/~s31552/wp/
diff --git a/d_cpp/README.en b/d_cpp/README.en
@@ -0,0 +1,99 @@
+from D to C++
+
+I'm sorry of my poor English...
+
+* Introduction
+
+This package helps to access C++ library from D. If D compiler
+supports such as extern(C++), this package becomes useless.
+
+* Figure
+
+generating process
+
+C++ using d_cpp -----------------------> C wrapper
+(interface definition) | preprocesser
+ |
+ --------------------> D import interface
+ perl script
+
+accessing process
+
+D client code --> D import interface --> C wrapper -->
+C++ using d_cpp --> C++ library code
+
+* File Description
+
+README:
+ this file.
+
+Makefile:
+ linux's makefile.
+
+Makefile.win32:
+ windows's makefile.
+
+d_cpp_interface.h:
+ helps C++ using d_cpp to C wrapper
+
+create_d_import.pl:
+ helps C++ using d_cpp to D import interface
+
+cpp.cc:
+ sample of C++ using d_cpp and C++ library code.
+
+cpp_test.d:
+ sample of D client code.
+
+create_d_cpp_interface.pl:
+ I created d_cpp_interface.h with this script.
+
+* Misc
+
+This package is alpha release. I'm glad if you give me advice.
+
+More complicated sample is available as "barrage 360 deg.",
+a BulletML viewer.
+
+- Japanese page
+http://user.ecc.u-tokyo.ac.jp/~s31552/wp/bulletss/
+- Download
+http://user.ecc.u-tokyo.ac.jp/~s31552/wp/bulletss/bulletss.tar.bz2
+- BulletML
+http://www.asahi-net.or.jp/~cs8k-cyu/bulletml/index_e.html
+
+This package distributes under the modified BSD license
+
+Copyright (c) 2003, shinichiro.h All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * The name of the author may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+TTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+------------------
+ shinichiro.h
+ s31552@mail.ecc.u-tokyo.ac.jp
+ http://user.ecc.u-tokyo.ac.jp/~s31552/wp/
+
diff --git a/d_cpp/cpp.cpp b/d_cpp/cpp.cpp
@@ -0,0 +1,97 @@
+class C {
+public:
+ C() {}
+ C(int a) : a_(a) {}
+
+ int a() const { return a_; }
+ void setA(int a) { a_ = a; }
+
+ void f2(int, int) {}
+ void f3(int, int, int) {}
+ void f4(int, int, int, int) {}
+ void f5(int, int, int, int, int) {}
+ void f6(int, int, int, int, int, int) {}
+ void f7(int, int, int, int, int, int, int) {}
+ void f8(int, int, int, int, int, int, int, int) {}
+ void f9(int, int, int, int, int, int, int, int, int) {}
+
+ void over_load(int a) { a_ = a; }
+ void over_load(char a) { a_ = a-48; }
+
+ static int sf0() { return 6; }
+ static int sf1(int) { return 7; }
+
+private:
+ int a_;
+};
+
+template <class T_> class TC {
+public:
+ T_ f() { return 5; }
+ template <class T2_>
+ T2_ tf() { return 6; }
+};
+
+class I {
+public:
+ int load_callback() {
+ return callback();
+ }
+ int load_callback2(int x, int y) {
+ return callback2(x, y);
+ }
+ virtual int callback() =0;
+ virtual int callback2(int, int) =0;
+};
+
+#include "d_cpp_interface.h"
+
+extern "C" {
+ D_CPP_CLASS(C, D_C)
+ D_CPP_NEW_0(C, D_C_new)
+ D_CPP_NEW_1(C, D_C_new_1, int)
+ D_CPP_DELETE(C, D_C_delete)
+
+ D_CPP_METHOD_0(C, a, D_C_a, int)
+ D_CPP_METHOD_1(C, setA, D_C_setA, void, int)
+
+ D_CPP_METHOD_2(C, f2, D_C_f2, void, int, int)
+ D_CPP_METHOD_3(C, f3, D_C_f3, void, int, int, int)
+ D_CPP_METHOD_4(C, f4, D_C_f4, void, int, int, int, int)
+ D_CPP_METHOD_5(C, f5, D_C_f5, void, int, int, int, int, int)
+ D_CPP_METHOD_6(C, f6, D_C_f6, void, int, int, int, int, int, int)
+ D_CPP_METHOD_7(C, f7, D_C_f7, void, int, int, int, int, int, int, int)
+ D_CPP_METHOD_8(C, f8, D_C_f8, void, int, int, int, int, int, int, int, int)
+ D_CPP_METHOD_9(C, f9, D_C_f9, void, int, int, int, int, int, int, int, int, int)
+
+ D_CPP_METHOD_1(C, over_load, D_C_over_load_int, void, int)
+ D_CPP_METHOD_1(C, over_load, D_C_over_load_char, void, char)
+
+ D_CPP_CLASS(TC<int>, D_TC_int)
+ D_CPP_NEW_0(TC<int>, D_TC_int_new)
+ D_CPP_METHOD_0(TC<int>, f, D_TC_int_f, int)
+ D_CPP_METHOD_0(TC<int>, tf<int>, D_TC_int_tf, int)
+ D_CPP_DELETE(TC<int>, D_TC_int_delete)
+
+ D_CPP_STATIC_METHOD_0(C, sf0, D_C_sf0, int)
+ D_CPP_STATIC_METHOD_1(C, sf1, D_C_sf1, int, int)
+
+}
+
+// inherit
+
+D_CPP_BASE_CLASS_OPEN(I, D_I)
+D_CPP_VIRTUAL_METHOD_0(D_I, callback, int)
+D_CPP_VIRTUAL_METHOD_2(D_I, callback2, int, int, int)
+D_CPP_BASE_CLASS_CLOSE()
+
+extern "C" {
+ D_CPP_CLASS(D_I, D_I)
+ D_CPP_NEW_0(D_I, D_I_new)
+ D_CPP_METHOD_0(D_I, load_callback, D_I_load_callback, int)
+ D_CPP_METHOD_2(D_I, load_callback2, D_I_load_callback2, int, int, int)
+ D_CPP_VIRTUAL_METHOD_SETTER_0(D_I, callback, D_I_setCallbackFunc, int)
+ D_CPP_VIRTUAL_METHOD_SETTER_2(D_I, callback2, D_I_setCallback2Func, int, int, int)
+ D_CPP_DELETE(D_I, D_I_delete)
+}
+
diff --git a/d_cpp/cpp_test.d b/d_cpp/cpp_test.d
@@ -0,0 +1,45 @@
+import cpp_inter;
+
+import stream;
+import string;
+
+extern (C) {
+ int return7(D_I* i) { return 7; }
+ int add(D_I* i, int x, int y) { return x+y; }
+}
+
+int main() {
+ D_C* c = D_C_new_1(1);
+ stdout.writeLine(string.toString(D_C_a(c)));
+ D_C_delete(c);
+
+ c = D_C_new();
+ D_C_setA(c, 2);
+ stdout.writeLine(string.toString(D_C_a(c)));
+
+ D_C_f2(c, 0, 0);
+ D_C_f5(c, 0,0,0,0,0);
+ D_C_f9(c, 0,0,0,0,0,0,0,0,0);
+
+ D_C_over_load_int(c, 3);
+ stdout.writeLine(string.toString(D_C_a(c)));
+
+ D_C_over_load_char(c, '4');
+ stdout.writeLine(string.toString(D_C_a(c)));
+
+ D_TC_int* tc = D_TC_int_new();
+ stdout.writeLine(string.toString(D_TC_int_f(tc)));
+ stdout.writeLine(string.toString(D_TC_int_tf(tc)));
+
+ D_C_delete(c);
+ D_TC_int_delete(tc);
+
+ D_I* i = D_I_new();
+ D_I_setCallbackFunc(i, &return7);
+ D_I_setCallback2Func(i, &add);
+ stdout.writeLine(string.toString(D_I_load_callback(i)));
+ stdout.writeLine(string.toString(D_I_load_callback2(i, 3, 5)));
+ D_I_delete(i);
+
+ return 0;
+}
diff --git a/d_cpp/create_d_cpp_interface.pl b/d_cpp/create_d_cpp_interface.pl
@@ -0,0 +1,127 @@
+use strict;
+
+print "#define D_CPP_CLASS(CLASS, CLASS_NAME) ;\n";
+print "\n";
+
+for (my $i = 0; $i < 10; $i++) {
+ print "#define D_CPP_NEW_$i(CLASS, NEW_NAME";
+ my @args;
+ my @args2;
+ for (my $j = 1; $j <= $i; $j++) {
+ print ", ARG$j";
+ push @args, "ARG$j arg$j";
+ push @args2, "arg$j";
+ }
+ print ") \\\n";
+ my $argStr = join ', ', @args;
+ my $argStr2 = join ', ', @args2;
+
+ print "CLASS* NEW_NAME($argStr) { \\\n";
+ print " return new CLASS($argStr2); \\\n";
+ print "}\n";
+
+ print "\n";
+}
+
+print "#define D_CPP_DELETE(CLASS, DELETE_NAME) \\\n";
+print "void DELETE_NAME(CLASS* c) { delete c; } \n";
+print "\n";
+
+for (my $i = 0; $i < 10; $i++) {
+ print "#define D_CPP_METHOD_$i(CLASS, METHOD, METHOD_NAME, RETURN";
+ my $argStr;
+ my @args2;
+ for (my $j = 1; $j <= $i; $j++) {
+ print ", ARG$j";
+ $argStr .= ", ARG$j arg$j";
+ push @args2, "arg$j";
+ }
+ print ") \\\n";
+ my $argStr2 = join ', ', @args2;
+
+ print "RETURN METHOD_NAME(CLASS* c$argStr) { \\\n";
+ print " return c->METHOD($argStr2); \\\n";
+ print "}\n";
+
+ print "\n";
+}
+
+for (my $i = 0; $i < 10; $i++) {
+ print "#define D_CPP_STATIC_METHOD_$i(CLASS, METHOD, METHOD_NAME, RETURN";
+ my @args;
+ my @args2;
+ for (my $j = 1; $j <= $i; $j++) {
+ print ", ARG$j";
+ push @args, "ARG$j arg$j";
+ push @args2, "arg$j";
+ }
+ print ") \\\n";
+ my $argStr = join ', ', @args;;
+ my $argStr2 = join ', ', @args2;
+
+ print "RETURN METHOD_NAME($argStr) { \\\n";
+ print " return CLASS::METHOD($argStr2); \\\n";
+ print "}\n";
+
+ print "\n";
+}
+
+print "#define D_CPP_BASE_CLASS_OPEN(BASE, BASE_NAME) \\\n";
+print "struct BASE_NAME : public BASE { \n";
+
+for (my $i = 0; $i < 10; $i++) {
+ print "#define D_CPP_VIRTUAL_METHOD_$i(CLASS, METHOD, RETURN";
+ my @args;
+ my @args2;
+ my @args3;
+ for (my $j = 1; $j <= $i; $j++) {
+ print ", ARG$j";
+ push @args, "ARG$j arg$j";
+ push @args2, ", arg$j";
+ push @args3, ", ARG$j";
+ }
+ print ") \\\n";
+ my $argStr = join ', ', @args;;
+ my $argStr2 = join '', @args2;
+ my $argStr3 = join '', @args3;
+
+ print " virtual RETURN METHOD($argStr) { \\\n";
+ print " return D_##METHOD##_fp(this $argStr2); \\\n";
+ print " } \\\n";
+ print " void D_set_##METHOD(RETURN (*fp) (CLASS* $argStr3)) { \\\n";
+ print " D_##METHOD##_fp = fp; \\\n";
+ print " } \\\n";
+ print " RETURN (*D_##METHOD##_fp) (CLASS*$argStr3); \n";
+
+ print "\n";
+}
+
+for (my $i = 0; $i < 10; $i++) {
+ print "#define D_CPP_VIRTUAL_METHOD_SETTER_$i(CLASS, METHOD, SETTER_NAME, RETURN";
+ my @args;
+ my @args2;
+ my @args3;
+ for (my $j = 1; $j <= $i; $j++) {
+ print ", ARG$j";
+ push @args, "ARG$j arg$j";
+ push @args2, ", arg$j";
+ push @args3, ", ARG$j";
+ }
+ print ") \\\n";
+ my $argStr = join ', ', @args;;
+ my $argStr2 = join '', @args2;
+ my $argStr3 = join '', @args3;
+
+ print "void SETTER_NAME(CLASS* c, RETURN (*fp) (CLASS*$argStr3)) { \\\n";
+ print " c->D_set_##METHOD(fp); \\\n";
+ print "}\n";
+
+ print "\n";
+}
+
+print "#define D_CPP_BASE_CLASS_CLOSE() \\\n";
+print "};\n";
+print "\n";
+
+print "#define D_CPP_D_DECLARE(arg) ; \n";
+print "\n";
diff --git a/d_cpp/create_d_import.pl b/d_cpp/create_d_import.pl
@@ -0,0 +1,84 @@
+#!/usr/bin/env perl
+
+use strict;
+
+my @args;
+
+my $in = *STDIN;
+if ($ARGV[0]) {
+ open $in, $ARGV[0];
+}
+
+my $out = *STDOUT;
+if ($ARGV[1]) {
+ open $out, "> $ARGV[1]";
+}
+
+print $out "extern (C) {\n";
+while (<$in>) {
+ s/const //g;
+ if (parseArgs("D_CPP_CLASS")) {
+ my $class = shift @args;
+ my $name = shift @args;
+ print $out "alias int $name;\n";
+ }
+ if (parseArgs("D_CPP_NEW_\\d")) {
+ my $class = shift @args;
+ my $name = shift @args;
+ my $args = join ', ', @args;
+ print $out "int* $name($args);\n";
+ }
+ if (parseArgs("D_CPP_DELETE")) {
+ my $class = shift @args;
+ my $name = shift @args;
+ print $out "void $name(int*);\n";
+ }
+ if (parseArgs("D_CPP_METHOD_\\d")) {
+ my $class = shift @args;
+ my $method = shift @args;
+ my $name = shift @args;
+ my $ret = shift @args;
+ my $args = join ', ', @args;
+ if ($args) {
+ $args = ", $args";
+ }
+ print $out "$ret $name(int* $args);\n";
+ }
+ if (parseArgs("D_CPP_STATIC_METHOD_\\d")) {
+ my $class = shift @args;
+ my $method = shift @args;
+ my $name = shift @args;
+ my $ret = shift @args;
+ my $args = join ', ', @args;
+ print $out "$ret $name($args);\n";
+ }
+ if (parseArgs("D_CPP_VIRTUAL_METHOD_SETTER_\\d")) {
+ my $class = shift @args;
+ my $method = shift @args;
+ my $name = shift @args;
+ my $ret = shift @args;
+ my $args = join ', ', @args;
+ if ($args) {
+ $args = ", $args";
+ }
+ print $out "void $name(int*, $ret (*fp) (int* $args)); \n";
+ }
+ if (parseArgs("D_CPP_D_DECLARE")) {
+ my $declare = shift @args;
+ $declare =~ s/^\"//;
+ $declare =~ s/\"$//;
+ print $out "$declare\n";
+ }
+}
+print $out "}\n";
+
+sub parseArgs {
+ my $name = shift;
+ if (/$name\s*\(([^\)]*)\)/) {
+ @args = split /\s*,\s*/, $1;
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
diff --git a/d_cpp/d_cpp_interface.h b/d_cpp/d_cpp_interface.h
@@ -0,0 +1,302 @@
+#define D_CPP_CLASS(CLASS, CLASS_NAME) ;
+
+#define D_CPP_NEW_0(CLASS, NEW_NAME) \
+CLASS* NEW_NAME() { \
+ return new CLASS(); \
+}
+
+#define D_CPP_NEW_1(CLASS, NEW_NAME, ARG1) \
+CLASS* NEW_NAME(ARG1 arg1) { \
+ return new CLASS(arg1); \
+}
+
+#define D_CPP_NEW_2(CLASS, NEW_NAME, ARG1, ARG2) \
+CLASS* NEW_NAME(ARG1 arg1, ARG2 arg2) { \
+ return new CLASS(arg1, arg2); \
+}
+
+#define D_CPP_NEW_3(CLASS, NEW_NAME, ARG1, ARG2, ARG3) \
+CLASS* NEW_NAME(ARG1 arg1, ARG2 arg2, ARG3 arg3) { \
+ return new CLASS(arg1, arg2, arg3); \
+}
+
+#define D_CPP_NEW_4(CLASS, NEW_NAME, ARG1, ARG2, ARG3, ARG4) \
+CLASS* NEW_NAME(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4) { \
+ return new CLASS(arg1, arg2, arg3, arg4); \
+}
+
+#define D_CPP_NEW_5(CLASS, NEW_NAME, ARG1, ARG2, ARG3, ARG4, ARG5) \
+CLASS* NEW_NAME(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5) { \
+ return new CLASS(arg1, arg2, arg3, arg4, arg5); \
+}
+
+#define D_CPP_NEW_6(CLASS, NEW_NAME, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) \
+CLASS* NEW_NAME(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6) { \
+ return new CLASS(arg1, arg2, arg3, arg4, arg5, arg6); \
+}
+
+#define D_CPP_NEW_7(CLASS, NEW_NAME, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) \
+CLASS* NEW_NAME(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7) { \
+ return new CLASS(arg1, arg2, arg3, arg4, arg5, arg6, arg7); \
+}
+
+#define D_CPP_NEW_8(CLASS, NEW_NAME, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8) \
+CLASS* NEW_NAME(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8) { \
+ return new CLASS(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \
+}
+
+#define D_CPP_NEW_9(CLASS, NEW_NAME, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8, ARG9) \
+CLASS* NEW_NAME(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9) { \
+ return new CLASS(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); \
+}
+
+#define D_CPP_DELETE(CLASS, DELETE_NAME) \
+void DELETE_NAME(CLASS* c) { delete c; }
+
+#define D_CPP_METHOD_0(CLASS, METHOD, METHOD_NAME, RETURN) \
+RETURN METHOD_NAME(CLASS* c) { \
+ return c->METHOD(); \
+}
+
+#define D_CPP_METHOD_1(CLASS, METHOD, METHOD_NAME, RETURN, ARG1) \
+RETURN METHOD_NAME(CLASS* c, ARG1 arg1) { \
+ return c->METHOD(arg1); \
+}
+
+#define D_CPP_METHOD_2(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2) \
+RETURN METHOD_NAME(CLASS* c, ARG1 arg1, ARG2 arg2) { \
+ return c->METHOD(arg1, arg2); \
+}
+
+#define D_CPP_METHOD_3(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2, ARG3) \
+RETURN METHOD_NAME(CLASS* c, ARG1 arg1, ARG2 arg2, ARG3 arg3) { \
+ return c->METHOD(arg1, arg2, arg3); \
+}
+
+#define D_CPP_METHOD_4(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2, ARG3, ARG4) \
+RETURN METHOD_NAME(CLASS* c, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4) { \
+ return c->METHOD(arg1, arg2, arg3, arg4); \
+}
+
+#define D_CPP_METHOD_5(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \
+RETURN METHOD_NAME(CLASS* c, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5) { \
+ return c->METHOD(arg1, arg2, arg3, arg4, arg5); \
+}
+
+#define D_CPP_METHOD_6(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) \
+RETURN METHOD_NAME(CLASS* c, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6) { \
+ return c->METHOD(arg1, arg2, arg3, arg4, arg5, arg6); \
+}
+
+#define D_CPP_METHOD_7(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) \
+RETURN METHOD_NAME(CLASS* c, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7) { \
+ return c->METHOD(arg1, arg2, arg3, arg4, arg5, arg6, arg7); \
+}
+
+#define D_CPP_METHOD_8(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8) \
+RETURN METHOD_NAME(CLASS* c, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8) { \
+ return c->METHOD(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \
+}
+
+#define D_CPP_METHOD_9(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8, ARG9) \
+RETURN METHOD_NAME(CLASS* c, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9) { \
+ return c->METHOD(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); \
+}
+
+#define D_CPP_STATIC_METHOD_0(CLASS, METHOD, METHOD_NAME, RETURN) \
+RETURN METHOD_NAME() { \
+ return CLASS::METHOD(); \
+}
+
+#define D_CPP_STATIC_METHOD_1(CLASS, METHOD, METHOD_NAME, RETURN, ARG1) \
+RETURN METHOD_NAME(ARG1 arg1) { \
+ return CLASS::METHOD(arg1); \
+}
+
+#define D_CPP_STATIC_METHOD_2(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2) \
+RETURN METHOD_NAME(ARG1 arg1, ARG2 arg2) { \
+ return CLASS::METHOD(arg1, arg2); \
+}
+
+#define D_CPP_STATIC_METHOD_3(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2, ARG3) \
+RETURN METHOD_NAME(ARG1 arg1, ARG2 arg2, ARG3 arg3) { \
+ return CLASS::METHOD(arg1, arg2, arg3); \
+}
+
+#define D_CPP_STATIC_METHOD_4(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2, ARG3, ARG4) \
+RETURN METHOD_NAME(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4) { \
+ return CLASS::METHOD(arg1, arg2, arg3, arg4); \
+}
+
+#define D_CPP_STATIC_METHOD_5(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \
+RETURN METHOD_NAME(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5) { \
+ return CLASS::METHOD(arg1, arg2, arg3, arg4, arg5); \
+}
+
+#define D_CPP_STATIC_METHOD_6(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) \
+RETURN METHOD_NAME(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6) { \
+ return CLASS::METHOD(arg1, arg2, arg3, arg4, arg5, arg6); \
+}
+
+#define D_CPP_STATIC_METHOD_7(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) \
+RETURN METHOD_NAME(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7) { \
+ return CLASS::METHOD(arg1, arg2, arg3, arg4, arg5, arg6, arg7); \
+}
+
+#define D_CPP_STATIC_METHOD_8(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8) \
+RETURN METHOD_NAME(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8) { \
+ return CLASS::METHOD(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \
+}
+
+#define D_CPP_STATIC_METHOD_9(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8, ARG9) \
+RETURN METHOD_NAME(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9) { \
+ return CLASS::METHOD(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); \
+}
+
+#define D_CPP_BASE_CLASS_OPEN(BASE, BASE_NAME) \
+struct BASE_NAME : public BASE {
+#define D_CPP_VIRTUAL_METHOD_0(CLASS, METHOD, RETURN) \
+ virtual RETURN METHOD() { \
+ return D_##METHOD##_fp(this ); \
+ } \
+ void D_set_##METHOD(RETURN (*fp) (CLASS* )) { \
+ D_##METHOD##_fp = fp; \
+ } \
+ RETURN (*D_##METHOD##_fp) (CLASS*);
+
+#define D_CPP_VIRTUAL_METHOD_1(CLASS, METHOD, RETURN, ARG1) \
+ virtual RETURN METHOD(ARG1 arg1) { \
+ return D_##METHOD##_fp(this , arg1); \
+ } \
+ void D_set_##METHOD(RETURN (*fp) (CLASS* , ARG1)) { \
+ D_##METHOD##_fp = fp; \
+ } \
+ RETURN (*D_##METHOD##_fp) (CLASS*, ARG1);
+
+#define D_CPP_VIRTUAL_METHOD_2(CLASS, METHOD, RETURN, ARG1, ARG2) \
+ virtual RETURN METHOD(ARG1 arg1, ARG2 arg2) { \
+ return D_##METHOD##_fp(this , arg1, arg2); \
+ } \
+ void D_set_##METHOD(RETURN (*fp) (CLASS* , ARG1, ARG2)) { \
+ D_##METHOD##_fp = fp; \
+ } \
+ RETURN (*D_##METHOD##_fp) (CLASS*, ARG1, ARG2);
+
+#define D_CPP_VIRTUAL_METHOD_3(CLASS, METHOD, RETURN, ARG1, ARG2, ARG3) \
+ virtual RETURN METHOD(ARG1 arg1, ARG2 arg2, ARG3 arg3) { \
+ return D_##METHOD##_fp(this , arg1, arg2, arg3); \
+ } \
+ void D_set_##METHOD(RETURN (*fp) (CLASS* , ARG1, ARG2, ARG3)) { \
+ D_##METHOD##_fp = fp; \
+ } \
+ RETURN (*D_##METHOD##_fp) (CLASS*, ARG1, ARG2, ARG3);
+
+#define D_CPP_VIRTUAL_METHOD_4(CLASS, METHOD, RETURN, ARG1, ARG2, ARG3, ARG4) \
+ virtual RETURN METHOD(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4) { \
+ return D_##METHOD##_fp(this , arg1, arg2, arg3, arg4); \
+ } \
+ void D_set_##METHOD(RETURN (*fp) (CLASS* , ARG1, ARG2, ARG3, ARG4)) { \
+ D_##METHOD##_fp = fp; \
+ } \
+ RETURN (*D_##METHOD##_fp) (CLASS*, ARG1, ARG2, ARG3, ARG4);
+
+#define D_CPP_VIRTUAL_METHOD_5(CLASS, METHOD, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \
+ virtual RETURN METHOD(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5) { \
+ return D_##METHOD##_fp(this , arg1, arg2, arg3, arg4, arg5); \
+ } \
+ void D_set_##METHOD(RETURN (*fp) (CLASS* , ARG1, ARG2, ARG3, ARG4, ARG5)) { \
+ D_##METHOD##_fp = fp; \
+ } \
+ RETURN (*D_##METHOD##_fp) (CLASS*, ARG1, ARG2, ARG3, ARG4, ARG5);
+
+#define D_CPP_VIRTUAL_METHOD_6(CLASS, METHOD, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) \
+ virtual RETURN METHOD(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6) { \
+ return D_##METHOD##_fp(this , arg1, arg2, arg3, arg4, arg5, arg6); \
+ } \
+ void D_set_##METHOD(RETURN (*fp) (CLASS* , ARG1, ARG2, ARG3, ARG4, ARG5, ARG6)) { \
+ D_##METHOD##_fp = fp; \
+ } \
+ RETURN (*D_##METHOD##_fp) (CLASS*, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
+
+#define D_CPP_VIRTUAL_METHOD_7(CLASS, METHOD, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) \
+ virtual RETURN METHOD(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7) { \
+ return D_##METHOD##_fp(this , arg1, arg2, arg3, arg4, arg5, arg6, arg7); \
+ } \
+ void D_set_##METHOD(RETURN (*fp) (CLASS* , ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7)) { \
+ D_##METHOD##_fp = fp; \
+ } \
+ RETURN (*D_##METHOD##_fp) (CLASS*, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
+
+#define D_CPP_VIRTUAL_METHOD_8(CLASS, METHOD, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8) \
+ virtual RETURN METHOD(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8) { \
+ return D_##METHOD##_fp(this , arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \
+ } \
+ void D_set_##METHOD(RETURN (*fp) (CLASS* , ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8)) { \
+ D_##METHOD##_fp = fp; \
+ } \
+ RETURN (*D_##METHOD##_fp) (CLASS*, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
+
+#define D_CPP_VIRTUAL_METHOD_9(CLASS, METHOD, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8, ARG9) \
+ virtual RETURN METHOD(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9) { \
+ return D_##METHOD##_fp(this , arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); \
+ } \
+ void D_set_##METHOD(RETURN (*fp) (CLASS* , ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8, ARG9)) { \
+ D_##METHOD##_fp = fp; \
+ } \
+ RETURN (*D_##METHOD##_fp) (CLASS*, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8, ARG9);
+
+#define D_CPP_VIRTUAL_METHOD_SETTER_0(CLASS, METHOD, SETTER_NAME, RETURN) \
+void SETTER_NAME(CLASS* c, RETURN (*fp) (CLASS*)) { \
+ c->D_set_##METHOD(fp); \
+}
+
+#define D_CPP_VIRTUAL_METHOD_SETTER_1(CLASS, METHOD, SETTER_NAME, RETURN, ARG1) \
+void SETTER_NAME(CLASS* c, RETURN (*fp) (CLASS*, ARG1)) { \
+ c->D_set_##METHOD(fp); \
+}
+
+#define D_CPP_VIRTUAL_METHOD_SETTER_2(CLASS, METHOD, SETTER_NAME, RETURN, ARG1, ARG2) \
+void SETTER_NAME(CLASS* c, RETURN (*fp) (CLASS*, ARG1, ARG2)) { \
+ c->D_set_##METHOD(fp); \
+}
+
+#define D_CPP_VIRTUAL_METHOD_SETTER_3(CLASS, METHOD, SETTER_NAME, RETURN, ARG1, ARG2, ARG3) \
+void SETTER_NAME(CLASS* c, RETURN (*fp) (CLASS*, ARG1, ARG2, ARG3)) { \
+ c->D_set_##METHOD(fp); \
+}
+
+#define D_CPP_VIRTUAL_METHOD_SETTER_4(CLASS, METHOD, SETTER_NAME, RETURN, ARG1, ARG2, ARG3, ARG4) \
+void SETTER_NAME(CLASS* c, RETURN (*fp) (CLASS*, ARG1, ARG2, ARG3, ARG4)) { \
+ c->D_set_##METHOD(fp); \
+}
+
+#define D_CPP_VIRTUAL_METHOD_SETTER_5(CLASS, METHOD, SETTER_NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \
+void SETTER_NAME(CLASS* c, RETURN (*fp) (CLASS*, ARG1, ARG2, ARG3, ARG4, ARG5)) { \
+ c->D_set_##METHOD(fp); \
+}
+
+#define D_CPP_VIRTUAL_METHOD_SETTER_6(CLASS, METHOD, SETTER_NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) \
+void SETTER_NAME(CLASS* c, RETURN (*fp) (CLASS*, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6)) { \
+ c->D_set_##METHOD(fp); \
+}
+
+#define D_CPP_VIRTUAL_METHOD_SETTER_7(CLASS, METHOD, SETTER_NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) \
+void SETTER_NAME(CLASS* c, RETURN (*fp) (CLASS*, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7)) { \
+ c->D_set_##METHOD(fp); \
+}
+
+#define D_CPP_VIRTUAL_METHOD_SETTER_8(CLASS, METHOD, SETTER_NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8) \
+void SETTER_NAME(CLASS* c, RETURN (*fp) (CLASS*, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8)) { \
+ c->D_set_##METHOD(fp); \
+}
+
+#define D_CPP_VIRTUAL_METHOD_SETTER_9(CLASS, METHOD, SETTER_NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8, ARG9) \
+void SETTER_NAME(CLASS* c, RETURN (*fp) (CLASS*, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8, ARG9)) { \
+ c->D_set_##METHOD(fp); \
+}
+
+#define D_CPP_BASE_CLASS_CLOSE() \
+};
+
+#define D_CPP_D_DECLARE(arg) ;
+