├── .gitignore ├── CODE-OF-CONDUCT.md ├── LICENSE ├── Makefile.am ├── Makefile.include ├── README ├── autogen.sh ├── configure.ac ├── cxxi.sln ├── examples ├── Hello │ ├── Hello.cpp │ ├── Hello.cs │ ├── Hello.h │ └── Makefile.am ├── Makefile.am └── qt │ ├── Makefile.am │ ├── demos │ └── hello.cs │ ├── qt-gui-filters.xml │ ├── qt-gui.cpp │ ├── qt-gui.h │ └── src │ ├── QApplication.cs │ ├── QCoreApplication.cs │ ├── QFlags.cs │ ├── QPoint.cs │ ├── QPushButton.cs │ ├── QSize.cs │ ├── QString.cs │ └── QWidget.cs ├── m4 ├── expansions.m4 └── pkg.m4 ├── src ├── Makefile.am ├── Mono.Cxxi │ ├── Abi │ │ ├── CppAbi.cs │ │ ├── EmitInfo.cs │ │ ├── Impl │ │ │ ├── ItaniumAbi.cs │ │ │ ├── ItaniumTypeInfo.cs │ │ │ └── MsvcAbi.cs │ │ ├── MethodType.cs │ │ ├── SymbolResolver.cs │ │ └── VTable.cs │ ├── AssemblyInfo.cs │ ├── Attributes.cs │ ├── CppField.cs │ ├── CppInstancePtr.cs │ ├── CppLibrary.cs │ ├── CppModifiers.cs │ ├── CppType.cs │ ├── CppTypeInfo.cs │ ├── Interfaces.cs │ ├── Makefile.am │ ├── Mono.Cxxi.csproj │ ├── Util │ │ ├── DelegateTypeCache.cs │ │ ├── IEnumerableTransform.cs │ │ ├── LazyGeneratedList.cs │ │ ├── MethodSignature.cs │ │ └── ReflectionHelper.cs │ └── mono.cxxi.pc.in ├── README └── generator │ ├── Access.cs │ ├── Class.cs │ ├── Enumeration.cs │ ├── Field.cs │ ├── Filter.cs │ ├── Generator.cs │ ├── Lib.cs │ ├── Makefile.am │ ├── Method.cs │ ├── Namespace.cs │ ├── Node.cs │ ├── Options.cs │ ├── Parameter.cs │ ├── Property.cs │ ├── Templates │ ├── Base.cs │ ├── Base.tt │ ├── BaseMembers.cs │ ├── CSharp │ │ ├── CSharpClass.cs │ │ ├── CSharpClass.tt │ │ ├── CSharpEnum.cs │ │ ├── CSharpEnum.tt │ │ ├── CSharpLanguage.cs │ │ ├── CSharpLibs.cs │ │ └── CSharpLibs.tt │ └── Context.cs │ ├── generator.csproj │ ├── generator.in │ └── generator.sln └── tests ├── FieldTests.cs ├── InheritanceTests.cs ├── Makefile.am ├── ManglingTests.cs ├── MarshalingTests.cs ├── Native ├── FieldTests.cpp ├── FieldTests.h ├── InheritanceTests.cpp ├── InheritanceTests.h ├── ManglingTests.cpp ├── ManglingTests.h ├── MarshalingTests.cpp ├── MarshalingTests.h ├── NUnit.cpp └── NUnit.h ├── README └── Tests.csproj /.gitignore: -------------------------------------------------------------------------------- 1 | *.pidb 2 | configure 3 | install-sh 4 | aclocal.m4 5 | config.status 6 | config.log 7 | autom4te.cache 8 | missing 9 | *Makefile 10 | *Makefile.in 11 | *.dll 12 | *.exe 13 | bin/ 14 | *.userprefs 15 | tests/output 16 | src/generator/generator 17 | *.pc 18 | .DS_Store 19 | -------------------------------------------------------------------------------- /CODE-OF-CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | This project has adopted the code of conduct defined by the Contributor Covenant 4 | to clarify expected behavior in our community. 5 | 6 | For more information, see the [.NET Foundation Code of Conduct](https://dotnetfoundation.org/code-of-conduct). 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 Novell, Inc and the individuals listed on the 2 | ChangeLog entries. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | EXTRA_DIST = m4/expansions.m4 3 | 4 | SUBDIRS = src 5 | 6 | if ENABLE_DEBUG 7 | SUBDIRS += tests 8 | endif 9 | 10 | if ENABLE_EXAMPLES 11 | SUBDIRS += examples 12 | endif 13 | -------------------------------------------------------------------------------- /Makefile.include: -------------------------------------------------------------------------------- 1 | VALID_CULTURES = ar bg ca zh-CHS cs da de el en es fi fr he hu is it ja ko nl no pl pt ro ru hr sk sq sv th tr id uk be sl et lv lt fa vi hy eu mk af ka fo hi sw gu ta te kn mr gl kok ar-SA bg-BG ca-ES zh-TW cs-CZ da-DK de-DE el-GR en-US fi-FI fr-FR he-IL hu-HU is-IS it-IT ja-JP ko-KR nl-NL nb-NO pl-PL pt-BR ro-RO ru-RU hr-HR sk-SK sq-AL sv-SE th-TH tr-TR id-ID uk-UA be-BY sl-SI et-EE lv-LV lt-LT fa-IR vi-VN hy-AM eu-ES mk-MK af-ZA ka-GE fo-FO hi-IN sw-KE gu-IN ta-IN te-IN kn-IN mr-IN gl-ES kok-IN ar-IQ zh-CN de-CH en-GB es-MX fr-BE it-CH nl-BE nn-NO pt-PT sv-FI ar-EG zh-HK de-AT en-AU es-ES fr-CA ar-LY zh-SG de-LU en-CA es-GT fr-CH ar-DZ zh-MO en-NZ es-CR fr-LU ar-MA en-IE es-PA ar-TN en-ZA es-DO ar-OM es-VE ar-YE es-CO ar-SY es-PE ar-JO en-TT es-AR ar-LB en-ZW es-EC ar-KW en-PH es-CL ar-AE es-UY ar-BH es-PY ar-QA es-BO es-SV es-HN es-NI es-PR zh-CHT 2 | 3 | s2q=$(subst \ ,?,$1) 4 | q2s=$(subst ?,\ ,$1) 5 | # use this when result will be quoted 6 | unesc2=$(subst ?, ,$1) 7 | 8 | build_sources = $(FILES) $(GENERATED_FILES) 9 | build_sources_esc= $(call s2q,$(build_sources)) 10 | # use unesc2, as build_sources_embed is quoted 11 | build_sources_embed= $(call unesc2,$(build_sources_esc:%='$(srcdir)/%')) 12 | 13 | comma__=, 14 | get_resource_name = $(firstword $(subst $(comma__), ,$1)) 15 | get_culture = $(lastword $(subst ., ,$(basename $1))) 16 | is_cultured_resource = $(and $(word 3,$(subst ., ,$1)), $(filter $(VALID_CULTURES),$(lastword $(subst ., ,$(basename $1))))) 17 | 18 | RESOURCES_ESC=$(call s2q,$(RESOURCES)) 19 | 20 | build_resx_list = $(foreach res, $(RESOURCES_ESC), $(if $(filter %.resx, $(call get_resource_name,$(res))),$(res),)) 21 | build_non_culture_resx_list = $(foreach res, $(build_resx_list),$(if $(call is_cultured_resource,$(call get_resource_name,$(res))),,$(res))) 22 | build_non_culture_others_list = $(foreach res, $(filter-out $(build_resx_list),$(RESOURCES_ESC)),$(if $(call is_cultured_resource,$(call get_resource_name,$(res))),,$(res))) 23 | build_others_list = $(build_non_culture_others_list) 24 | build_xamlg_list = $(filter %.xaml.g.cs, $(FILES)) 25 | 26 | # resgen all .resx resources 27 | build_resx_files = $(foreach res, $(build_resx_list), $(call get_resource_name,$(res))) 28 | build_resx_resources_esc = $(build_resx_files:.resx=.resources) 29 | build_resx_resources = $(call q2s,$(build_resx_resources_esc)) 30 | 31 | # embed resources for the main assembly 32 | build_resx_resources_hack = $(subst .resx,.resources, $(build_non_culture_resx_list)) 33 | # use unesc2, as build_resx_resources_embed is quoted 34 | build_resx_resources_embed = $(call unesc2,$(build_resx_resources_hack:%='-resource:%')) 35 | build_others_files = $(call q2s,$(foreach res, $(build_others_list),$(call get_resource_name,$(res)))) 36 | build_others_resources = $(build_others_files) 37 | # use unesc2, as build_others_resources_embed is quoted 38 | build_others_resources_embed = $(call unesc2,$(build_others_list:%='-resource:$(srcdir)/%')) 39 | 40 | build_resources = $(build_resx_resources) $(build_others_resources) 41 | build_resources_embed = $(build_resx_resources_embed) $(build_others_resources_embed) 42 | 43 | # -usesourcepath is available only for resgen2 44 | emit_resgen_target_1=$(call q2s,$1) : $(call q2s,$(subst .resources,.resx,$1)); cd '$$(shell dirname '$$<')' && MONO_IOMAP=drive $$(RESGEN) '$$(shell basename '$$<')' '$$(shell basename '$$@')' 45 | emit_resgen_target_2=$(call q2s,$1) : $(call q2s,$(subst .resources,.resx,$1)); MONO_IOMAP=drive $$(RESGEN) -usesourcepath '$$<' '$$@' 46 | 47 | emit_resgen_target=$(if $(filter resgen2,$(RESGEN)),$(emit_resgen_target_2),$(emit_resgen_target_1)) 48 | emit_resgen_targets=$(foreach res,$(build_resx_resources_esc),$(eval $(call emit_resgen_target,$(res)))) 49 | 50 | build_references_ref = $(call q2s,$(foreach ref, $(call s2q,$(REFERENCES)), $(if $(filter -pkg:%, $(ref)), $(ref), $(if $(filter -r:%, $(ref)), $(ref), -r:$(ref))))) 51 | build_references_ref += $(call q2s,$(foreach ref, $(call s2q,$(DLL_REFERENCES)), -r:$(ref))) 52 | build_references_ref += $(call q2s,$(foreach ref, $(call s2q,$(PROJECT_REFERENCES)), -r:$(ref))) 53 | 54 | s2q2s=$(call unesc2,$(call s2q,$1)) 55 | cp_actual=test -z $1 || cp $1 $2 56 | cp=$(call cp_actual,'$(call s2q2s,$1)','$(call s2q2s,$2)') 57 | 58 | rm_actual=test -z '$1' || rm -f '$2' 59 | rm=$(call rm_actual,$(call s2q2s,$1),$(call s2q2s,$2)/$(shell basename '$(call s2q2s,$1)')) 60 | 61 | EXTRA_DIST += $(build_sources) $(build_resx_files) $(build_others_files) $(ASSEMBLY_WRAPPER_IN) $(EXTRAS) $(DATA_FILES) $(build_culture_res_files) 62 | CLEANFILES += $(ASSEMBLY) $(ASSEMBLY).mdb $(BINARIES) $(build_resx_resources) $(build_satellite_assembly_list) 63 | DISTCLEANFILES = $(GENERATED_FILES) $(pc_files) $(BUILD_DIR)/* 64 | 65 | pkglib_SCRIPTS = $(ASSEMBLY) 66 | bin_SCRIPTS = $(BINARIES) 67 | 68 | programfilesdir = @libdir@/@PACKAGE@ 69 | programfiles_DATA = $(PROGRAMFILES) 70 | linuxpkgconfigdir = @libdir@/pkgconfig 71 | linuxpkgconfig_DATA = $(LINUX_PKGCONFIG) 72 | 73 | 74 | # macros 75 | 76 | # $(call emit-deploy-target,deploy-variable-name) 77 | define emit-deploy-target 78 | $($1): $($1_SOURCE) 79 | mkdir -p '$$(shell dirname '$$@')' 80 | cp '$$<' '$$@' 81 | endef 82 | 83 | # $(call emit-deploy-wrapper,wrapper-variable-name,wrapper-sourcefile,x) 84 | # assumes that for a wrapper foo.pc its source template is foo.pc.in 85 | # if $3 is non-empty then wrapper is marked exec 86 | define emit-deploy-wrapper 87 | $($1): $2 88 | mkdir -p '$$(shell dirname '$$@')' 89 | cp '$$<' '$$@' 90 | $(if $3,chmod +x '$$@') 91 | 92 | endef 93 | 94 | # generating satellite assemblies 95 | 96 | culture_resources = $(foreach res, $(RESOURCES_ESC), $(if $(call is_cultured_resource,$(call get_resource_name, $(res))),$(res))) 97 | cultures = $(sort $(foreach res, $(culture_resources), $(call get_culture,$(call get_resource_name,$(res))))) 98 | culture_resource_dependencies = $(call q2s,$(BUILD_DIR)/$1/$(SATELLITE_ASSEMBLY_NAME): $(subst .resx,.resources,$2)) 99 | culture_resource_commandlines = $(call unesc2,cmd_line_satellite_$1 += '/embed:$(subst .resx,.resources,$2)') 100 | build_satellite_assembly_list = $(call q2s,$(cultures:%=$(BUILD_DIR)/%/$(SATELLITE_ASSEMBLY_NAME))) 101 | build_culture_res_files = $(call q2s,$(foreach res, $(culture_resources),$(call get_resource_name,$(res)))) 102 | install_satellite_assembly_list = $(subst $(BUILD_DIR),$(DESTDIR)$(libdir)/$(PACKAGE),$(build_satellite_assembly_list)) 103 | 104 | $(eval $(foreach res, $(culture_resources), $(eval $(call culture_resource_dependencies,$(call get_culture,$(call get_resource_name,$(res))),$(call get_resource_name,$(res)))))) 105 | $(eval $(foreach res, $(culture_resources), $(eval $(call culture_resource_commandlines,$(call get_culture,$(call get_resource_name,$(res))),$(res))))) 106 | 107 | $(build_satellite_assembly_list): $(BUILD_DIR)/%/$(SATELLITE_ASSEMBLY_NAME): 108 | mkdir -p '$(@D)' 109 | $(AL) -out:'$@' -culture:$* -t:lib $(cmd_line_satellite_$*) 110 | 111 | $(install_satellite_assembly_list): 112 | mkdir -p '$(@D)' 113 | cp $(subst $(DESTDIR)$(libdir)/$(PACKAGE), $(BUILD_DIR), $@) $@ 114 | 115 | install-satellite-assemblies: $(install_satellite_assembly_list) 116 | 117 | uninstall-satellite-assemblies: 118 | rm -rf $(install_satellite_assembly_list) -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Directory structure 2 | ------------------- 3 | 4 | src/ 5 | Mono.Cxxi 6 | The runtime library 7 | generator 8 | The binding generator 9 | qt 10 | Auto generated Qt bindings + test program 11 | 12 | tests/ 13 | Regression tests 14 | 15 | examples/ 16 | Hello 17 | Small, Hello, World! example 18 | 19 | Inlining 20 | -------- 21 | 22 | Inline methods are mapped to a shared library name libFoo-inline.so where libFoo.so is the 23 | original shared library we are binding to. This library should be compiled using gcc's 24 | -fkeep-inline-functions option: 25 | 26 | g++ `pkg-config --cflags QtCore QtGui` --shared -fPIC -o libQtGui-inline.so -fkeep-inline-functions qt-gui.cpp `pkg-config --libs QtCore QtGui` 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | PROJECT=cxxi 4 | FILE= 5 | CONFIGURE=configure.ac 6 | 7 | : ${AUTOCONF=autoconf} 8 | : ${AUTOHEADER=autoheader} 9 | : ${AUTOMAKE=automake} 10 | : ${LIBTOOLIZE=libtoolize} 11 | : ${ACLOCAL=aclocal} 12 | : ${LIBTOOL=libtool} 13 | 14 | srcdir=`dirname $0` 15 | test -z "$srcdir" && srcdir=. 16 | 17 | ORIGDIR=`pwd` 18 | cd $srcdir 19 | TEST_TYPE=-f 20 | aclocalinclude="-I . -I m4 $ACLOCAL_FLAGS" 21 | 22 | DIE=0 23 | 24 | ($AUTOCONF --version) < /dev/null > /dev/null 2>&1 || { 25 | echo 26 | echo "You must have autoconf installed to compile $PROJECT." 27 | echo "Download the appropriate package for your distribution," 28 | echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" 29 | DIE=1 30 | } 31 | 32 | ($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || { 33 | echo 34 | echo "You must have automake installed to compile $PROJECT." 35 | echo "Get ftp://sourceware.cygnus.com/pub/automake/automake-1.4.tar.gz" 36 | echo "(or a newer version if it is available)" 37 | DIE=1 38 | } 39 | 40 | (grep "^AM_PROG_LIBTOOL" $CONFIGURE >/dev/null) && { 41 | ($LIBTOOL --version) < /dev/null > /dev/null 2>&1 || { 42 | echo 43 | echo "**Error**: You must have \`libtool' installed to compile $PROJECT." 44 | echo "Get ftp://ftp.gnu.org/pub/gnu/libtool-1.2d.tar.gz" 45 | echo "(or a newer version if it is available)" 46 | DIE=1 47 | } 48 | } 49 | 50 | if test "$DIE" -eq 1; then 51 | exit 1 52 | fi 53 | 54 | #test $TEST_TYPE $FILE || { 55 | # echo "You must run this script in the top-level $PROJECT directory" 56 | # exit 1 57 | #} 58 | 59 | if test -z "$*"; then 60 | echo "I am going to run ./configure with no arguments - if you wish " 61 | echo "to pass any to it, please specify them on the $0 command line." 62 | fi 63 | 64 | case $CC in 65 | *xlc | *xlc\ * | *lcc | *lcc\ *) am_opt=--include-deps;; 66 | esac 67 | 68 | (grep "^AM_PROG_LIBTOOL" $CONFIGURE >/dev/null) && { 69 | echo "Running $LIBTOOLIZE ..." 70 | $LIBTOOLIZE --force --copy 71 | } 72 | 73 | echo "Running $ACLOCAL $aclocalinclude ..." 74 | $ACLOCAL $aclocalinclude 75 | 76 | echo "Running $AUTOMAKE --gnu $am_opt ..." 77 | $AUTOMAKE --add-missing --gnu $am_opt 78 | 79 | echo "Running $AUTOCONF ..." 80 | $AUTOCONF 81 | 82 | echo Running $srcdir/configure $conf_flags "$@" ... 83 | $srcdir/configure --enable-maintainer-mode $conf_flags "$@" \ 84 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | dnl Process this file with autoconf to produce a configure script. 2 | AC_PREREQ([2.54]) 3 | AC_INIT([Mono.Cxxi], [0.99.1]) 4 | AM_INIT_AUTOMAKE([foreign]) 5 | AM_MAINTAINER_MODE 6 | 7 | dnl pkg-config 8 | AC_PATH_PROG(PKG_CONFIG, pkg-config, no) 9 | if test "x$PKG_CONFIG" = "xno"; then 10 | AC_MSG_ERROR([You need to install pkg-config]) 11 | fi 12 | 13 | SHAMROCK_EXPAND_LIBDIR 14 | SHAMROCK_EXPAND_BINDIR 15 | SHAMROCK_EXPAND_DATADIR 16 | 17 | AC_PROG_INSTALL 18 | 19 | AC_PATH_PROG(MONO, mono, no) 20 | if test "x$MONO" = "xno"; then 21 | AC_MSG_ERROR([mono Not found]) 22 | fi 23 | 24 | AC_PATH_PROG(GMCS, mcs, no) 25 | if test "x$GMCS" = "xno"; then 26 | AC_MSG_ERROR([mcs Not found]) 27 | fi 28 | 29 | AC_PATH_PROG(GCCXML, gccxml, no) 30 | if test "x$GCCXML" = "xno"; then 31 | AC_MSG_ERROR([gccxml Not found]) 32 | fi 33 | 34 | AC_ARG_ENABLE(debug, 35 | AC_HELP_STRING([--enable-debug], 36 | [Use 'DEBUG' Configuration [default=YES]]), 37 | enable_debug=yes, enable_debug=no) 38 | AM_CONDITIONAL(ENABLE_DEBUG, test x$enable_debug = xyes) 39 | if test "x$enable_debug" = "xyes" ; then 40 | CONFIG_REQUESTED="yes" 41 | fi 42 | AC_ARG_ENABLE(release, 43 | AC_HELP_STRING([--enable-release], 44 | [Use 'RELEASE' Configuration [default=NO]]), 45 | enable_release=yes, enable_release=no) 46 | AM_CONDITIONAL(ENABLE_RELEASE, test x$enable_release = xyes) 47 | if test "x$enable_release" = "xyes" ; then 48 | CONFIG_REQUESTED="yes" 49 | fi 50 | if test -z "$CONFIG_REQUESTED" ; then 51 | AM_CONDITIONAL(ENABLE_DEBUG, true) 52 | enable_debug=yes 53 | fi 54 | 55 | AC_ARG_ENABLE(examples, 56 | AC_HELP_STRING([--enable-examples], 57 | [Build examples [default=NO]]), 58 | enable_examples=yes, enable_examples=no) 59 | AM_CONDITIONAL(ENABLE_EXAMPLES, test x$enable_examples = xyes) 60 | 61 | dnl package checks, common for all configs 62 | 63 | PKG_CHECK_MODULES([MONO_NUNIT], [mono-nunit]) 64 | 65 | dnl package checks, per config 66 | 67 | 68 | AC_CONFIG_FILES([ 69 | src/Mono.Cxxi/mono.cxxi.pc 70 | src/Mono.Cxxi/Makefile 71 | src/generator/generator 72 | src/generator/Makefile 73 | src/Makefile 74 | tests/Makefile 75 | examples/Makefile 76 | examples/Hello/Makefile 77 | examples/qt/Makefile 78 | Makefile 79 | ]) 80 | 81 | AC_OUTPUT 82 | -------------------------------------------------------------------------------- /cxxi.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cxxi", "src\Mono.Cxxi\Mono.Cxxi.csproj", "{4A864586-93C5-4DC1-8A80-F094A88506D7}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "tests\Tests.csproj", "{3C290CBE-CA39-47F6-B3A0-ACD16C5A38C8}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "generator", "src\generator\generator.csproj", "{AD0F9378-789C-4AF1-B0DD-6DD9A63C3401}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {3C290CBE-CA39-47F6-B3A0-ACD16C5A38C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {3C290CBE-CA39-47F6-B3A0-ACD16C5A38C8}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {3C290CBE-CA39-47F6-B3A0-ACD16C5A38C8}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {3C290CBE-CA39-47F6-B3A0-ACD16C5A38C8}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {4A864586-93C5-4DC1-8A80-F094A88506D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {4A864586-93C5-4DC1-8A80-F094A88506D7}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {4A864586-93C5-4DC1-8A80-F094A88506D7}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {4A864586-93C5-4DC1-8A80-F094A88506D7}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {AD0F9378-789C-4AF1-B0DD-6DD9A63C3401}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {AD0F9378-789C-4AF1-B0DD-6DD9A63C3401}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {AD0F9378-789C-4AF1-B0DD-6DD9A63C3401}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {AD0F9378-789C-4AF1-B0DD-6DD9A63C3401}.Release|Any CPU.Build.0 = Release|Any CPU 28 | EndGlobalSection 29 | GlobalSection(MonoDevelopProperties) = preSolution 30 | StartupItem = src\generator\generator.csproj 31 | Policies = $0 32 | $0.TextStylePolicy = $1 33 | $1.inheritsSet = null 34 | $1.scope = text/x-csharp 35 | $0.CSharpFormattingPolicy = $2 36 | $2.NamespaceBraceStyle = EndOfLine 37 | $2.ClassBraceStyle = EndOfLine 38 | $2.InterfaceBraceStyle = EndOfLine 39 | $2.StructBraceStyle = EndOfLine 40 | $2.EnumBraceStyle = EndOfLine 41 | $2.inheritsSet = Mono 42 | $2.inheritsScope = text/x-csharp 43 | $2.scope = text/x-csharp 44 | $0.TextStylePolicy = $3 45 | $3.FileWidth = 120 46 | $3.TabWidth = 4 47 | $3.RemoveTrailingWhitespace = True 48 | $3.inheritsSet = Mono 49 | $3.inheritsScope = text/plain 50 | $3.scope = text/plain 51 | name = CPPInterop 52 | EndGlobalSection 53 | GlobalSection(SolutionProperties) = preSolution 54 | HideSolutionNode = FALSE 55 | EndGlobalSection 56 | EndGlobal 57 | -------------------------------------------------------------------------------- /examples/Hello/Hello.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Hello.h" 3 | 4 | using namespace std; 5 | 6 | void 7 | Hello::PrintHello () 8 | { 9 | cout << "Hello, World!\n"; 10 | } 11 | 12 | Hello::Hello () 13 | { 14 | } 15 | 16 | int 17 | main () 18 | { 19 | Hello h; 20 | 21 | h.PrintHello (); 22 | 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /examples/Hello/Hello.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | public class HelloExample 4 | { 5 | public static void Main (String[] args) { 6 | var h = new Hello.Hello (); 7 | h.PrintHello (); 8 | } 9 | } 10 | 11 | -------------------------------------------------------------------------------- /examples/Hello/Hello.h: -------------------------------------------------------------------------------- 1 | 2 | class Hello 3 | { 4 | public: 5 | Hello (); 6 | 7 | void PrintHello (); 8 | }; 9 | -------------------------------------------------------------------------------- /examples/Hello/Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | top_srcdir=../.. 3 | 4 | if ENABLE_DEBUG 5 | BUILD_DIR=$(top_srcdir)/bin/Debug 6 | endif 7 | 8 | if ENABLE_RELEASE 9 | BUILD_DIR=$(top_srcdir)/bin/Release 10 | endif 11 | 12 | INTEROP_DLL = \ 13 | $(BUILD_DIR)/Mono.Cxxi.dll 14 | 15 | HELLO_EXE = \ 16 | $(BUILD_DIR)/Hello.exe 17 | 18 | all: $(BUILD_DIR)/libhello.so Hello.xml $(HELLO_EXE) 19 | 20 | $(BUILD_DIR)/libhello.so: Hello.cpp Hello.h 21 | $(CXX) -fPIC --shared -o $@ Hello.cpp 22 | 23 | Hello.xml: Hello.h 24 | $(GCCXML) -fxml=$@ Hello.h 25 | 26 | generated: Hello.xml 27 | $(RM) -r generated 28 | $(MONO) $(BUILD_DIR)/generator.exe -ns=Hello -lib=hello -o=$@ Hello.xml 29 | 30 | $(HELLO_EXE): generated Hello.cs 31 | $(GMCS) -unsafe -out:$@ -target:exe -r:$(INTEROP_DLL) generated/*.cs Hello.cs 32 | 33 | clean: 34 | $(RM) -r generated libhello.so Hello.xml $(HELLO_EXE) 35 | 36 | run: Hello.exe 37 | $(MONO) --debug $(HELLO_EXE) 38 | -------------------------------------------------------------------------------- /examples/Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | SUBDIRS = Hello qt 3 | -------------------------------------------------------------------------------- /examples/qt/Makefile.am: -------------------------------------------------------------------------------- 1 | top_srcdir = ../.. 2 | 3 | INTEROP_DLL = \ 4 | $(top_srcdir)/bin/Debug/Mono.Cxxi.dll 5 | 6 | HANDWRITTEN = \ 7 | QString.cs \ 8 | QApplication.cs \ 9 | QCoreApplication.cs \ 10 | QSize.cs \ 11 | QPushButton.cs \ 12 | QWidget.cs \ 13 | QPoint.cs \ 14 | QFlags.cs 15 | 16 | all: hello.exe 17 | 18 | # HACK: some Mac versions of Qt don't play nice with pkg-config 19 | QT_FLAGS := `pkg-config --silence-errors --cflags QtCore QtGui || \ 20 | (ln -s /Library/Frameworks/QtGui.framework/Versions/Current/Headers QtGui && \ 21 | ln -s /Library/Frameworks/QtCore.framework/Versions/Current/Headers QtCore && \ 22 | echo "-m32 -I. -I/Library/Frameworks/QtGui.framework/Versions/Current/Headers")` 23 | 24 | qt-gui.xml: qt-gui.h 25 | $(GCCXML) -fxml=$@ --gccxml-cxxflags $(QT_FLAGS) $^ 26 | 27 | generated: qt-gui-filters.xml qt-gui.xml 28 | $(RM) -r generated 29 | $(MONO) --debug $(top_srcdir)/bin/Debug/generator.exe -o=generated -ns=Qt.Gui -lib=QtGui --filters=$^ 30 | 31 | libQtGui-inline.so: qt-gui.cpp 32 | $(CXX) -m32 -I. -framework QtGui -framework QtCore --shared -fPIC -o $@ -fkeep-inline-functions -fdump-class-hierarchy qt-gui.cpp 33 | 34 | Qt.Gui-binding.dll: generated $(addprefix src/,$(HANDWRITTEN)) 35 | $(GMCS) -debug -out:$@ -target:library -unsafe -r:$(INTEROP_DLL) generated/*.cs $(addprefix src/,$(HANDWRITTEN)) 36 | 37 | hello.exe: Qt.Gui-binding.dll demos/hello.cs #libQtGui-inline.so 38 | $(GMCS) -debug -out:$@ -target:exe -r:$(INTEROP_DLL) -r:Qt.Gui-binding.dll demos/hello.cs 39 | 40 | clean: 41 | $(RM) -r generated QtCore QtGui hello.exe* qt-gui.xml Qt.Gui-binding.dll* libQtGui-inline.so 42 | 43 | run: hello.exe 44 | MONO_PATH=.:$(top_srcdir)/bin/Debug $(MONO) --debug hello.exe 45 | -------------------------------------------------------------------------------- /examples/qt/demos/hello.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using Qt.Gui; 4 | using Qt.Gui.Qt; 5 | 6 | using Mono.Cxxi; 7 | 8 | namespace QtTest { 9 | class MainClass { 10 | public static void Main (string[] args) 11 | { 12 | using (QApplication app = new QApplication ()) { 13 | using (QPushButton hello = new QPushButton ("Hello world!")) { 14 | 15 | hello.Resize (200, 30); 16 | QObject.Connect (hello, "2clicked()", app, "1aboutQt()", ConnectionType.AutoConnection); 17 | 18 | hello.SetVisible (true); 19 | QApplication.Exec (); 20 | } 21 | } 22 | } 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /examples/qt/qt-gui-filters.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | QObject 19 | Qt 20 | Qt::ConnectionType 21 | Qt::KeyboardModifier 22 | Qt::MouseButton 23 | Qt::ButtonState 24 | 25 | QApplication 26 | QCoreApplication 27 | QWidget 28 | QAbstractButton 29 | QPushButton 30 | QPaintDevice 31 | 32 | QEvent 33 | QInputEvent 34 | QMouseEvent 35 | QTimerEvent 36 | 37 | QString 38 | QSize 39 | QPoint 40 | QFlags<Qt::KeyboardModifier> 41 | 42 | -------------------------------------------------------------------------------- /examples/qt/qt-gui.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * These are not in the unix version of qt, and -fkeep-inline-functions will generate 4 | * references to their vtables etc., making the library unloadable. 5 | */ 6 | #define QT_NO_STYLE_WINDOWSVISTA 7 | #define QT_NO_STYLE_WINDOWSXP 8 | #define QT_NO_STYLE_S60 9 | #define QT_NO_STYLE_WINDOWSCE 10 | #define QT_NO_STYLE_WINDOWSMOBILE 11 | #define QT_NO_QWSEMBEDWIDGET 12 | 13 | // this one was annoying to track down! 14 | #define QT_NO_TRANSLATION 15 | 16 | #include "QtGui/QApplication" 17 | #include "QtGui/QPushButton" 18 | 19 | int main () 20 | { 21 | } 22 | -------------------------------------------------------------------------------- /examples/qt/qt-gui.h: -------------------------------------------------------------------------------- 1 | #include "QApplication" 2 | #include "qevent.h" 3 | #include "QPushButton" 4 | -------------------------------------------------------------------------------- /examples/qt/src/QApplication.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using Mono.Cxxi; 4 | 5 | namespace Qt.Gui { 6 | public partial class QApplication { 7 | 8 | public partial interface IQApplication { 9 | [Constructor] CppInstancePtr QApplication (CppInstancePtr @this, [MangleAs ("int&")] IntPtr argc, [MangleAs ("char**")] IntPtr argv, int version); 10 | } 11 | 12 | public QApplication () : base (impl.TypeInfo) 13 | { 14 | InitArgcAndArgv (); 15 | Native = impl.QApplication (impl.Alloc (this), argc, argv, 0x040602); 16 | } 17 | 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /examples/qt/src/QCoreApplication.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using Mono.Cxxi; 4 | 5 | namespace Qt.Gui { 6 | public partial class QCoreApplication { 7 | 8 | public partial interface IQCoreApplication { 9 | [Constructor] CppInstancePtr QCoreApplication (CppInstancePtr @this, [MangleAs ("int&")] IntPtr argc, [MangleAs ("char**")] IntPtr argv); 10 | } 11 | 12 | protected IntPtr argc, argv; 13 | 14 | public QCoreApplication () : base (impl.TypeInfo) 15 | { 16 | InitArgcAndArgv (); 17 | Native = impl.QCoreApplication (impl.Alloc (this), argc, argv); 18 | } 19 | 20 | partial void AfterDestruct () 21 | { 22 | FreeArgcAndArgv (); 23 | } 24 | 25 | protected void InitArgcAndArgv () 26 | { 27 | var args = Environment.GetCommandLineArgs (); 28 | var argCount = args.Length; 29 | 30 | argc = Marshal.AllocHGlobal (sizeof(int)); 31 | Marshal.WriteInt32 (argc, argCount); 32 | 33 | argv = Marshal.AllocHGlobal (Marshal.SizeOf (typeof(IntPtr)) * argCount); 34 | for (var i = 0; i < argCount; i++) { 35 | IntPtr arg = Marshal.StringToHGlobalAnsi (args [i]); 36 | Marshal.WriteIntPtr (argv, i * Marshal.SizeOf (typeof(IntPtr)), arg); 37 | } 38 | } 39 | 40 | protected void FreeArgcAndArgv () 41 | { 42 | Marshal.FreeHGlobal (argc); 43 | for (var i = 0; i < Environment.GetCommandLineArgs ().Length; i++) 44 | Marshal.FreeHGlobal (Marshal.ReadIntPtr (argv, i * Marshal.SizeOf (typeof(IntPtr)))); 45 | Marshal.FreeHGlobal (argv); 46 | } 47 | 48 | } 49 | } 50 | 51 | -------------------------------------------------------------------------------- /examples/qt/src/QFlags.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using Mono.Cxxi; 4 | 5 | namespace Qt.Gui { 6 | 7 | [StructLayout (LayoutKind.Sequential)] 8 | public struct QFlags where T : struct { 9 | 10 | public T Value; 11 | } 12 | } 13 | 14 | -------------------------------------------------------------------------------- /examples/qt/src/QPoint.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using Mono.Cxxi; 4 | 5 | namespace Qt.Gui { 6 | 7 | [StructLayout (LayoutKind.Sequential)] 8 | public struct QPoint { 9 | 10 | private int xy, yx; //Wtf.. on Mac the order is y, x; elsewhere x, y 11 | 12 | public QPoint (int x, int y) 13 | { 14 | //FIXME: do some snazzy stuff to get this right.. for now, I'm a mac user :P 15 | this.yx = x; 16 | this.xy = y; 17 | } 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /examples/qt/src/QPushButton.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using Mono.Cxxi; 4 | 5 | namespace Qt.Gui { 6 | public partial class QPushButton { 7 | 8 | public QPushButton (QString text, QWidget parent) 9 | : this (ref text, parent) 10 | { 11 | } 12 | 13 | public QPushButton (QString text) 14 | : this (ref text, null) 15 | { 16 | } 17 | 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /examples/qt/src/QSize.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using Mono.Cxxi; 4 | 5 | namespace Qt.Gui { 6 | 7 | [StructLayout (LayoutKind.Sequential)] 8 | public struct QSize { 9 | 10 | public int Width; 11 | public int Height; 12 | 13 | public QSize (int w, int h) 14 | { 15 | this.Width = w; 16 | this.Height = h; 17 | } 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /examples/qt/src/QString.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.Runtime.InteropServices; 4 | 5 | using Mono.Cxxi; 6 | 7 | namespace Qt.Gui { 8 | //TODO: Will this leak? 9 | [StructLayout (LayoutKind.Sequential)] 10 | public unsafe struct QString { 11 | #region Sync with qstring.h 12 | public interface IQString : ICppClass { 13 | [Constructor] void QString(ref QString @this, [MangleAs ("const QChar*")] IntPtr unicode, int size); 14 | } 15 | 16 | [StructLayout (LayoutKind.Sequential)] 17 | public struct Data { 18 | public int @ref; 19 | public int alloc, size; 20 | public IntPtr data; 21 | public ushort clean; 22 | public ushort simpletext; 23 | public ushort righttoleft; 24 | public ushort asciiCache; 25 | public ushort capacity; 26 | public ushort reserved; 27 | public IntPtr array; 28 | } 29 | 30 | 31 | public Data* d; 32 | #endregion 33 | 34 | private static IQString impl = Libs.QtGui.GetClass ("QString"); 35 | 36 | public QString (string str) : this () 37 | { 38 | var strPtr = Marshal.StringToHGlobalUni (str); 39 | impl.QString (ref this, strPtr, str.Length); 40 | Marshal.FreeHGlobal (strPtr); 41 | 42 | // TODO: I deref this on construction to let Qt free it when it's done with it. 43 | // My assumption is that this struct will only be used to interop with Qt and 44 | // no managed class is going to hold on to it. 45 | this.DeRef (); 46 | } 47 | 48 | public static implicit operator QString (string str) 49 | { 50 | return new QString (str); 51 | } 52 | 53 | public override string ToString () 54 | { 55 | return Marshal.PtrToStringUni (d->data, d->size); 56 | } 57 | 58 | public QString AddRef () 59 | { 60 | d->@ref++; 61 | return this; 62 | } 63 | 64 | public QString DeRef () 65 | { 66 | d->@ref--; 67 | return this; 68 | } 69 | } 70 | } 71 | 72 | -------------------------------------------------------------------------------- /examples/qt/src/QWidget.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using Mono.Cxxi; 4 | 5 | namespace Qt.Gui { 6 | public partial class QWidget { 7 | 8 | public void Resize (int width, int height) 9 | { 10 | var size = new QSize (width, height); 11 | impl.resize (Native, ref size); 12 | } 13 | 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /m4/expansions.m4: -------------------------------------------------------------------------------- 1 | AC_DEFUN([SHAMROCK_EXPAND_LIBDIR], 2 | [ 3 | expanded_libdir=`( 4 | case $prefix in 5 | NONE) prefix=$ac_default_prefix ;; 6 | *) ;; 7 | esac 8 | case $exec_prefix in 9 | NONE) exec_prefix=$prefix ;; 10 | *) ;; 11 | esac 12 | eval echo $libdir 13 | )` 14 | AC_SUBST(expanded_libdir) 15 | ]) 16 | 17 | AC_DEFUN([SHAMROCK_EXPAND_BINDIR], 18 | [ 19 | expanded_bindir=`( 20 | case $prefix in 21 | NONE) prefix=$ac_default_prefix ;; 22 | *) ;; 23 | esac 24 | case $exec_prefix in 25 | NONE) exec_prefix=$prefix ;; 26 | *) ;; 27 | esac 28 | eval echo $bindir 29 | )` 30 | AC_SUBST(expanded_bindir) 31 | ]) 32 | 33 | AC_DEFUN([SHAMROCK_EXPAND_DATADIR], 34 | [ 35 | case $prefix in 36 | NONE) prefix=$ac_default_prefix ;; 37 | *) ;; 38 | esac 39 | 40 | case $exec_prefix in 41 | NONE) exec_prefix=$prefix ;; 42 | *) ;; 43 | esac 44 | 45 | expanded_datadir=`(eval echo $datadir)` 46 | expanded_datadir=`(eval echo $expanded_datadir)` 47 | 48 | AC_SUBST(expanded_datadir) 49 | ]) 50 | 51 | -------------------------------------------------------------------------------- /m4/pkg.m4: -------------------------------------------------------------------------------- 1 | # pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- 2 | # 3 | # Copyright © 2004 Scott James Remnant . 4 | # 5 | # This program is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, but 11 | # WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | # General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program; if not, write to the Free Software 17 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 | # 19 | # As a special exception to the GNU General Public License, if you 20 | # distribute this file as part of a program that contains a 21 | # configuration script generated by Autoconf, you may include it under 22 | # the same distribution terms that you use for the rest of that program. 23 | 24 | # PKG_PROG_PKG_CONFIG([MIN-VERSION]) 25 | # ---------------------------------- 26 | AC_DEFUN([PKG_PROG_PKG_CONFIG], 27 | [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) 28 | m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) 29 | AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl 30 | if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then 31 | AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) 32 | fi 33 | if test -n "$PKG_CONFIG"; then 34 | _pkg_min_version=m4_default([$1], [0.9.0]) 35 | AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) 36 | if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then 37 | AC_MSG_RESULT([yes]) 38 | else 39 | AC_MSG_RESULT([no]) 40 | PKG_CONFIG="" 41 | fi 42 | 43 | fi[]dnl 44 | ])# PKG_PROG_PKG_CONFIG 45 | 46 | # PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) 47 | # 48 | # Check to see whether a particular set of modules exists. Similar 49 | # to PKG_CHECK_MODULES(), but does not set variables or print errors. 50 | # 51 | # 52 | # Similar to PKG_CHECK_MODULES, make sure that the first instance of 53 | # this or PKG_CHECK_MODULES is called, or make sure to call 54 | # PKG_CHECK_EXISTS manually 55 | # -------------------------------------------------------------- 56 | AC_DEFUN([PKG_CHECK_EXISTS], 57 | [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl 58 | if test -n "$PKG_CONFIG" && \ 59 | AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then 60 | m4_ifval([$2], [$2], [:]) 61 | m4_ifvaln([$3], [else 62 | $3])dnl 63 | fi]) 64 | 65 | 66 | # _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) 67 | # --------------------------------------------- 68 | m4_define([_PKG_CONFIG], 69 | [if test -n "$$1"; then 70 | pkg_cv_[]$1="$$1" 71 | elif test -n "$PKG_CONFIG"; then 72 | PKG_CHECK_EXISTS([$3], 73 | [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`], 74 | [pkg_failed=yes]) 75 | else 76 | pkg_failed=untried 77 | fi[]dnl 78 | ])# _PKG_CONFIG 79 | 80 | # _PKG_SHORT_ERRORS_SUPPORTED 81 | # ----------------------------- 82 | AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], 83 | [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) 84 | if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then 85 | _pkg_short_errors_supported=yes 86 | else 87 | _pkg_short_errors_supported=no 88 | fi[]dnl 89 | ])# _PKG_SHORT_ERRORS_SUPPORTED 90 | 91 | 92 | # PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], 93 | # [ACTION-IF-NOT-FOUND]) 94 | # 95 | # 96 | # Note that if there is a possibility the first call to 97 | # PKG_CHECK_MODULES might not happen, you should be sure to include an 98 | # explicit call to PKG_PROG_PKG_CONFIG in your configure.ac 99 | # 100 | # 101 | # -------------------------------------------------------------- 102 | AC_DEFUN([PKG_CHECK_MODULES], 103 | [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl 104 | AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl 105 | AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl 106 | 107 | pkg_failed=no 108 | AC_MSG_CHECKING([for $1]) 109 | 110 | _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) 111 | _PKG_CONFIG([$1][_LIBS], [libs], [$2]) 112 | 113 | m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS 114 | and $1[]_LIBS to avoid the need to call pkg-config. 115 | See the pkg-config man page for more details.]) 116 | 117 | if test $pkg_failed = yes; then 118 | _PKG_SHORT_ERRORS_SUPPORTED 119 | if test $_pkg_short_errors_supported = yes; then 120 | $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$2" 2>&1` 121 | else 122 | $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors "$2" 2>&1` 123 | fi 124 | # Put the nasty error message in config.log where it belongs 125 | echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD 126 | 127 | ifelse([$4], , [AC_MSG_ERROR(dnl 128 | [Package requirements ($2) were not met: 129 | 130 | $$1_PKG_ERRORS 131 | 132 | Consider adjusting the PKG_CONFIG_PATH environment variable if you 133 | installed software in a non-standard prefix. 134 | 135 | _PKG_TEXT 136 | ])], 137 | [AC_MSG_RESULT([no]) 138 | $4]) 139 | elif test $pkg_failed = untried; then 140 | ifelse([$4], , [AC_MSG_FAILURE(dnl 141 | [The pkg-config script could not be found or is too old. Make sure it 142 | is in your PATH or set the PKG_CONFIG environment variable to the full 143 | path to pkg-config. 144 | 145 | _PKG_TEXT 146 | 147 | To get pkg-config, see .])], 148 | [$4]) 149 | else 150 | $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS 151 | $1[]_LIBS=$pkg_cv_[]$1[]_LIBS 152 | AC_MSG_RESULT([yes]) 153 | ifelse([$3], , :, [$3]) 154 | fi[]dnl 155 | ])# PKG_CHECK_MODULES 156 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | SUBDIRS = Mono.Cxxi generator 3 | -------------------------------------------------------------------------------- /src/Mono.Cxxi/Abi/EmitInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection.Emit; 3 | 4 | namespace Mono.Cxxi.Abi { 5 | 6 | public class EmitInfo { 7 | public TypeBuilder type_builder; 8 | public FieldBuilder typeinfo_field, native_vtable_field; 9 | public ILGenerator ctor_il, current_il; 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /src/Mono.Cxxi/Abi/Impl/ItaniumAbi.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Mono.Cxxi.Abi.ItaniumAbi.cs: An implementation of the Itanium C++ ABI 3 | // 4 | // Author: 5 | // Alexander Corrado (alexander.corrado@gmail.com) 6 | // Andreia Gaita (shana@spoiledcat.net) 7 | // 8 | // Copyright (C) 2010-2011 Alexander Corrado 9 | // Copyright 2011 Xamarin Inc (http://www.xamarin.com) 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining 12 | // a copy of this software and associated documentation files (the 13 | // "Software"), to deal in the Software without restriction, including 14 | // without limitation the rights to use, copy, modify, merge, publish, 15 | // distribute, sublicense, and/or sell copies of the Software, and to 16 | // permit persons to whom the Software is furnished to do so, subject to 17 | // the following conditions: 18 | // 19 | // The above copyright notice and this permission notice shall be 20 | // included in all copies or substantial portions of the Software. 21 | // 22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 23 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 24 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 25 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 26 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 27 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 28 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | 30 | using System; 31 | using System.Linq; 32 | using System.Text; 33 | using System.Reflection; 34 | using System.Reflection.Emit; 35 | using System.Collections.Generic; 36 | using System.Runtime.InteropServices; 37 | 38 | using Mono.Cxxi.Util; 39 | 40 | namespace Mono.Cxxi.Abi { 41 | public class ItaniumAbi : CppAbi { 42 | 43 | public static readonly ItaniumAbi Instance = new ItaniumAbi (); 44 | 45 | private ItaniumAbi () 46 | { 47 | } 48 | 49 | public override CppTypeInfo MakeTypeInfo (CppLibrary lib, string typeName, Type interfaceType, Type layoutType/*?*/, Type/*?*/ wrapperType) 50 | { 51 | return new ItaniumTypeInfo (lib, typeName, interfaceType, layoutType, wrapperType); 52 | } 53 | 54 | public override IEnumerable GetVirtualMethodSlots (CppTypeInfo typeInfo, Type interfaceType) 55 | { 56 | foreach (var method in base.GetVirtualMethodSlots (typeInfo, interfaceType)) { 57 | if (!IsVirtual (method.OrigMethod)) 58 | continue; 59 | 60 | yield return method; 61 | 62 | // Itanium has extra slot for virt dtor 63 | if (method.Type == MethodType.NativeDtor) 64 | yield return null; 65 | } 66 | } 67 | 68 | internal override Delegate GetManagedOverrideTrampoline (CppTypeInfo typeInfo, int vtableIndex) 69 | { 70 | 71 | // FIXME: HACK! we really need to support by val return types for managed override trampolines 72 | if (typeInfo.VirtualMethods [vtableIndex] != null && 73 | IsByVal (typeInfo.VirtualMethods [vtableIndex].OrigMethod.ReturnTypeCustomAttributes)) 74 | return null; 75 | 76 | return base.GetManagedOverrideTrampoline (typeInfo, vtableIndex); 77 | } 78 | 79 | protected override MethodBuilder DefineMethod (CppTypeInfo typeInfo, PInvokeSignature sig, ref int vtableIndex) 80 | { 81 | var builder = base.DefineMethod (typeInfo, sig, ref vtableIndex); 82 | 83 | // increment vtableIndex an extra time for that extra vdtor slot (already incremented once in base) 84 | if (IsVirtual (sig.OrigMethod) && sig.Type == MethodType.NativeDtor) 85 | vtableIndex++; 86 | 87 | return builder; 88 | } 89 | 90 | public override CallingConvention? GetCallingConvention (MethodInfo methodInfo) 91 | { 92 | return CallingConvention.Cdecl; 93 | } 94 | 95 | protected override string GetMangledMethodName (CppTypeInfo typeInfo, MethodInfo methodInfo) 96 | { 97 | var compressMap = new Dictionary (); 98 | var methodName = methodInfo.Name; 99 | var type = typeInfo.GetMangleType (); 100 | var className = type.ElementTypeName; 101 | 102 | MethodType methodType = GetMethodType (typeInfo, methodInfo); 103 | ParameterInfo [] parameters = methodInfo.GetParameters (); 104 | 105 | StringBuilder nm = new StringBuilder ("_ZN", 30); 106 | 107 | if (IsConst (methodInfo)) 108 | nm.Append ('K'); 109 | 110 | if (type.Namespaces != null) { 111 | foreach (var ns in type.Namespaces) 112 | nm.Append (GetIdentifier (compressMap, ns)); 113 | } 114 | 115 | nm.Append (GetIdentifier (compressMap, className)); 116 | 117 | // FIXME: Implement compression completely 118 | 119 | switch (methodType) { 120 | case MethodType.NativeCtor: 121 | nm.Append ("C1"); 122 | break; 123 | 124 | case MethodType.NativeDtor: 125 | nm.Append ("D1"); 126 | break; 127 | 128 | default: 129 | nm.Append (methodName.Length).Append (methodName); 130 | break; 131 | } 132 | 133 | nm.Append ('E'); 134 | int argStart = (IsStatic (methodInfo)? 0 : 1); 135 | 136 | if (parameters.Length == argStart) // no args (other than C++ "this" object) 137 | nm.Append ('v'); 138 | else 139 | for (int i = argStart; i < parameters.Length; i++) 140 | nm.Append (GetTypeCode (GetMangleType (parameters [i], parameters [i].ParameterType), compressMap)); 141 | 142 | return nm.ToString (); 143 | } 144 | 145 | public virtual string GetTypeCode (CppType mangleType) { 146 | return GetTypeCode (mangleType, new Dictionary ()); 147 | } 148 | 149 | string GetTypeCode (CppType mangleType, Dictionary compressMap) 150 | { 151 | CppTypes element = mangleType.ElementType; 152 | IEnumerable modifiers = mangleType.Modifiers; 153 | 154 | StringBuilder code = new StringBuilder (); 155 | 156 | var ptrOrRef = For.AnyInputIn (CppModifiers.Pointer, CppModifiers.Reference); 157 | var modifierCode = modifiers.Reverse ().Transform ( 158 | For.AnyInputIn (CppModifiers.Pointer, CppModifiers.Array).Emit ("P"), 159 | For.AnyInputIn (CppModifiers.Reference).Emit ("R"), 160 | 161 | // Itanium mangled names do not include const or volatile unless 162 | // they modify the type pointed to by pointer or reference. 163 | Choose.TopOne ( 164 | For.AllInputsIn (CppModifiers.Volatile, CppModifiers.Const).InAnyOrder ().After (ptrOrRef).Emit ("VK"), 165 | For.AnyInputIn (CppModifiers.Volatile).After (ptrOrRef).Emit ("V"), 166 | For.AnyInputIn (CppModifiers.Const).After (ptrOrRef).Emit ("K") 167 | ) 168 | ); 169 | code.Append (string.Join(string.Empty, modifierCode.ToArray ())); 170 | 171 | switch (element) { 172 | case CppTypes.Int: 173 | code.Append (modifiers.Transform ( 174 | For.AllInputsIn (CppModifiers.Unsigned, CppModifiers.Short).InAnyOrder ().Emit ('t'), 175 | For.AnyInputIn (CppModifiers.Short).Emit ('s'), 176 | For.AllInputsIn (CppModifiers.Unsigned, CppModifiers.Long, CppModifiers.Long).InAnyOrder ().Emit ('y'), 177 | For.AllInputsIn (CppModifiers.Long, CppModifiers.Long).InAnyOrder ().Emit ('x'), 178 | For.AllInputsIn (CppModifiers.Unsigned, CppModifiers.Long).InAnyOrder ().Emit ('m'), 179 | For.AnyInputIn (CppModifiers.Long).Emit ('l'), 180 | For.AnyInputIn (CppModifiers.Unsigned).Emit ('j') 181 | ).DefaultIfEmpty ('i').ToArray ()); 182 | break; 183 | case CppTypes.Bool: 184 | code.Append ('b'); 185 | break; 186 | case CppTypes.Char: 187 | if (modifiers.Contains (CppModifiers.Signed)) 188 | code.Append ('a'); 189 | else if (modifiers.Contains (CppModifiers.Unsigned)) 190 | code.Append ('h'); 191 | else 192 | code.Append ('c'); 193 | break; 194 | case CppTypes.Float: 195 | code.Append ('f'); 196 | break; 197 | case CppTypes.Double: 198 | if (modifiers.Contains (CppModifiers.Long)) 199 | code.Append ('e'); 200 | else 201 | code.Append ('d'); 202 | break; 203 | case CppTypes.Class: 204 | case CppTypes.Struct: 205 | case CppTypes.Union: 206 | case CppTypes.Enum: 207 | if (mangleType.Namespaces != null) { 208 | code.Append ('N'); 209 | foreach (var ns in mangleType.Namespaces) 210 | code.Append (GetIdentifier (compressMap, ns)); 211 | } 212 | 213 | code.Append (GetIdentifier (compressMap, mangleType.ElementTypeName)); 214 | 215 | if (mangleType.Namespaces != null) 216 | code.Append ('E'); 217 | break; 218 | 219 | } 220 | 221 | return code.ToString (); 222 | } 223 | 224 | protected override string GetMangledVTableName (CppTypeInfo typeInfo) 225 | { 226 | var compressMap = new Dictionary (); 227 | var type = typeInfo.GetMangleType (); 228 | var nm = new StringBuilder ("_ZTV", 30); 229 | 230 | if (type.Namespaces != null) { 231 | nm.Append ('N'); 232 | foreach (var ns in type.Namespaces) 233 | nm.Append (GetIdentifier (compressMap, ns)); 234 | } 235 | 236 | nm.Append (GetIdentifier (compressMap, type.ElementTypeName)); 237 | 238 | if (type.Namespaces != null) 239 | nm.Append ('E'); 240 | 241 | return nm.ToString (); 242 | } 243 | 244 | string GetIdentifier (Dictionary compressMap, string identifier) 245 | { 246 | int cid; 247 | if (compressMap.TryGetValue (identifier, out cid)) 248 | return cid == 0 ? "S_" : ToBase36String (cid - 1); 249 | compressMap [identifier] = compressMap.Count; 250 | return identifier.Length.ToString () + identifier; 251 | } 252 | 253 | const string Base36 = "0123456789abcdefghijklmnopqrstuvwxyz"; 254 | string ToBase36String (int input) 255 | { 256 | var result = new Stack (); 257 | while (input != 0) 258 | { 259 | result.Push (Base36 [input % 36]); 260 | input /= 36; 261 | } 262 | return new string (result.ToArray ()); 263 | } 264 | 265 | // Section 3.1.4: 266 | // Classes with non-default copy ctors/destructors are returned using a hidden 267 | // argument 268 | bool ReturnByHiddenArgument (CppTypeInfo typeInfo, MethodInfo method) 269 | { 270 | var iti = (ItaniumTypeInfo)typeInfo; 271 | 272 | if (!IsByVal (method.ReturnTypeCustomAttributes)) 273 | return false; 274 | 275 | if (iti.has_non_default_copy_ctor_or_dtor == null) 276 | iti.has_non_default_copy_ctor_or_dtor = GetMethods (typeInfo.InterfaceType) 277 | .Any (m => (IsCopyConstructor (m) || 278 | GetMethodType (typeInfo, m) == MethodType.NativeDtor) && 279 | !IsArtificial (m)); 280 | 281 | return iti.has_non_default_copy_ctor_or_dtor.Value; 282 | } 283 | 284 | public override PInvokeSignature GetPInvokeSignature (CppTypeInfo/*?*/ typeInfo, MethodInfo method) 285 | { 286 | var psig = base.GetPInvokeSignature (typeInfo, method); 287 | 288 | if (ReturnByHiddenArgument (typeInfo, method)) { 289 | psig.ParameterTypes.Insert (0, typeof (IntPtr)); 290 | psig.ReturnType = typeof (void); 291 | } 292 | 293 | return psig; 294 | } 295 | 296 | protected override void EmitNativeCall (CppTypeInfo typeInfo, MethodInfo nativeMethod, PInvokeSignature psig, LocalBuilder nativePtr) 297 | { 298 | var il = typeInfo.emit_info.current_il; 299 | var method = psig.OrigMethod; 300 | var returnType = method.ReturnType; 301 | var hiddenReturnByValue = ReturnByHiddenArgument (typeInfo, method); 302 | 303 | LocalBuilder returnValue = null; 304 | 305 | if (hiddenReturnByValue) 306 | { 307 | returnValue = il.DeclareLocal (typeof (CppInstancePtr)); 308 | 309 | if (typeof (ICppObject).IsAssignableFrom (returnType)) 310 | il.Emit (OpCodes.Ldc_I4, GetTypeInfo (returnType).NativeSize); 311 | else if (returnType.IsValueType) 312 | il.Emit (OpCodes.Ldc_I4, Marshal.SizeOf (returnType)); 313 | 314 | il.Emit (OpCodes.Newobj, cppip_fromsize); 315 | il.Emit (OpCodes.Stloc, returnValue); 316 | il.Emit (OpCodes.Ldloca, returnValue); 317 | il.Emit (OpCodes.Call, cppip_native); 318 | } 319 | 320 | base.EmitNativeCall (typeInfo, nativeMethod, psig, nativePtr); 321 | 322 | if (hiddenReturnByValue) { 323 | EmitCreateCppObjectFromNative (il, returnType, returnValue); 324 | 325 | if (returnType.IsValueType) { 326 | // FIXME: This dispose should prolly be in a Finally block.. 327 | il.Emit (OpCodes.Ldloca, returnValue); 328 | il.Emit (OpCodes.Call, cppip_dispose); 329 | } 330 | } 331 | } 332 | 333 | 334 | } 335 | } -------------------------------------------------------------------------------- /src/Mono.Cxxi/Abi/Impl/ItaniumTypeInfo.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Mono.Cxxi.Abi.ItaniumTypeInfo.cs: An implementation of the Itanium C++ ABI 3 | // 4 | // Author: 5 | // Alexander Corrado (alexander.corrado@gmail.com) 6 | // 7 | // Copyright (C) 2011 Alexander Corrado 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining 10 | // a copy of this software and associated documentation files (the 11 | // "Software"), to deal in the Software without restriction, including 12 | // without limitation the rights to use, copy, modify, merge, publish, 13 | // distribute, sublicense, and/or sell copies of the Software, and to 14 | // permit persons to whom the Software is furnished to do so, subject to 15 | // the following conditions: 16 | // 17 | // The above copyright notice and this permission notice shall be 18 | // included in all copies or substantial portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 24 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 25 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 26 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | 28 | using System; 29 | using System.Linq; 30 | using System.Collections.Generic; 31 | using System.Runtime.InteropServices; 32 | using System.Reflection; 33 | 34 | using Mono.Cxxi.Util; 35 | 36 | namespace Mono.Cxxi.Abi { 37 | 38 | public class ItaniumTypeInfo : CppTypeInfo { 39 | 40 | protected internal bool? has_non_default_copy_ctor_or_dtor; 41 | 42 | public ItaniumTypeInfo (CppLibrary lib, string typeName, Type interfaceType, Type nativeLayout, Type/*?*/ wrapperType) 43 | : base (lib, typeName, interfaceType, nativeLayout, wrapperType) 44 | { 45 | } 46 | /* 47 | protected override void AddBase (CppTypeInfo baseType, BaseVirtualMethods location) 48 | { 49 | if (TypeComplete) 50 | return; 51 | 52 | // When adding a non-primary base class's complete vtable, we need to reserve space for 53 | // the stuff before the address point of the vtptr.. 54 | // Includes vbase & vcall offsets (virtual inheritance), offset to top, and RTTI info 55 | if (addVTable) { 56 | 57 | // FIXME: virtual inheritance 58 | virtual_methods.Add (null); 59 | virtual_methods.Add (null); 60 | 61 | vt_overrides.Add (2); 62 | vt_delegate_types.Add (2); 63 | } 64 | 65 | base.AddBase (baseType, addVTable); 66 | } 67 | */ 68 | protected override bool OnVTableDuplicate (ref int iter, ref int adj, PInvokeSignature sig, PInvokeSignature dup) 69 | { 70 | var isOverride = base.OnVTableDuplicate (ref iter, ref adj, sig, dup); 71 | if (isOverride && sig.Type == MethodType.NativeDtor) { 72 | 73 | // also remove that pesky extra dtor 74 | virtual_methods.RemoveAt (iter + 1); 75 | vt_overrides.Remove (1); 76 | vt_delegate_types.Remove (1); 77 | vtable_index_adjustments.Add (0); 78 | adj--; 79 | return true; 80 | } 81 | 82 | return false; 83 | } 84 | 85 | } 86 | } 87 | 88 | -------------------------------------------------------------------------------- /src/Mono.Cxxi/Abi/Impl/MsvcAbi.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Mono.Cxxi.Abi.MsvcAbi.cs: An implementation of the Microsoft Visual C++ ABI 3 | // 4 | // Author: 5 | // Alexander Corrado (alexander.corrado@gmail.com) 6 | // Andreia Gaita (shana@spoiledcat.net) 7 | // 8 | // Copyright (C) 2010-2011 Alexander Corrado 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining 11 | // a copy of this software and associated documentation files (the 12 | // "Software"), to deal in the Software without restriction, including 13 | // without limitation the rights to use, copy, modify, merge, publish, 14 | // distribute, sublicense, and/or sell copies of the Software, and to 15 | // permit persons to whom the Software is furnished to do so, subject to 16 | // the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be 19 | // included in all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 25 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 26 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 27 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | 29 | using System; 30 | using System.Linq; 31 | using System.Text; 32 | using System.Reflection; 33 | using System.Collections.Generic; 34 | using System.Runtime.InteropServices; 35 | 36 | using Mono.Cxxi; 37 | using Mono.Cxxi.Util; 38 | 39 | namespace Mono.Cxxi.Abi { 40 | 41 | // FIXME: No 64-bit support 42 | public class MsvcAbi : CppAbi { 43 | 44 | public static readonly MsvcAbi Instance = new MsvcAbi (); 45 | 46 | private MsvcAbi () 47 | { 48 | } 49 | 50 | public override CallingConvention? GetCallingConvention (MethodInfo methodInfo) 51 | { 52 | // FIXME: Varargs methods ... ? 53 | 54 | if (IsStatic (methodInfo)) 55 | return CallingConvention.Cdecl; 56 | else 57 | return CallingConvention.ThisCall; 58 | } 59 | 60 | protected override string GetMangledMethodName (CppTypeInfo typeInfo, MethodInfo methodInfo) 61 | { 62 | var methodName = methodInfo.Name; 63 | var type = typeInfo.GetMangleType (); 64 | var className = type.ElementTypeName; 65 | 66 | MethodType methodType = GetMethodType (typeInfo, methodInfo); 67 | ParameterInfo [] parameters = methodInfo.GetParameters (); 68 | 69 | StringBuilder nm = new StringBuilder ("?", 30); 70 | 71 | if (methodType == MethodType.NativeCtor) 72 | nm.Append ("?0"); 73 | else if (methodType == MethodType.NativeDtor) 74 | nm.Append ("?1"); 75 | else 76 | nm.Append (methodName).Append ('@'); 77 | 78 | // FIXME: This has to include not only the name of the immediate containing class, 79 | // but also all names of containing classes and namespaces up the hierarchy. 80 | nm.Append (className).Append ("@@"); 81 | 82 | // function modifiers are a matrix of consecutive uppercase letters 83 | // depending on access type and virtual (far)/static (far)/far modifiers 84 | 85 | // first, access type 86 | char funcModifier = 'Q'; // (public) 87 | if (IsProtected (methodInfo)) 88 | funcModifier = 'I'; 89 | else if (IsPrivate (methodInfo)) // (probably don't need this) 90 | funcModifier = 'A'; 91 | 92 | // now, offset based on other modifiers 93 | if (IsStatic (methodInfo)) 94 | funcModifier += (char)2; 95 | else if (IsVirtual (methodInfo)) 96 | funcModifier += (char)4; 97 | 98 | nm.Append (funcModifier); 99 | 100 | // FIXME: deal with other storage classes for "this" i.e. the "volatile" in -> int foo () volatile; 101 | if (!IsStatic (methodInfo)) { 102 | if (IsConst (methodInfo)) 103 | nm.Append ('B'); 104 | else 105 | nm.Append ('A'); 106 | } 107 | 108 | switch (GetCallingConvention (methodInfo)) { 109 | case CallingConvention.Cdecl: 110 | nm.Append ('A'); 111 | break; 112 | case CallingConvention.ThisCall: 113 | nm.Append ('E'); 114 | break; 115 | case CallingConvention.StdCall: 116 | nm.Append ('G'); 117 | break; 118 | case CallingConvention.FastCall: 119 | nm.Append ('I'); 120 | break; 121 | } 122 | 123 | // FIXME: handle const, volatile modifiers on return type 124 | // FIXME: the manual says this is only omitted for simple types.. are we doing the right thing here? 125 | CppType returnType = GetMangleType (methodInfo.ReturnTypeCustomAttributes, methodInfo.ReturnType); 126 | if (returnType.ElementType == CppTypes.Class || 127 | returnType.ElementType == CppTypes.Struct || 128 | returnType.ElementType == CppTypes.Union) 129 | nm.Append ("?A"); 130 | 131 | if (methodType == MethodType.NativeCtor || methodType == MethodType.NativeDtor) 132 | nm.Append ('@'); 133 | else 134 | nm.Append (GetTypeCode (returnType)); 135 | 136 | int argStart = (IsStatic (methodInfo)? 0 : 1); 137 | if (parameters.Length == argStart) { // no args (other than C++ "this" object) 138 | nm.Append ("XZ"); 139 | return nm.ToString (); 140 | } else 141 | for (int i = argStart; i < parameters.Length; i++) 142 | nm.Append (GetTypeCode (GetMangleType (parameters [i], parameters [i].ParameterType))); 143 | 144 | nm.Append ("@Z"); 145 | return nm.ToString (); 146 | } 147 | 148 | public virtual string GetTypeCode (CppType mangleType) 149 | { 150 | CppTypes element = mangleType.ElementType; 151 | IEnumerable modifiers = mangleType.Modifiers; 152 | 153 | StringBuilder code = new StringBuilder (); 154 | 155 | var ptr = For.AnyInputIn (CppModifiers.Pointer); 156 | var ptrRefOrArray = For.AnyInputIn (CppModifiers.Pointer, CppModifiers.Reference, CppModifiers.Array); 157 | 158 | var modifierCode = modifiers.Reverse ().Transform ( 159 | 160 | Choose.TopOne ( 161 | For.AllInputsIn (CppModifiers.Const, CppModifiers.Volatile).InAnyOrder ().After (ptrRefOrArray).Emit ('D'), 162 | For.AnyInputIn (CppModifiers.Const).After (ptrRefOrArray).Emit ('B'), 163 | For.AnyInputIn (CppModifiers.Volatile).After (ptrRefOrArray).Emit ('C'), 164 | For.AnyInput ().After (ptrRefOrArray).Emit ('A') 165 | ), 166 | 167 | For.AnyInputIn (CppModifiers.Array).Emit ('Q'), 168 | For.AnyInputIn (CppModifiers.Reference).Emit ('A'), 169 | 170 | Choose.TopOne ( 171 | ptr.After ().AllInputsIn (CppModifiers.Const, CppModifiers.Volatile).InAnyOrder ().Emit ('S'), 172 | ptr.After ().AnyInputIn (CppModifiers.Const).Emit ('Q'), 173 | ptr.After ().AnyInputIn (CppModifiers.Volatile).Emit ('R'), 174 | ptr.Emit ('P') 175 | ), 176 | 177 | ptrRefOrArray.AtEnd ().Emit ('A') 178 | ); 179 | code.Append (modifierCode.ToArray ()); 180 | 181 | switch (element) { 182 | case CppTypes.Void: 183 | code.Append ('X'); 184 | break; 185 | case CppTypes.Int: 186 | code.Append (modifiers.Transform ( 187 | For.AllInputsIn (CppModifiers.Unsigned, CppModifiers.Short).InAnyOrder ().Emit ('G') 188 | ).DefaultIfEmpty ('H').ToArray ()); 189 | break; 190 | case CppTypes.Char: 191 | code.Append ('D'); 192 | break; 193 | case CppTypes.Class: 194 | code.Append ('V'); 195 | code.Append(mangleType.ElementTypeName); 196 | code.Append ("@@"); 197 | break; 198 | case CppTypes.Struct: 199 | code.Append ('U'); 200 | code.Append(mangleType.ElementTypeName); 201 | code.Append ("@@"); 202 | break; 203 | case CppTypes.Union: 204 | code.Append ('T'); 205 | code.Append(mangleType.ElementTypeName); 206 | code.Append ("@@"); 207 | break; 208 | case CppTypes.Enum: 209 | code.Append ("W4"); 210 | code.Append(mangleType.ElementTypeName); 211 | code.Append ("@@"); 212 | break; 213 | } 214 | 215 | return code.ToString (); 216 | } 217 | 218 | } 219 | } 220 | 221 | -------------------------------------------------------------------------------- /src/Mono.Cxxi/Abi/MethodType.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Mono.Cxxi.Abi.MethodType.cs: Method annotation for IL codegen 3 | // 4 | // Author: 5 | // Alexander Corrado (alexander.corrado@gmail.com) 6 | // Andreia Gaita (shana@spoiledcat.net) 7 | // 8 | // Copyright (C) 2010-2011 Alexander Corrado 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining 11 | // a copy of this software and associated documentation files (the 12 | // "Software"), to deal in the Software without restriction, including 13 | // without limitation the rights to use, copy, modify, merge, publish, 14 | // distribute, sublicense, and/or sell copies of the Software, and to 15 | // permit persons to whom the Software is furnished to do so, subject to 16 | // the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be 19 | // included in all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 25 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 26 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 27 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | 29 | using System; 30 | namespace Mono.Cxxi.Abi { 31 | public enum MethodType { 32 | NoOp, 33 | NotImplemented, 34 | Native, 35 | NativeCtor, 36 | NativeDtor, 37 | ManagedAlloc 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Mono.Cxxi/Abi/SymbolResolver.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Mono.Cxxi.Abi.SymbolResolver.cs: Platform-independent dynamic symbol lookup 3 | // 4 | // Author: 5 | // Alexander Corrado (alexander.corrado@gmail.com) 6 | // 7 | // Copyright 2011 Xamarin Inc (http://www.xamarin.com) 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining 10 | // a copy of this software and associated documentation files (the 11 | // "Software"), to deal in the Software without restriction, including 12 | // without limitation the rights to use, copy, modify, merge, publish, 13 | // distribute, sublicense, and/or sell copies of the Software, and to 14 | // permit persons to whom the Software is furnished to do so, subject to 15 | // the following conditions: 16 | // 17 | // The above copyright notice and this permission notice shall be 18 | // included in all copies or substantial portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 24 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 25 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 26 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | 28 | 29 | using System; 30 | using System.Runtime.InteropServices; 31 | 32 | namespace Mono.Cxxi.Abi { 33 | internal static class SymbolResolver { 34 | 35 | static readonly string [] formats; 36 | static readonly Func load_image; 37 | static readonly Func resolve_symbol; 38 | 39 | static SymbolResolver () 40 | { 41 | switch (Environment.OSVersion.Platform) { 42 | 43 | case PlatformID.Unix: 44 | case PlatformID.MacOSX: 45 | load_image = dlopen; 46 | resolve_symbol = dlsym; 47 | formats = new[] { 48 | "{0}", 49 | "{0}.so", 50 | "{0}.dylib", 51 | "lib{0}.so", 52 | "lib{0}.dylib", 53 | "{0}.bundle" 54 | }; 55 | break; 56 | 57 | default: 58 | load_image = LoadLibrary; 59 | resolve_symbol = GetProcAddress; 60 | formats = new[] { "{0}", "{0}.dll" }; 61 | break; 62 | } 63 | } 64 | 65 | // will fix up name with a more precise name to speed up later p/invokes (hopefully?) 66 | public static IntPtr LoadImage (ref string name) 67 | { 68 | foreach (var format in formats) { 69 | var attempted = string.Format (format, name); 70 | var ptr = load_image (attempted); 71 | if (ptr != IntPtr.Zero) { 72 | name = attempted; 73 | return ptr; 74 | } 75 | } 76 | return IntPtr.Zero; 77 | } 78 | 79 | public static IntPtr ResolveSymbol (IntPtr image, string symbol) 80 | { 81 | if (image != IntPtr.Zero) 82 | return resolve_symbol (image, symbol); 83 | return IntPtr.Zero; 84 | } 85 | 86 | #region POSIX 87 | 88 | static IntPtr dlopen (string path) 89 | { 90 | return dlopen (path, 0x0); 91 | } 92 | 93 | [DllImport ("dl", CharSet=CharSet.Ansi)] 94 | static extern IntPtr dlopen (string path, int flags); 95 | 96 | [DllImport ("dl", CharSet=CharSet.Ansi)] 97 | static extern IntPtr dlsym (IntPtr handle, string symbol); 98 | 99 | #endregion 100 | 101 | #region Win32 102 | 103 | [DllImport("kernel32", SetLastError=true)] 104 | static extern IntPtr LoadLibrary (string lpFileName); 105 | 106 | [DllImport("kernel32", CharSet=CharSet.Ansi, ExactSpelling=true, SetLastError=true)] 107 | static extern IntPtr GetProcAddress (IntPtr hModule, string procName); 108 | 109 | #endregion 110 | 111 | } 112 | } 113 | 114 | -------------------------------------------------------------------------------- /src/Mono.Cxxi/Abi/VTable.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Mono.Cxxi.Abi.VTable.cs: Managed VTable Implementation 3 | // 4 | // Author: 5 | // Alexander Corrado (alexander.corrado@gmail.com) 6 | // Andreia Gaita (shana@spoiledcat.net) 7 | // 8 | // Copyright (C) 2010-2011 Alexander Corrado 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining 11 | // a copy of this software and associated documentation files (the 12 | // "Software"), to deal in the Software without restriction, including 13 | // without limitation the rights to use, copy, modify, merge, publish, 14 | // distribute, sublicense, and/or sell copies of the Software, and to 15 | // permit persons to whom the Software is furnished to do so, subject to 16 | // the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be 19 | // included in all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 25 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 26 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 27 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | 29 | using System; 30 | using System.Diagnostics; 31 | using System.Collections.Generic; 32 | 33 | using System.Reflection; 34 | using System.Reflection.Emit; 35 | using System.Runtime.InteropServices; 36 | 37 | namespace Mono.Cxxi.Abi { 38 | 39 | // TODO: RTTI .. support virtual inheritance 40 | 41 | public class VTable : IDisposable { 42 | 43 | protected bool initialized; 44 | protected CppTypeInfo type_info; 45 | protected IntPtr vtPtr; 46 | 47 | public virtual int EntryCount { 48 | get { return type_info.VirtualMethods.Count; } 49 | } 50 | public virtual int EntrySize { 51 | get { return IntPtr.Size; } 52 | } 53 | 54 | // Subclasses should allocate vtPtr and then call WriteOverrides 55 | public VTable (CppTypeInfo typeInfo) 56 | { 57 | this.initialized = false; 58 | this.type_info = typeInfo; 59 | this.vtPtr = Marshal.AllocHGlobal ((EntryCount * EntrySize) + typeInfo.VTableTopPadding + typeInfo.VTableBottomPadding); 60 | 61 | WriteOverrides (); 62 | CppInstancePtr.RegisterManagedVTable (this); 63 | } 64 | 65 | protected virtual void WriteOverrides () 66 | { 67 | IntPtr vtEntryPtr; 68 | int currentOffset = type_info.VTableTopPadding; 69 | for (int i = 0; i < EntryCount; i++) { 70 | Delegate currentOverride = type_info.VTableOverrides [i]; 71 | 72 | if (currentOverride != null) // managed override 73 | vtEntryPtr = Marshal.GetFunctionPointerForDelegate (currentOverride); 74 | else 75 | vtEntryPtr = IntPtr.Zero; 76 | 77 | Marshal.WriteIntPtr (vtPtr, currentOffset, vtEntryPtr); 78 | currentOffset += EntrySize; 79 | } 80 | } 81 | 82 | public virtual T GetVirtualCallDelegate (CppInstancePtr instance, int index) 83 | where T : class /*Delegate*/ 84 | { 85 | var vtable = instance.NativeVTable; 86 | 87 | var ftnptr = Marshal.ReadIntPtr (vtable, (index * EntrySize) + type_info.VTableTopPadding); 88 | if (ftnptr == IntPtr.Zero) 89 | throw new NullReferenceException ("Native VTable contains null...possible abstract class???"); 90 | 91 | var del = Marshal.GetDelegateForFunctionPointer (ftnptr, typeof (T)); 92 | return del as T; 93 | } 94 | 95 | // FIXME: Make this method unsafe.. it would probably be much faster 96 | public virtual void InitInstance (ref CppInstancePtr instance) 97 | { 98 | var basePtr = Marshal.ReadIntPtr (instance.Native); 99 | Debug.Assert (basePtr != IntPtr.Zero); 100 | 101 | if (basePtr == vtPtr) 102 | return; 103 | 104 | instance.NativeVTable = basePtr; 105 | 106 | if (!initialized) { 107 | 108 | // FIXME: This could probably be a more efficient memcpy 109 | for (int i = 0; i < type_info.VTableTopPadding; i++) 110 | Marshal.WriteByte(vtPtr, i, Marshal.ReadByte(basePtr, i)); 111 | 112 | int currentOffset = type_info.VTableTopPadding; 113 | for (int i = 0; i < EntryCount; i++) { 114 | if (Marshal.ReadIntPtr (vtPtr, currentOffset) == IntPtr.Zero) 115 | Marshal.WriteIntPtr (vtPtr, currentOffset, Marshal.ReadIntPtr (basePtr, currentOffset)); 116 | 117 | currentOffset += EntrySize; 118 | } 119 | 120 | // FIXME: This could probably be a more efficient memcpy 121 | for (int i = 0; i < type_info.VTableBottomPadding; i++) 122 | Marshal.WriteByte(vtPtr, currentOffset + i, Marshal.ReadByte(basePtr, currentOffset + i)); 123 | 124 | initialized = true; 125 | } 126 | 127 | Marshal.WriteIntPtr (instance.Native, vtPtr); 128 | } 129 | 130 | public virtual void ResetInstance (CppInstancePtr instance) 131 | { 132 | Marshal.WriteIntPtr (instance.Native, instance.NativeVTable); 133 | } 134 | 135 | public CppTypeInfo TypeInfo { 136 | get { return type_info; } 137 | } 138 | 139 | public IntPtr Pointer { 140 | get { return vtPtr; } 141 | } 142 | 143 | protected virtual void Dispose (bool disposing) 144 | { 145 | if (vtPtr != IntPtr.Zero) { 146 | Marshal.FreeHGlobal (vtPtr); 147 | vtPtr = IntPtr.Zero; 148 | } 149 | } 150 | 151 | // TODO: This WON'T usually be called because VTables are associated with classes 152 | // (not instances) and managed C++ class wrappers are staticly held? 153 | public void Dispose () 154 | { 155 | Dispose (true); 156 | GC.SuppressFinalize (this); 157 | } 158 | 159 | ~VTable () 160 | { 161 | Dispose (false); 162 | } 163 | 164 | public static bool BindToSignatureAndAttribute (MemberInfo member, object obj) 165 | { 166 | var overrideNative = member.GetCustomAttributes (typeof (OverrideNativeAttribute), true); 167 | if (overrideNative.Length == 0) 168 | return false; 169 | 170 | var name = ((OverrideNativeAttribute)overrideNative [0]).NativeMethod ?? member.Name; 171 | 172 | return BindToSignature (member, obj, name); 173 | } 174 | 175 | public static bool BindToSignature (MemberInfo member, object obj) 176 | { 177 | return BindToSignature (member, obj, member.Name); 178 | } 179 | 180 | public static bool BindToSignature (MemberInfo member, object obj, string nativeMethod) 181 | { 182 | MethodInfo imethod = (MethodInfo) obj; 183 | MethodInfo candidate = (MethodInfo) member; 184 | 185 | if (nativeMethod != imethod.Name) 186 | return false; 187 | 188 | ParameterInfo[] invokeParams = imethod.GetParameters (); 189 | ParameterInfo[] methodParams = candidate.GetParameters (); 190 | 191 | if (invokeParams.Length == methodParams.Length) { 192 | for (int i = 0; i < invokeParams.Length; i++) { 193 | if (!invokeParams [i].ParameterType.IsAssignableFrom (methodParams [i].ParameterType)) 194 | return false; 195 | } 196 | } else if (invokeParams.Length == methodParams.Length + 1) { 197 | for (int i = 1; i < invokeParams.Length; i++) { 198 | if (!invokeParams [i].ParameterType.IsAssignableFrom (methodParams [i - 1].ParameterType)) 199 | return false; 200 | } 201 | } else 202 | return false; 203 | 204 | return true; 205 | } 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /src/Mono.Cxxi/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Author: 2 | // Alexander Corrado (alexander.corrado@gmail.com) 3 | // Andreia Gaita (shana@spoiledcat.net) 4 | // 5 | // Copyright (C) 2010-2011 Alexander Corrado 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining 8 | // a copy of this software and associated documentation files (the 9 | // "Software"), to deal in the Software without restriction, including 10 | // without limitation the rights to use, copy, modify, merge, publish, 11 | // distribute, sublicense, and/or sell copies of the Software, and to 12 | // permit persons to whom the Software is furnished to do so, subject to 13 | // the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 22 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | 26 | using System; 27 | using System.Reflection; 28 | using System.Runtime.CompilerServices; 29 | 30 | // Information about this assembly is defined by the following attributes. 31 | // Change them to the values specific to your project. 32 | 33 | [assembly: AssemblyTitle("Mono.Cxxi")] 34 | [assembly: AssemblyDescription("")] 35 | [assembly: AssemblyConfiguration("")] 36 | [assembly: AssemblyCompany("")] 37 | [assembly: AssemblyProduct("")] 38 | [assembly: AssemblyCopyright("")] 39 | [assembly: AssemblyTrademark("")] 40 | [assembly: AssemblyCulture("")] 41 | 42 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 43 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 44 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 45 | 46 | [assembly: AssemblyVersion("1.0.*")] 47 | 48 | // The following attributes are used to specify the signing key for the assembly, 49 | // if desired. See the Mono documentation for more information about signing. 50 | 51 | //[assembly: AssemblyDelaySign(false)] 52 | //[assembly: AssemblyKeyFile("")] 53 | 54 | [assembly: CLSCompliant(true)] 55 | // FIXME: This will not work if we ever support saving these assemblies 56 | [assembly: InternalsVisibleTo("__CppLibraryImplAssembly")] 57 | -------------------------------------------------------------------------------- /src/Mono.Cxxi/Attributes.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Mono.Cxxi.Attributes.cs 3 | // 4 | // Author: 5 | // Alexander Corrado (alexander.corrado@gmail.com) 6 | // 7 | // Copyright (C) 2010 Alexander Corrado 8 | // 9 | 10 | using System; 11 | using System.Linq; 12 | using System.Reflection; 13 | 14 | namespace Mono.Cxxi { 15 | 16 | #region Interface method attributes 17 | 18 | [AttributeUsage (AttributeTargets.Method)] 19 | public class ConstructorAttribute : Attribute {} 20 | 21 | [AttributeUsage (AttributeTargets.Method)] 22 | public class DestructorAttribute : Attribute {} 23 | 24 | 25 | [AttributeUsage (AttributeTargets.Method)] 26 | public class VirtualAttribute : Attribute {} 27 | 28 | [AttributeUsage (AttributeTargets.Method)] 29 | public class StaticAttribute : Attribute {} 30 | 31 | // used for the const "this" - for example: int value () const; 32 | // use MangleAsAttribute for const parameters 33 | [AttributeUsage (AttributeTargets.Method)] 34 | public class ConstAttribute : Attribute {} 35 | 36 | // FIXME: Will we ever be calling private methods? 37 | [AttributeUsage (AttributeTargets.Method)] 38 | public class PrivateAttribute : Attribute {} 39 | 40 | [AttributeUsage (AttributeTargets.Method)] 41 | public class ProtectedAttribute : Attribute {} 42 | 43 | [AttributeUsage (AttributeTargets.Method)] 44 | public class InlineAttribute : Attribute {} 45 | 46 | [AttributeUsage (AttributeTargets.Method)] 47 | public class ArtificialAttribute : Attribute {} 48 | 49 | [AttributeUsage (AttributeTargets.Method)] 50 | public class CopyConstructorAttribute : Attribute {} 51 | 52 | // applied when the target would normally be passed by reference (e.g. class) 53 | [AttributeUsage (AttributeTargets.Parameter | AttributeTargets.ReturnValue)] 54 | public class ByValAttribute : Attribute {} 55 | 56 | // used for byref return of things that would normally be passed by value (e.g. int&) 57 | [AttributeUsage (AttributeTargets.ReturnValue)] 58 | public class ByRefAttribute : Attribute {} 59 | 60 | [AttributeUsage (AttributeTargets.Interface | AttributeTargets.Parameter | AttributeTargets.ReturnValue)] 61 | public class MangleAsAttribute : Attribute { 62 | public CppType MangleType { get; private set; } 63 | 64 | public MangleAsAttribute (CppType mangleType) 65 | { 66 | this.MangleType = mangleType; 67 | } 68 | public MangleAsAttribute (string mangleTypeStr) 69 | { 70 | this.MangleType = new CppType (mangleTypeStr); 71 | } 72 | public MangleAsAttribute (params object [] cppTypeSpec) 73 | { 74 | this.MangleType = new CppType (cppTypeSpec); 75 | } 76 | } 77 | 78 | // for testing: 79 | [AttributeUsage (AttributeTargets.Method)] 80 | public class AbiTestAttribute : Attribute { 81 | public string MangledName { get; set; } 82 | public Type Abi { get; set; } 83 | 84 | public AbiTestAttribute (string mangledName) 85 | { 86 | MangledName = mangledName; 87 | } 88 | } 89 | 90 | #endregion 91 | 92 | #region Wrapper method attributes 93 | [AttributeUsage (AttributeTargets.Method)] 94 | public class OverrideNativeAttribute : Attribute { 95 | public string NativeMethod { get; set; } 96 | public OverrideNativeAttribute () 97 | { 98 | } 99 | public OverrideNativeAttribute (string nativeMethod) 100 | { 101 | this.NativeMethod = nativeMethod; 102 | } 103 | } 104 | #endregion 105 | } 106 | 107 | namespace Mono.Cxxi.Abi { 108 | using Mono.Cxxi; 109 | 110 | public partial class CppAbi { 111 | 112 | public virtual bool IsVirtual (MethodInfo method) 113 | { 114 | return method.IsDefined (typeof (VirtualAttribute), false); 115 | } 116 | public virtual bool IsStatic (MethodInfo method) 117 | { 118 | return method.IsDefined (typeof (StaticAttribute), false); 119 | } 120 | public virtual bool IsConst (MethodInfo method) 121 | { 122 | return method.IsDefined (typeof (ConstAttribute), false); 123 | } 124 | public virtual bool IsPrivate (MethodInfo method) 125 | { 126 | return method.IsDefined (typeof (PrivateAttribute), false); 127 | } 128 | public virtual bool IsProtected (MethodInfo method) 129 | { 130 | return method.IsDefined (typeof (ProtectedAttribute), false); 131 | } 132 | public virtual bool IsInline (MethodInfo method) 133 | { 134 | return method.IsDefined (typeof (InlineAttribute), false); 135 | } 136 | public virtual bool IsArtificial (MethodInfo method) 137 | { 138 | return method.IsDefined (typeof (ArtificialAttribute), false); 139 | } 140 | public virtual bool IsCopyConstructor (MethodInfo method) 141 | { 142 | return method.IsDefined (typeof (CopyConstructorAttribute), false); 143 | } 144 | public virtual bool IsByVal (ICustomAttributeProvider icap) 145 | { 146 | return icap.IsDefined (typeof (ByValAttribute), false); 147 | } 148 | public virtual bool IsByRef (ICustomAttributeProvider icap, Type type) 149 | { 150 | return type.IsByRef || icap.IsDefined (typeof (ByRefAttribute), false); 151 | } 152 | 153 | public virtual CppType GetMangleType (ICustomAttributeProvider icap, Type managedType) 154 | { 155 | CppType mangleType = new CppType (); 156 | MangleAsAttribute maa = (MangleAsAttribute)icap.GetCustomAttributes (typeof (MangleAsAttribute), false).FirstOrDefault (); 157 | if (maa != null) 158 | mangleType = maa.MangleType; 159 | 160 | // this means that either no MangleAsAttribute was defined, or 161 | // only CppModifiers were applied .. apply CppType from managed parameter type 162 | if (mangleType.ElementType == CppTypes.Unknown && mangleType.ElementTypeName == null) 163 | mangleType.CopyTypeFrom (CppType.ForManagedType (managedType)); 164 | else if (mangleType.ElementType == CppTypes.Unknown) 165 | // FIXME: otherwise, we just assume it's CppTypes.Class for now. 166 | mangleType.ElementType = CppTypes.Class; 167 | 168 | return mangleType; 169 | } 170 | 171 | } 172 | 173 | } 174 | -------------------------------------------------------------------------------- /src/Mono.Cxxi/CppField.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Mono.Cxxi.CppField.cs: Represents a field in a native C++ object 3 | // 4 | // Author: 5 | // Alexander Corrado (alexander.corrado@gmail.com) 6 | // Andreia Gaita (shana@spoiledcat.net) 7 | // 8 | // Copyright (C) 2010-2011 Alexander Corrado 9 | // Copyright 2011 Xamarin Inc (http://www.xamarin.com) 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining 12 | // a copy of this software and associated documentation files (the 13 | // "Software"), to deal in the Software without restriction, including 14 | // without limitation the rights to use, copy, modify, merge, publish, 15 | // distribute, sublicense, and/or sell copies of the Software, and to 16 | // permit persons to whom the Software is furnished to do so, subject to 17 | // the following conditions: 18 | // 19 | // The above copyright notice and this permission notice shall be 20 | // included in all copies or substantial portions of the Software. 21 | // 22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 23 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 24 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 25 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 26 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 27 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 28 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | 30 | using System; 31 | using System.Runtime.InteropServices; 32 | 33 | namespace Mono.Cxxi { 34 | public class CppField { 35 | private int fieldOffset; 36 | 37 | public CppField (int fieldOffset) 38 | { 39 | this.fieldOffset = fieldOffset; 40 | } 41 | 42 | public T this [CppInstancePtr ip] { 43 | get { 44 | 45 | Type retType = typeof (T).IsEnum? Enum.GetUnderlyingType (typeof (T)) : typeof (T); 46 | object retVal; 47 | 48 | if (retType.Equals (typeof (IntPtr))) 49 | retVal = Marshal.ReadIntPtr (ip.Native, fieldOffset); 50 | else if (retType.Equals (typeof (Byte))) 51 | retVal = Marshal.ReadByte (ip.Native, fieldOffset); 52 | else if (retType.Equals (typeof (Int16))) 53 | retVal = Marshal.ReadInt16 (ip.Native, fieldOffset); 54 | else if (retType.Equals (typeof (Int32))) 55 | retVal = Marshal.ReadInt32 (ip.Native, fieldOffset); 56 | 57 | else if (typeof (ICppObject).IsAssignableFrom (retType)) { 58 | 59 | var ptr = Marshal.ReadIntPtr (ip.Native, fieldOffset); 60 | if (ptr == IntPtr.Zero) 61 | return default (T); 62 | 63 | var ctor = retType.GetConstructor (new Type [] { typeof (IntPtr) }); 64 | if (ctor != null) { 65 | 66 | retVal = ctor.Invoke (new object [] { ptr }); 67 | 68 | } else { 69 | ctor = retType.GetConstructor (new Type [] { typeof (CppInstancePtr) }); 70 | if (ctor == null) 71 | throw new NotSupportedException ("Type " + retType.Name + " does not have a constructor that takes either IntPtr or CppInstancePtr."); 72 | 73 | retVal = ctor.Invoke (new object [] { new CppInstancePtr (ptr) }); 74 | } 75 | 76 | } else { 77 | throw new NotSupportedException ("Cannot read C++ fields of type " + retType.Name); 78 | } 79 | 80 | return (T)retVal; 81 | } 82 | set { 83 | Type setType = typeof (T).IsEnum? Enum.GetUnderlyingType (typeof (T)) : typeof (T); 84 | object setVal = value; 85 | 86 | if (setType.Equals (typeof (IntPtr))) 87 | Marshal.WriteIntPtr (ip.Native, fieldOffset, (IntPtr)setVal); 88 | else if (setType.Equals (typeof (Byte))) 89 | Marshal.WriteByte (ip.Native, fieldOffset, (byte)setVal); 90 | else if (setType.Equals (typeof (Int16))) 91 | Marshal.WriteInt16 (ip.Native, fieldOffset, (Int16)setVal); 92 | else if (setType.Equals (typeof (Int32))) 93 | Marshal.WriteInt32 (ip.Native, fieldOffset, (Int32)setVal); 94 | 95 | else if (typeof (ICppObject).IsAssignableFrom (setType)) { 96 | 97 | if (value == null) { 98 | Marshal.WriteIntPtr (ip.Native, fieldOffset, IntPtr.Zero); 99 | 100 | } else { 101 | 102 | var cppobj = (ICppObject)value; 103 | Marshal.WriteIntPtr (ip.Native, fieldOffset, (IntPtr)cppobj.Native); 104 | } 105 | 106 | } else { 107 | throw new NotSupportedException ("Cannot write C++ fields of type " + setType.Name); 108 | } 109 | 110 | } 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/Mono.Cxxi/CppInstancePtr.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Mono.Cxxi.CppInstancePtr.cs: Represents a pointer to a native C++ instance 3 | // 4 | // Author: 5 | // Alexander Corrado (alexander.corrado@gmail.com) 6 | // Andreia Gaita (shana@spoiledcat.net) 7 | // 8 | // Copyright (C) 2010-2011 Alexander Corrado 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining 11 | // a copy of this software and associated documentation files (the 12 | // "Software"), to deal in the Software without restriction, including 13 | // without limitation the rights to use, copy, modify, merge, publish, 14 | // distribute, sublicense, and/or sell copies of the Software, and to 15 | // permit persons to whom the Software is furnished to do so, subject to 16 | // the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be 19 | // included in all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 25 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 26 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 27 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | 29 | using System; 30 | using System.Reflection.Emit; 31 | using System.Collections.Generic; 32 | using System.Runtime.InteropServices; 33 | using System.Diagnostics; 34 | 35 | using Mono.Cxxi.Abi; 36 | 37 | namespace Mono.Cxxi { 38 | public struct CppInstancePtr : ICppObject { 39 | 40 | private IntPtr ptr, native_vtptr; 41 | private bool manage_memory; 42 | 43 | private static Dictionary managed_vtptr_to_gchandle_offset = null; 44 | 45 | // Alloc a new C++ instance 46 | internal CppInstancePtr (CppTypeInfo typeInfo, object managedWrapper) 47 | { 48 | // Under the hood, we're secretly subclassing this C++ class to store a 49 | // handle to the managed wrapper. 50 | int allocSize = typeInfo.GCHandleOffset + IntPtr.Size; 51 | ptr = Marshal.AllocHGlobal (allocSize); 52 | 53 | // NOTE: native_vtptr will be set later after native ctor is called 54 | native_vtptr = IntPtr.Zero; 55 | 56 | // zero memory for sanity 57 | // FIXME: This should be an initblk 58 | byte[] zeroArray = new byte [allocSize]; 59 | Marshal.Copy (zeroArray, 0, ptr, allocSize); 60 | 61 | IntPtr handlePtr = MakeGCHandle (managedWrapper); 62 | Marshal.WriteIntPtr (ptr, typeInfo.GCHandleOffset, handlePtr); 63 | 64 | manage_memory = true; 65 | } 66 | 67 | // Alloc a new C++ instance when there is no managed wrapper. 68 | internal CppInstancePtr (int nativeSize) 69 | { 70 | ptr = Marshal.AllocHGlobal (nativeSize); 71 | native_vtptr = IntPtr.Zero; 72 | manage_memory = true; 73 | } 74 | 75 | // Gets a casted CppInstancePtr 76 | internal CppInstancePtr (CppInstancePtr instance, int offset) 77 | { 78 | // FIXME: On NET_4_0 use IntPtr.Add 79 | ptr = new IntPtr (instance.Native.ToInt64 () + offset); 80 | native_vtptr = IntPtr.Zero; 81 | manage_memory = false; 82 | } 83 | 84 | // Get a CppInstancePtr for an existing C++ instance from an IntPtr 85 | public CppInstancePtr (IntPtr native) 86 | { 87 | if (native == IntPtr.Zero) 88 | throw new ArgumentOutOfRangeException ("native cannot be null pointer"); 89 | 90 | ptr = native; 91 | native_vtptr = IntPtr.Zero; 92 | manage_memory = false; 93 | } 94 | 95 | // Fulfills ICppObject requirement 96 | public CppInstancePtr (CppInstancePtr copy) 97 | { 98 | this.ptr = copy.ptr; 99 | this.native_vtptr = copy.native_vtptr; 100 | this.manage_memory = copy.manage_memory; 101 | } 102 | 103 | // Provide casts to/from IntPtr: 104 | public static implicit operator CppInstancePtr (IntPtr native) 105 | { 106 | return new CppInstancePtr (native); 107 | } 108 | 109 | // cast from CppInstancePtr -> IntPtr is explicit because we lose information 110 | public static explicit operator IntPtr (CppInstancePtr ip) 111 | { 112 | return ip.Native; 113 | } 114 | 115 | public IntPtr Native { 116 | get { 117 | if (ptr == IntPtr.Zero) 118 | throw new ObjectDisposedException ("CppInstancePtr"); 119 | 120 | return ptr; 121 | } 122 | } 123 | 124 | // Internal for now to prevent attempts to read vtptr from non-virtual class 125 | internal IntPtr NativeVTable { 126 | get { 127 | 128 | if (native_vtptr == IntPtr.Zero) { 129 | // For pointers from native code... 130 | // Kludge! CppInstancePtr doesn't know whether this class is virtual or not, but we'll just assume that either 131 | // way it's at least sizeof(void*) and read what would be the vtptr anyway. Supposedly, if it's not virtual, 132 | // the wrappers won't use this field anyway... 133 | native_vtptr = Marshal.ReadIntPtr (ptr); 134 | } 135 | 136 | return native_vtptr; 137 | } 138 | set { 139 | native_vtptr = value; 140 | } 141 | } 142 | 143 | CppInstancePtr ICppObject.Native { 144 | get { return this; } 145 | } 146 | 147 | public bool IsManagedAlloc { 148 | get { return manage_memory; } 149 | } 150 | 151 | internal static void RegisterManagedVTable (VTable vtable) 152 | { 153 | if (managed_vtptr_to_gchandle_offset == null) 154 | managed_vtptr_to_gchandle_offset = new Dictionary (); 155 | 156 | managed_vtptr_to_gchandle_offset [vtable.Pointer] = vtable.TypeInfo.GCHandleOffset; 157 | } 158 | 159 | internal static IntPtr MakeGCHandle (object managedWrapper) 160 | { 161 | // TODO: Dispose() should probably be called at some point on this GCHandle. 162 | GCHandle handle = GCHandle.Alloc (managedWrapper, GCHandleType.Normal); 163 | return GCHandle.ToIntPtr (handle); 164 | } 165 | 166 | // This might be made public, but in this form it only works for classes with vtables. 167 | // Returns null if the native ptr passed in does not appear to be a managed instance. 168 | // (i.e. its vtable ptr is not in managed_vtptr_to_gchandle_offset) 169 | internal static T ToManaged (IntPtr native) where T : class 170 | { 171 | if (managed_vtptr_to_gchandle_offset == null) 172 | return null; 173 | 174 | int gchOffset; 175 | if (!managed_vtptr_to_gchandle_offset.TryGetValue (Marshal.ReadIntPtr (native), out gchOffset)) 176 | return null; 177 | 178 | return ToManaged (native, gchOffset); 179 | } 180 | 181 | // WARNING! This method is not safe. DO NOT call 182 | // if we do not KNOW that this instance is managed. 183 | internal static T ToManaged (IntPtr native, int nativeSize) where T : class 184 | { 185 | IntPtr handlePtr = Marshal.ReadIntPtr (native, nativeSize); 186 | GCHandle handle = GCHandle.FromIntPtr (handlePtr); 187 | 188 | return handle.Target as T; 189 | } 190 | 191 | // TODO: Free GCHandle? 192 | public void Dispose () 193 | { 194 | if (manage_memory && ptr != IntPtr.Zero) 195 | Marshal.FreeHGlobal (ptr); 196 | 197 | ptr = IntPtr.Zero; 198 | manage_memory = false; 199 | } 200 | } 201 | } 202 | -------------------------------------------------------------------------------- /src/Mono.Cxxi/CppLibrary.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Mono.Cxxi.CppLibrary.cs: Represents a native C++ library for interop 3 | // 4 | // Author: 5 | // Alexander Corrado (alexander.corrado@gmail.com) 6 | // Andreia Gaita (shana@spoiledcat.net) 7 | // 8 | // Copyright (C) 2010-2011 Alexander Corrado 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining 11 | // a copy of this software and associated documentation files (the 12 | // "Software"), to deal in the Software without restriction, including 13 | // without limitation the rights to use, copy, modify, merge, publish, 14 | // distribute, sublicense, and/or sell copies of the Software, and to 15 | // permit persons to whom the Software is furnished to do so, subject to 16 | // the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be 19 | // included in all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 25 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 26 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 27 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | 29 | 30 | using System; 31 | using System.IO; 32 | using System.Collections.Generic; 33 | using System.Runtime.InteropServices; 34 | 35 | using System.Reflection; 36 | using System.Reflection.Emit; 37 | 38 | using Mono.Cxxi.Abi; 39 | 40 | namespace Mono.Cxxi { 41 | 42 | public enum InlineMethods { 43 | 44 | // Normally, C++ inline methods are not exported from the library, so C++ interop cannot call them. 45 | // This is the default option. It throws a NotImplementedException if you try to call the native version of one of these methods. 46 | // Use this if you reimplement the inline methods in managed code, or if they are not to be available in the bindings. 47 | NotPresent, 48 | 49 | // Expect the inline methods to be present in the specified library 50 | // For example, if the library was compiled with GCC's -fkeep-inline-functions option 51 | Present, 52 | 53 | // Expect the inline methods to be exported in a separate library named %name%-inline 54 | SurrogateLib, 55 | } 56 | 57 | public sealed class CppLibrary { 58 | internal static AssemblyBuilder interopAssembly; 59 | internal static ModuleBuilder interopModule; 60 | 61 | public CppAbi Abi { get; private set; } 62 | public InlineMethods InlineMethodPolicy { get; private set; } 63 | 64 | internal string name; 65 | public string Name { get { return name; } } 66 | 67 | static CppLibrary () 68 | { 69 | AssemblyName assemblyName = new AssemblyName ("__CppLibraryImplAssembly"); 70 | string moduleName = "CppLibraryImplAssembly.dll"; 71 | 72 | interopAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly (assemblyName, AssemblyBuilderAccess.RunAndSave); 73 | interopModule = interopAssembly.DefineDynamicModule (moduleName, moduleName, true); 74 | } 75 | 76 | public CppLibrary (string name) 77 | : this (name, InlineMethods.NotPresent) 78 | { 79 | } 80 | 81 | public CppLibrary (string name, InlineMethods inlinePolicy) 82 | : this (name, ItaniumAbi.Instance, inlinePolicy) 83 | { 84 | //FIXME: Ideally we would auto-detect ABI here. 85 | } 86 | 87 | public CppLibrary (string name, CppAbi abi, InlineMethods inlinePolicy) 88 | { 89 | if (name == null) 90 | throw new ArgumentNullException ("Name cannot be NULL."); 91 | if (abi == null) 92 | throw new ArgumentNullException ("Abi cannot be NULL."); 93 | 94 | this.name = name; 95 | this.Abi = abi; 96 | this.InlineMethodPolicy = inlinePolicy; 97 | } 98 | 99 | // Mainly for debugging at this point 100 | public static void SaveInteropAssembly () 101 | { 102 | interopAssembly.Save ("CppLibraryImplAssembly.dll"); 103 | } 104 | 105 | // For working with a class that you are not instantiating 106 | // from managed code and where access to fields is not necessary 107 | public Iface GetClass (string className) 108 | where Iface : ICppClass 109 | { 110 | var typeInfo = Abi.MakeTypeInfo (this, className, typeof (Iface), null, null); 111 | return (Iface)Abi.ImplementClass (typeInfo); 112 | } 113 | 114 | // For instantiating or working with a class that may have fields 115 | // but where overriding virtual methods in managed code is not necessary 116 | public Iface GetClass (string className) 117 | where Iface : ICppClassInstantiatable 118 | where NativeLayout : struct 119 | { 120 | var typeInfo = Abi.MakeTypeInfo (this, className, typeof (Iface), typeof (NativeLayout), null); 121 | return (Iface)Abi.ImplementClass (typeInfo); 122 | } 123 | 124 | /* The most powerful override. Allows the following from managed code: 125 | * + Instantiation 126 | * + Field access 127 | * + Virtual method overriding 128 | */ 129 | public Iface GetClass (string className) 130 | where Iface : ICppClassOverridable 131 | where NativeLayout : struct 132 | where Managed : ICppObject 133 | { 134 | var typeInfo = Abi.MakeTypeInfo (this, className, typeof (Iface), typeof (NativeLayout), typeof (Managed)); 135 | return (Iface)Abi.ImplementClass (typeInfo); 136 | } 137 | 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/Mono.Cxxi/CppModifiers.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Mono.Cxxi.CppModifiers.cs: Abstracts a C++ type modifiers 3 | // 4 | // Author: 5 | // Alexander Corrado (alexander.corrado@gmail.com) 6 | // Andreia Gaita (shana@spoiledcat.net) 7 | // 8 | // Copyright (C) 2010-2011 Alexander Corrado 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining 11 | // a copy of this software and associated documentation files (the 12 | // "Software"), to deal in the Software without restriction, including 13 | // without limitation the rights to use, copy, modify, merge, publish, 14 | // distribute, sublicense, and/or sell copies of the Software, and to 15 | // permit persons to whom the Software is furnished to do so, subject to 16 | // the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be 19 | // included in all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 25 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 26 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 27 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | 29 | using System; 30 | using System.Linq; 31 | using System.Collections.Generic; 32 | using System.Text.RegularExpressions; 33 | 34 | using Mono.Cxxi.Util; 35 | 36 | namespace Mono.Cxxi { 37 | 38 | public abstract class CppModifiers { 39 | #pragma warning disable 0414 40 | static int tmp; 41 | #pragma warning restore 42 | // This can be added to at runtime to support other modifiers 43 | // The list should be prioritized, in that the first items should be modifiers that can potentially contain other modifiers 44 | public static readonly Dictionary>> Tokenize = new Dictionary>> () { 45 | { "\\<(.*)\\>", (m,l) => l.AddFirst (m.Groups [1].Success && m.Groups [1].Value.Trim () != ""? new TemplateModifier (m.Groups [1].Value) : CppModifiers.Template) }, 46 | { "\\[([^\\]]*)\\]", (m,l) => l.Add (m.Groups [1].Success && m.Groups [1].Value.Trim () != "" && int.TryParse (m.Groups [1].Value, out tmp) ? new ArrayModifier (int.Parse (m.Groups [1].Value)) : CppModifiers.Array) }, 47 | { "\\bconst\\b", (m,l) => l.Add (CppModifiers.Const) }, 48 | { "\\*", (m,l) => l.Add (CppModifiers.Pointer) }, 49 | { "\\&", (m,l) => l.Add (CppModifiers.Reference) }, 50 | { "\\bvolatile\\b", (m,l) => l.Add (CppModifiers.Volatile) }, 51 | { "\\bunsigned\\b", (m,l) => l.Add (CppModifiers.Unsigned) }, 52 | { "\\bsigned\\b", (m,l) => l.Add (CppModifiers.Signed) }, 53 | { "\\bshort\\b", (m,l) => l.Add (CppModifiers.Short) }, 54 | { "\\blong\\b", (m,l) => l.Add (CppModifiers.Long) } 55 | }; 56 | 57 | private struct Token { 58 | public Action> action; 59 | public Match match; 60 | } 61 | private static IEnumerable Tokenizer (string input) { 62 | 63 | foreach (var token in Tokenize) { 64 | Match match; 65 | 66 | while ((match = Regex.Match (input, token.Key)) != null && match.Success) { 67 | yield return new Token { match = match, action = token.Value }; 68 | input = input.Remove (match.Index, match.Length); 69 | } 70 | } 71 | 72 | } 73 | 74 | public static List Parse (string input) 75 | { 76 | List cpm = new List (); 77 | var tokenizer = Tokenizer (input); 78 | 79 | foreach (var token in tokenizer.OrderBy (t => t.match.Index)) 80 | token.action (token.match, cpm); 81 | 82 | return cpm; 83 | } 84 | 85 | // removes any modifiers from the passed input 86 | public static string Remove (string input) 87 | { 88 | foreach (var token in Tokenize) 89 | input = Regex.Replace (input, token.Key, ""); 90 | 91 | return input; 92 | } 93 | 94 | // normalizes the order of order-agnostic modifiers 95 | public static IEnumerable NormalizeOrder (IEnumerable modifiers) 96 | { 97 | var parts = modifiers.Transform ( 98 | For.AllInputsIn (CppModifiers.Unsigned, CppModifiers.Long).InAnyOrder ().Emit (new CppModifiers [] { CppModifiers.Unsigned, CppModifiers.Long }), 99 | For.AllInputsIn (CppModifiers.Signed, CppModifiers.Long).InAnyOrder ().Emit (new CppModifiers [] { CppModifiers.Signed, CppModifiers.Long }), 100 | For.AllInputsIn (CppModifiers.Unsigned, CppModifiers.Short).InAnyOrder ().Emit (new CppModifiers [] { CppModifiers.Unsigned, CppModifiers.Short }), 101 | For.AllInputsIn (CppModifiers.Signed, CppModifiers.Short).InAnyOrder ().Emit (new CppModifiers [] { CppModifiers.Signed, CppModifiers.Short }), 102 | 103 | For.UnmatchedInput ().Emit (cppmod => new CppModifiers [] { cppmod }) 104 | ); 105 | 106 | foreach (var array in parts) 107 | foreach (var item in array) 108 | yield return item; 109 | } 110 | 111 | public override bool Equals (object obj) 112 | { 113 | return this == obj as CppModifiers; 114 | } 115 | public override int GetHashCode () 116 | { 117 | return GetType ().GetHashCode (); 118 | } 119 | 120 | public static bool operator == (CppModifiers a, CppModifiers b) 121 | { 122 | if ((object)a == (object)b) 123 | return true; 124 | 125 | if ((object)a == null || (object)b == null) 126 | return false; 127 | 128 | return a.GetHashCode () == b.GetHashCode (); 129 | } 130 | public static bool operator != (CppModifiers a, CppModifiers b) 131 | { 132 | return !(a == b); 133 | } 134 | 135 | public static readonly CppModifiers Const = new ConstModifier (); 136 | public static readonly CppModifiers Pointer = new PointerModifier (); 137 | public static readonly CppModifiers Array = new ArrayModifier (); 138 | public static readonly CppModifiers Reference = new ReferenceModifier (); 139 | public static readonly CppModifiers Volatile = new VolatileModifier (); 140 | public static readonly CppModifiers Signed = new SignedModifier (); 141 | public static readonly CppModifiers Unsigned = new UnsignedModifier (); 142 | public static readonly CppModifiers Short = new ShortModifier (); 143 | public static readonly CppModifiers Long = new LongModifier (); 144 | public static readonly CppModifiers Template = new TemplateModifier (); 145 | 146 | // Add list of modifiers here: 147 | public class ConstModifier : CppModifiers { public override string ToString () { return "const"; } } 148 | public class PointerModifier : CppModifiers { public override string ToString () { return "*"; } } 149 | public class ReferenceModifier : CppModifiers { public override string ToString () { return "&"; } } 150 | public class VolatileModifier : CppModifiers { public override string ToString () { return "volatile"; } } 151 | public class SignedModifier : CppModifiers { public override string ToString () { return "signed"; } } 152 | public class UnsignedModifier : CppModifiers { public override string ToString () { return "unsigned"; } } 153 | public class ShortModifier : CppModifiers { public override string ToString () { return "short"; } } 154 | public class LongModifier : CppModifiers { public override string ToString () { return "long"; } } 155 | 156 | public class ArrayModifier : CppModifiers { 157 | public int? Size { get; set; } 158 | 159 | public ArrayModifier () 160 | { 161 | } 162 | 163 | public ArrayModifier (int size) { 164 | Size = size; 165 | } 166 | 167 | public override string ToString () 168 | { 169 | return string.Format ("[{0}]", Size.HasValue? Size.ToString () : ""); 170 | } 171 | } 172 | 173 | public class TemplateModifier : CppModifiers { 174 | public CppType [] Types { get; set; } 175 | 176 | public TemplateModifier () 177 | { 178 | } 179 | 180 | public TemplateModifier (string types) 181 | { 182 | Types = Regex.Split (types, "(?]*),").Select (p => new CppType (p)).ToArray (); 183 | } 184 | 185 | public TemplateModifier (CppType [] types) 186 | { 187 | Types = types; 188 | } 189 | 190 | public override string ToString () 191 | { 192 | return string.Format ("<{0}>", Types == null? "" : string.Join (", ", Types.Select (t => t.ToString ()).ToArray ())); 193 | } 194 | } 195 | } 196 | } 197 | 198 | -------------------------------------------------------------------------------- /src/Mono.Cxxi/Interfaces.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Mono.Cxxi.Interfaces.cs 3 | // 4 | // Author: 5 | // Alexander Corrado (alexander.corrado@gmail.com) 6 | // Andreia Gaita (shana@spoiledcat.net) 7 | // 8 | // Copyright (C) 2010-2011 Alexander Corrado 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining 11 | // a copy of this software and associated documentation files (the 12 | // "Software"), to deal in the Software without restriction, including 13 | // without limitation the rights to use, copy, modify, merge, publish, 14 | // distribute, sublicense, and/or sell copies of the Software, and to 15 | // permit persons to whom the Software is furnished to do so, subject to 16 | // the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be 19 | // included in all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 25 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 26 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 27 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | 29 | using System; 30 | using Mono.Cxxi.Abi; 31 | 32 | namespace Mono.Cxxi { 33 | 34 | // The contract for ICppObject requires implementations to have the following constructors: 35 | // + A public constructor that takes CppInstancePtr (native constructor) 36 | // + A public constructor that takes CppTypeInfo, and as its sole operation, 37 | // calls AddBase on that passed CppTypeInfo, passing its own typeinfo (subclass constructor) 38 | // NOTE: It is important that the subclass constructor have no side effects. 39 | // All constructors for wrappers of native subclasses must call the subclass constructor for the 40 | // wrappers of their base class(es). 41 | public interface ICppObject : IDisposable { 42 | CppInstancePtr Native { get; } 43 | } 44 | 45 | public interface ICppClass { 46 | CppTypeInfo TypeInfo { get; } 47 | } 48 | 49 | // This should go without saying, but the C++ class must have a constructor 50 | // if it is to be instantiatable. 51 | public interface ICppClassInstantiatable : ICppClass { 52 | CppInstancePtr Alloc (); 53 | } 54 | 55 | // It is recommended that managed wrappers implement ICppObject, but 56 | // I'm not making it required so that any arbitrary object can be exposed to 57 | // C++ via CppInstancePtr.ForManagedObject. 58 | public interface ICppClassOverridable : ICppClassInstantiatable 59 | /* where TManaged : ICppObject */ 60 | { 61 | CppInstancePtr Alloc (TManaged managed); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/Mono.Cxxi/Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | EXTRA_DIST = m4/expansions.m4 3 | 4 | if ENABLE_DEBUG 5 | ASSEMBLY_COMPILER_COMMAND = $(GMCS) 6 | ASSEMBLY_COMPILER_FLAGS = -noconfig -codepage:utf8 -warn:4 -optimize- -debug "-define:DEBUG" 7 | BUILD_DIR = $(top_srcdir)/bin/Debug 8 | 9 | ASSEMBLY = $(BUILD_DIR)/Mono.Cxxi.dll 10 | ASSEMBLY_MDB = $(ASSEMBLY).mdb 11 | 12 | MONO_CXXI_DLL_MDB=$(BUILD_DIR)/Mono.Cxxi.dll.mdb 13 | 14 | endif 15 | 16 | if ENABLE_RELEASE 17 | ASSEMBLY_COMPILER_COMMAND = $(GMCS) 18 | ASSEMBLY_COMPILER_FLAGS = -noconfig -codepage:utf8 -warn:4 -optimize+ 19 | BUILD_DIR = $(top_srcdir)/bin/Release 20 | 21 | ASSEMBLY = $(BUILD_DIR)/Mono.Cxxi.dll 22 | ASSEMBLY_MDB = 23 | 24 | MONO_VISUALC_INTEROP_DLL_MDB= 25 | 26 | endif 27 | 28 | COMPILE_TARGET = library 29 | PROJECT_REFERENCES = 30 | 31 | AL=al2 32 | SATELLITE_ASSEMBLY_NAME=$(notdir $(basename $(ASSEMBLY))).resources.dll 33 | 34 | PROGRAMFILES = \ 35 | $(MONO_CXXI_DLL_MDB) 36 | 37 | LINUX_PKGCONFIG = \ 38 | $(MONO_CXXI_PC) 39 | 40 | 41 | RESGEN=resgen2 42 | 43 | all: $(ASSEMBLY) $(PROGRAMFILES) $(LINUX_PKGCONFIG) 44 | 45 | FILES = \ 46 | Abi/CppAbi.cs \ 47 | Abi/EmitInfo.cs \ 48 | Abi/Impl/ItaniumAbi.cs \ 49 | Abi/Impl/ItaniumTypeInfo.cs \ 50 | Abi/Impl/MsvcAbi.cs \ 51 | Abi/MethodType.cs \ 52 | Abi/SymbolResolver.cs \ 53 | Abi/VTable.cs \ 54 | AssemblyInfo.cs \ 55 | Attributes.cs \ 56 | CppField.cs \ 57 | CppInstancePtr.cs \ 58 | CppLibrary.cs \ 59 | CppModifiers.cs \ 60 | CppType.cs \ 61 | CppTypeInfo.cs \ 62 | Interfaces.cs \ 63 | Util/DelegateTypeCache.cs \ 64 | Util/IEnumerableTransform.cs \ 65 | Util/LazyGeneratedList.cs \ 66 | Util/MethodSignature.cs \ 67 | Util/ReflectionHelper.cs 68 | 69 | DATA_FILES = 70 | 71 | RESOURCES = 72 | 73 | EXTRAS = \ 74 | Abi \ 75 | Abi/Impl \ 76 | Util \ 77 | mono.cxxi.pc.in 78 | 79 | REFERENCES = \ 80 | System \ 81 | System.Core 82 | 83 | DLL_REFERENCES = 84 | 85 | CLEANFILES = $(PROGRAMFILES) $(LINUX_PKGCONFIG) 86 | 87 | include $(top_srcdir)/Makefile.include 88 | 89 | MONO_CXXI_PC = $(BUILD_DIR)/mono.cxxi.pc 90 | 91 | $(eval $(call emit-deploy-wrapper,MONO_CXXI_PC,mono.cxxi.pc)) 92 | 93 | 94 | $(eval $(call emit_resgen_targets)) 95 | $(build_xamlg_list): %.xaml.g.cs: %.xaml 96 | xamlg '$<' 97 | 98 | $(ASSEMBLY_MDB): $(ASSEMBLY) 99 | 100 | $(ASSEMBLY): $(build_sources) $(build_resources) $(build_datafiles) $(DLL_REFERENCES) $(PROJECT_REFERENCES) $(build_xamlg_list) $(build_satellite_assembly_list) 101 | mkdir -p $(shell dirname $(ASSEMBLY)) 102 | $(ASSEMBLY_COMPILER_COMMAND) $(ASSEMBLY_COMPILER_FLAGS) -out:$(ASSEMBLY) -target:$(COMPILE_TARGET) $(build_sources_embed) $(build_resources_embed) $(build_references_ref) 103 | -------------------------------------------------------------------------------- /src/Mono.Cxxi/Mono.Cxxi.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.50727 7 | {4A864586-93C5-4DC1-8A80-F094A88506D7} 8 | Library 9 | 2.0 10 | Mono.Cxxi 11 | v3.5 12 | 13 | 14 | 15 | 16 | 2.0 17 | http://localhost/Mono.VisualC.Interop/ 18 | true 19 | Web 20 | true 21 | Foreground 22 | 7 23 | Days 24 | false 25 | false 26 | true 27 | 0 28 | 1.0.0.%2a 29 | true 30 | false 31 | true 32 | 33 | 34 | true 35 | full 36 | false 37 | ..\..\bin\Debug 38 | DEBUG 39 | prompt 40 | 4 41 | false 42 | Mono.Cxxi 43 | AllRules.ruleset 44 | 45 | 46 | none 47 | false 48 | bin\Release 49 | prompt 50 | 4 51 | false 52 | CPPInterop 53 | AllRules.ruleset 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | False 87 | .NET Framework 3.5 SP1 Client Profile 88 | false 89 | 90 | 91 | False 92 | .NET Framework 3.5 SP1 93 | true 94 | 95 | 96 | False 97 | Windows Installer 3.1 98 | true 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /src/Mono.Cxxi/Util/DelegateTypeCache.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Mono.Cxxi.Util.DelegateTypeCache.cs: Automatic delegate type creation and caching 3 | // 4 | // Author: 5 | // Alexander Corrado (alexander.corrado@gmail.com) 6 | // Andreia Gaita (shana@spoiledcat.net) 7 | // 8 | // Copyright (C) 2010-2011 Alexander Corrado 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining 11 | // a copy of this software and associated documentation files (the 12 | // "Software"), to deal in the Software without restriction, including 13 | // without limitation the rights to use, copy, modify, merge, publish, 14 | // distribute, sublicense, and/or sell copies of the Software, and to 15 | // permit persons to whom the Software is furnished to do so, subject to 16 | // the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be 19 | // included in all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 25 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 26 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 27 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | 29 | using System; 30 | using System.Linq; 31 | using System.Reflection; 32 | using System.Reflection.Emit; 33 | using System.Runtime.InteropServices; 34 | using System.Collections.Generic; 35 | 36 | namespace Mono.Cxxi.Util { 37 | 38 | public static class DelegateTypeCache { 39 | 40 | private static Dictionary type_cache; 41 | 42 | public static Type GetDelegateType (MethodInfo signature, CallingConvention? callingConvention) 43 | { 44 | return GetDelegateType (ReflectionHelper.GetMethodParameterTypes (signature), signature.ReturnType, callingConvention); 45 | } 46 | public static Type GetDelegateType (IEnumerable parameterTypes, Type returnType, CallingConvention? callingConvention) 47 | { 48 | return GetDelegateType (new BasicSignature { ParameterTypes = parameterTypes.ToList (), ReturnType = returnType, CallingConvention = callingConvention }); 49 | } 50 | public static Type GetDelegateType (BasicSignature signature) 51 | { 52 | Type delegateType; 53 | if (type_cache == null) 54 | type_cache = new Dictionary (); 55 | 56 | if (!type_cache.TryGetValue (signature, out delegateType)) { 57 | delegateType = CreateDelegateType (signature); 58 | type_cache.Add (signature, delegateType); 59 | } 60 | 61 | return delegateType; 62 | } 63 | 64 | private static Type CreateDelegateType (BasicSignature signature) 65 | { 66 | string delTypeName = signature.UniqueName; 67 | 68 | TypeAttributes typeAttr = TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.AnsiClass | TypeAttributes.AutoClass; 69 | TypeBuilder del = CppLibrary.interopModule.DefineType (delTypeName, typeAttr, typeof(MulticastDelegate)); 70 | 71 | if (signature.CallingConvention.HasValue) { 72 | ConstructorInfo ufpa = typeof (UnmanagedFunctionPointerAttribute).GetConstructor (new Type [] { typeof (CallingConvention) }); 73 | CustomAttributeBuilder unmanagedPointer = new CustomAttributeBuilder (ufpa, new object [] { signature.CallingConvention.Value }); 74 | del.SetCustomAttribute (unmanagedPointer); 75 | } 76 | 77 | MethodAttributes ctorAttr = MethodAttributes.RTSpecialName | MethodAttributes.HideBySig | MethodAttributes.Public; 78 | ConstructorBuilder ctor = del.DefineConstructor (ctorAttr, CallingConventions.Standard, new Type[] { typeof(object), typeof(System.IntPtr) }); 79 | ctor.SetImplementationFlags (MethodImplAttributes.Runtime | MethodImplAttributes.Managed); 80 | 81 | Type [] parameterTypes = signature.ParameterTypes.ToArray (); 82 | MethodAttributes methodAttr = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual; 83 | 84 | MethodBuilder invokeMethod = del.DefineMethod ("Invoke", methodAttr, signature.ReturnType, parameterTypes); 85 | invokeMethod.SetImplementationFlags (MethodImplAttributes.Runtime | MethodImplAttributes.Managed); 86 | 87 | return del.CreateType (); 88 | } 89 | } 90 | 91 | } 92 | 93 | -------------------------------------------------------------------------------- /src/Mono.Cxxi/Util/LazyGeneratedList.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Mono.Cxxi.Util.LazyGeneratedList.cs: A list whose items are generated and cached on first access 3 | // 4 | // Author: 5 | // Alexander Corrado (alexander.corrado@gmail.com) 6 | // Andreia Gaita (shana@spoiledcat.net) 7 | // 8 | // Copyright (C) 2010-2011 Alexander Corrado 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining 11 | // a copy of this software and associated documentation files (the 12 | // "Software"), to deal in the Software without restriction, including 13 | // without limitation the rights to use, copy, modify, merge, publish, 14 | // distribute, sublicense, and/or sell copies of the Software, and to 15 | // permit persons to whom the Software is furnished to do so, subject to 16 | // the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be 19 | // included in all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 25 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 26 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 27 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | 29 | using System; 30 | using System.Collections; 31 | using System.Collections.Generic; 32 | 33 | namespace Mono.Cxxi.Util { 34 | 35 | public class LazyGeneratedList : IList 36 | where TItem : class 37 | { 38 | private TItem [] cache; 39 | private Func generator; 40 | 41 | private int count; 42 | 43 | public LazyGeneratedList (int count, Func generator) 44 | { 45 | this.cache = new TItem [count]; 46 | this.generator = generator; 47 | this.count = count; 48 | } 49 | 50 | public IEnumerator GetEnumerator () 51 | { 52 | for (int i = 0; i < Count; i++) 53 | yield return this [i]; 54 | } 55 | IEnumerator IEnumerable.GetEnumerator () 56 | { 57 | return this.GetEnumerator (); 58 | } 59 | 60 | public int Count { 61 | get { return count; } 62 | } 63 | 64 | public bool IsReadOnly { 65 | get { return true; } 66 | } 67 | 68 | public TItem this [int i] { 69 | get { 70 | // access to cache [i] will throw the IndexOutOfRange exception for us 71 | return cache [i] == null? (cache [i] = generator (i)) : cache [i]; 72 | } 73 | set { 74 | throw new NotSupportedException ("This IList is read only"); 75 | } 76 | } 77 | 78 | public void Add (int count) 79 | { 80 | this.count += count; 81 | // flush cache 82 | cache = new TItem [this.count]; 83 | } 84 | public void Remove (int count) 85 | { 86 | this.count -= count; 87 | // flush cache 88 | cache = new TItem [this.count]; 89 | } 90 | 91 | // FIXME: Should probably implement these at some point 92 | public bool Contains (TItem item) 93 | { 94 | throw new NotImplementedException (); 95 | } 96 | public void CopyTo (TItem[] array, int arrayIndex) 97 | { 98 | throw new NotImplementedException (); 99 | } 100 | public int IndexOf (TItem item) 101 | { 102 | throw new NotImplementedException (); 103 | } 104 | public void Insert (int index, TItem item) 105 | { 106 | throw new NotImplementedException (); 107 | } 108 | public void RemoveAt (int index) 109 | { 110 | throw new NotImplementedException (); 111 | } 112 | public void Add (TItem item) 113 | { 114 | throw new NotImplementedException (); 115 | } 116 | public void Clear () 117 | { 118 | throw new NotImplementedException (); 119 | } 120 | public bool Remove (TItem item) 121 | { 122 | throw new NotImplementedException (); 123 | } 124 | } 125 | } 126 | 127 | -------------------------------------------------------------------------------- /src/Mono.Cxxi/Util/MethodSignature.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Mono.Cxxi.Util.MethodSignature.cs: Hash-friendly structs to represent arbitrary method and delegate signatures 3 | // 4 | // Author: 5 | // Alexander Corrado (alexander.corrado@gmail.com) 6 | // Andreia Gaita (shana@spoiledcat.net) 7 | // 8 | // Copyright (C) 2010-2011 Alexander Corrado 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining 11 | // a copy of this software and associated documentation files (the 12 | // "Software"), to deal in the Software without restriction, including 13 | // without limitation the rights to use, copy, modify, merge, publish, 14 | // distribute, sublicense, and/or sell copies of the Software, and to 15 | // permit persons to whom the Software is furnished to do so, subject to 16 | // the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be 19 | // included in all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 25 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 26 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 27 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | 29 | using System; 30 | using System.Linq; 31 | using System.Text; 32 | using System.Reflection; 33 | using System.Runtime.InteropServices; 34 | using System.Collections.Generic; 35 | 36 | using Mono.Cxxi.Abi; 37 | 38 | namespace Mono.Cxxi.Util { 39 | 40 | public class BasicSignature { 41 | public CallingConvention? CallingConvention { get; set; } 42 | public List ParameterTypes { get; set; } 43 | public Type ReturnType { get; set; } 44 | 45 | private string uniqueName; 46 | 47 | public string UniqueName { 48 | get { 49 | if (uniqueName != null) 50 | return uniqueName; 51 | 52 | StringBuilder sb = new StringBuilder ("_"); 53 | 54 | if (CallingConvention.HasValue) 55 | sb.Append (Enum.GetName (typeof (CallingConvention), CallingConvention.Value)); 56 | 57 | sb.Append ('_').Append (ReturnType.Name); 58 | 59 | if (ParameterTypes == null) 60 | return uniqueName = sb.ToString (); 61 | 62 | foreach (var param in ParameterTypes) 63 | sb.Append ('_').Append (param.Name); 64 | 65 | return uniqueName = sb.ToString (); 66 | } 67 | } 68 | 69 | public bool IsCompatibleWith (BasicSignature other) 70 | { 71 | return CallingConvention == other.CallingConvention && 72 | ((ParameterTypes == null && other.ParameterTypes == null) || 73 | ParameterTypes.SequenceEqual (other.ParameterTypes)) && 74 | ReturnType.Equals (other.ReturnType); 75 | } 76 | 77 | public override bool Equals (object obj) 78 | { 79 | var other = obj as BasicSignature; 80 | if (other == null) 81 | return false; 82 | 83 | return IsCompatibleWith (other); 84 | } 85 | 86 | public override int GetHashCode () 87 | { 88 | unchecked { 89 | return CallingConvention.GetHashCode () ^ 90 | (ParameterTypes != null? ParameterTypes.SequenceHashCode () : 0) ^ 91 | ReturnType.GetHashCode (); 92 | } 93 | } 94 | } 95 | 96 | public class MethodSignature : BasicSignature { 97 | public static readonly IEqualityComparer EqualityComparer = new MethodSignatureEqualityComparer (); 98 | 99 | public string Name { get; set; } 100 | public MethodType Type { get; set; } 101 | 102 | public new bool Equals (object obj) 103 | { 104 | var other = obj as MethodSignature; 105 | if (other == null) 106 | return false; 107 | 108 | return IsCompatibleWith (other) && 109 | Type == other.Type && 110 | (Name.Equals (other.Name) || Type != MethodType.Native); 111 | } 112 | 113 | 114 | public new int GetHashCode () 115 | { 116 | unchecked { 117 | return base.GetHashCode () ^ 118 | Type.GetHashCode () ^ 119 | (Type == MethodType.Native? Name.GetHashCode () : 0); 120 | } 121 | } 122 | 123 | private class MethodSignatureEqualityComparer : IEqualityComparer { 124 | public bool Equals (MethodSignature x, MethodSignature y) 125 | { 126 | return x.Equals (y); 127 | } 128 | public int GetHashCode (MethodSignature obj) 129 | { 130 | return obj.GetHashCode (); 131 | } 132 | } 133 | 134 | public override string ToString () 135 | { 136 | return string.Format ("[{0} {1} ({2})]", ReturnType.Name, Name, string.Join (", ", ParameterTypes.Select (t => t.Name).ToArray ())); 137 | } 138 | } 139 | 140 | public class PInvokeSignature : MethodSignature { 141 | // The original c# method this signature was generated from 142 | public MethodInfo OrigMethod; 143 | } 144 | } 145 | 146 | -------------------------------------------------------------------------------- /src/Mono.Cxxi/Util/ReflectionHelper.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Mono.Cxxi.Util.ReflectionHelper.cs: Helper methods for common reflection API tasks 3 | // 4 | // Author: 5 | // Alexander Corrado (alexander.corrado@gmail.com) 6 | // Andreia Gaita (shana@spoiledcat.net) 7 | // 8 | // Copyright (C) 2010-2011 Alexander Corrado 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining 11 | // a copy of this software and associated documentation files (the 12 | // "Software"), to deal in the Software without restriction, including 13 | // without limitation the rights to use, copy, modify, merge, publish, 14 | // distribute, sublicense, and/or sell copies of the Software, and to 15 | // permit persons to whom the Software is furnished to do so, subject to 16 | // the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be 19 | // included in all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 25 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 26 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 27 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | 29 | using System; 30 | using System.Linq; 31 | using System.Collections.Generic; 32 | using System.Runtime.InteropServices; 33 | using System.Reflection; 34 | using System.Reflection.Emit; 35 | 36 | namespace Mono.Cxxi.Util { 37 | internal static class ReflectionHelper { 38 | 39 | public static MethodInfo GetMethodInfoForDelegate (Type delType) 40 | { 41 | return delType.GetMethod ("Invoke"); 42 | } 43 | 44 | public static Type[] GetDelegateParameterTypes (Type delType) 45 | { 46 | MethodInfo invoke = GetMethodInfoForDelegate (delType); 47 | if (invoke == null) 48 | return null; 49 | 50 | return GetMethodParameterTypes (invoke); 51 | } 52 | 53 | public static Type[] GetMethodParameterTypes (MethodInfo method) 54 | { 55 | ParameterInfo[] parameters = method.GetParameters (); 56 | Type[] parameterTypes = new Type [parameters.Length]; 57 | 58 | for (int i = 0; i < parameters.Length; i++) 59 | parameterTypes [i] = parameters [i].ParameterType; 60 | 61 | return parameterTypes; 62 | } 63 | 64 | public static void ApplyMethodParameterAttributes (MethodInfo source, MethodBuilder target, bool forPInvoke) 65 | { 66 | ParameterInfo[] parameters = source.GetParameters (); 67 | foreach (var param in parameters) 68 | ApplyAttributes (param, target.DefineParameter, forPInvoke); 69 | } 70 | 71 | public static void ApplyMethodParameterAttributes (MethodInfo source, DynamicMethod target, bool forPInvoke) 72 | { 73 | ParameterInfo[] parameters = source.GetParameters (); 74 | foreach (var param in parameters) 75 | ApplyAttributes (param, target.DefineParameter, forPInvoke); 76 | } 77 | 78 | public static ParameterBuilder ApplyAttributes (ParameterInfo param, Func makePB, bool forPInvoke) 79 | { 80 | ParameterAttributes attr = param.Attributes; 81 | CustomAttributeBuilder marshalAsAttr = null; 82 | 83 | MarshalAsAttribute existingMarshalAs = param.GetCustomAttributes (typeof (MarshalAsAttribute), 84 | false).FirstOrDefault () as MarshalAsAttribute; 85 | 86 | /* if (forPInvoke && 87 | typeof (ICppObject).IsAssignableFrom (param.ParameterType) && 88 | !param.ParameterType.Equals (typeof (CppInstancePtr)) && 89 | existingMarshalAs == null) 90 | { 91 | ConstructorInfo ctor = typeof (MarshalAsAttribute).GetConstructor (new Type[] { typeof (UnmanagedType) }); 92 | object[] args = new object [] { UnmanagedType.CustomMarshaler }; 93 | FieldInfo[] fields = new FieldInfo [] { typeof (MarshalAsAttribute).GetField("MarshalTypeRef") }; 94 | object[] values = new object [] { typeof (CppObjectMarshaler) }; 95 | 96 | marshalAsAttr = new CustomAttributeBuilder (ctor, args, fields, values); 97 | attr = attr | ParameterAttributes.HasFieldMarshal; 98 | } else */ if (forPInvoke && existingMarshalAs != null) { 99 | // FIXME: This still doesn't feel like it's working right.. especially for virtual functions 100 | ConstructorInfo ctor = typeof (MarshalAsAttribute).GetConstructor (new Type[] { typeof (UnmanagedType) }); 101 | object[] args = new object [] { existingMarshalAs.Value }; 102 | 103 | var fields = from field in typeof (MarshalAsAttribute).GetFields () 104 | where field.GetValue (existingMarshalAs) != null 105 | select field; 106 | 107 | var values = from field in fields select field.GetValue (existingMarshalAs); 108 | 109 | marshalAsAttr = new CustomAttributeBuilder (ctor, args, fields.ToArray (), values.ToArray ()); 110 | attr = attr | ParameterAttributes.HasFieldMarshal; 111 | } 112 | 113 | ParameterBuilder pb = makePB (param.Position, attr, param.Name); 114 | if (marshalAsAttr != null) pb.SetCustomAttribute (marshalAsAttr); 115 | return pb; 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/Mono.Cxxi/mono.cxxi.pc.in: -------------------------------------------------------------------------------- 1 | Name: Mono.Cxxi 2 | Description: C++ interoperability for managed code 3 | Version: 0.1 4 | 5 | Requires: 6 | Libs: -r:@expanded_libdir@/@PACKAGE@/Mono.Cxxi.dll 7 | -------------------------------------------------------------------------------- /src/README: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/cxxi/12598d0d77ddd6aa07728e9d7cee7135056793b2/src/README -------------------------------------------------------------------------------- /src/generator/Access.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | public enum Access { 4 | @private, 5 | @protected, 6 | @public 7 | } 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/generator/Class.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Class.cs: Represents a C++ class 3 | // 4 | // Author: 5 | // Alexander Corrado (alexander.corrado@gmail.com) 6 | // Andreia Gaita (shana@spoiledcat.net) 7 | // Zoltan Varga 8 | // 9 | // Copyright (C) 2011 Novell Inc. 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining 12 | // a copy of this software and associated documentation files (the 13 | // "Software"), to deal in the Software without restriction, including 14 | // without limitation the rights to use, copy, modify, merge, publish, 15 | // distribute, sublicense, and/or sell copies of the Software, and to 16 | // permit persons to whom the Software is furnished to do so, subject to 17 | // the following conditions: 18 | // 19 | // The above copyright notice and this permission notice shall be 20 | // included in all copies or substantial portions of the Software. 21 | // 22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 23 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 24 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 25 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 26 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 27 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 28 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | 30 | using System; 31 | using System.Collections.Generic; 32 | 33 | using Mono.Cxxi; 34 | 35 | public class Class : Namespace { 36 | 37 | public Class (Node n) 38 | : base (n) 39 | { 40 | BaseClasses = new List (); 41 | Fields = new List (); 42 | Properties = new List (); 43 | Methods = new List (); 44 | NestedClasses = new List (); 45 | NestedEnums = new List (); 46 | } 47 | 48 | public List BaseClasses { 49 | get; set; 50 | } 51 | 52 | public List NestedClasses { 53 | get; set; 54 | } 55 | 56 | public List NestedEnums { 57 | get; set; 58 | } 59 | 60 | public List Fields { 61 | get; set; 62 | } 63 | 64 | public List Properties { 65 | get; set; 66 | } 67 | 68 | public List Methods { 69 | get; 70 | set; 71 | } 72 | 73 | public CppType MangleType { 74 | get; 75 | set; 76 | } 77 | 78 | public bool Disable { 79 | get; set; 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /src/generator/Enumeration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | public class Enumeration : Namespace { 5 | 6 | public struct Item { 7 | public string Name; 8 | public int Value; 9 | } 10 | 11 | public Enumeration (Node n) 12 | : base (n) 13 | { 14 | this.Items = new List (); 15 | } 16 | 17 | public List Items { 18 | get; set; 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /src/generator/Field.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Field.cs: Represents a field of a C++ class 3 | // 4 | // Author: 5 | // Alexander Corrado (alexander.corrado@gmail.com) 6 | // Andreia Gaita (shana@spoiledcat.net) 7 | // Zoltan Varga 8 | // 9 | // Copyright (C) 2011 Novell Inc. 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining 12 | // a copy of this software and associated documentation files (the 13 | // "Software"), to deal in the Software without restriction, including 14 | // without limitation the rights to use, copy, modify, merge, publish, 15 | // distribute, sublicense, and/or sell copies of the Software, and to 16 | // permit persons to whom the Software is furnished to do so, subject to 17 | // the following conditions: 18 | // 19 | // The above copyright notice and this permission notice shall be 20 | // included in all copies or substantial portions of the Software. 21 | // 22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 23 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 24 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 25 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 26 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 27 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 28 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | 30 | using System; 31 | using Mono.Cxxi; 32 | 33 | public class Field { 34 | 35 | public Field (string name, CppType type, Access access) { 36 | Name = name; 37 | Type = type; 38 | Access = access; 39 | } 40 | 41 | public string Name { 42 | get; set; 43 | } 44 | 45 | public CppType Type { 46 | get; set; 47 | } 48 | 49 | public Access Access { 50 | get; set; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/generator/Filter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Xml.Linq; 4 | using System.Collections.Generic; 5 | 6 | public enum FilterMode { 7 | Include, 8 | Exclude, 9 | External 10 | } 11 | 12 | public enum ImplementationType { 13 | @class, 14 | @struct 15 | } 16 | 17 | public struct Filter { 18 | 19 | public string TypeName { get; set; } 20 | public FilterMode Mode { get; set; } 21 | public ImplementationType ImplType { get; set; } 22 | 23 | public static Dictionary Load (XDocument doc, out FilterMode @default) 24 | { 25 | string value; 26 | @default = (value = (string)doc.Root.Attribute ("default")) != null ? (FilterMode)Enum.Parse (typeof (FilterMode), value) : FilterMode.Include; 27 | 28 | var rules = from rule in doc.Root.Elements () 29 | let mode = (FilterMode)Enum.Parse (typeof (FilterMode), rule.Name.LocalName) 30 | let impl = (value = (string)rule.Attribute ("implementation")) != null ? (ImplementationType)Enum.Parse (typeof (ImplementationType), value) : ImplementationType.@class 31 | select new Filter { TypeName = rule.Value, Mode = mode, ImplType = impl }; 32 | 33 | 34 | return rules.ToDictionary (r => r.TypeName); 35 | } 36 | } -------------------------------------------------------------------------------- /src/generator/Lib.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using Mono.Cxxi; 5 | 6 | public class Lib { 7 | 8 | public Lib () 9 | { 10 | Namespaces = new List (); 11 | } 12 | 13 | public string BaseName { 14 | get; 15 | set; 16 | } 17 | 18 | public InlineMethods InlinePolicy { 19 | get; 20 | set; 21 | } 22 | 23 | public string BaseNamespace { 24 | get; 25 | set; 26 | } 27 | 28 | public IList Namespaces { 29 | get; 30 | set; 31 | } 32 | } 33 | 34 | -------------------------------------------------------------------------------- /src/generator/Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | EXTRA_DIST = m4/expansions.m4 3 | 4 | if ENABLE_DEBUG 5 | ASSEMBLY_COMPILER_COMMAND = mcs 6 | ASSEMBLY_COMPILER_FLAGS = -noconfig -codepage:utf8 -warn:4 -optimize- -debug "-define:DEBUG" 7 | BUILD_DIR = $(top_srcdir)/bin/Debug 8 | 9 | ASSEMBLY = $(BUILD_DIR)/generator.exe 10 | ASSEMBLY_MDB = $(ASSEMBLY).mdb 11 | 12 | MONO_CXXI_DLL_SOURCE=$(BUILD_DIR)/Mono.Cxxi.dll 13 | MONO_CXXI_DLL=$(BUILD_DIR)/Mono.Cxxi.dll 14 | GENERATOR_EXE_MDB_SOURCE=$(BUILD_DIR)/generator.exe.mdb 15 | GENERATOR_EXE_MDB=$(BUILD_DIR)/generator.exe.mdb 16 | 17 | endif 18 | 19 | if ENABLE_RELEASE 20 | ASSEMBLY_COMPILER_COMMAND = mcs 21 | ASSEMBLY_COMPILER_FLAGS = -noconfig -codepage:utf8 -warn:4 -optimize+ 22 | BUILD_DIR = $(top_srcdir)/bin/Release 23 | 24 | ASSEMBLY = $(BUILD_DIR)/generator.exe 25 | ASSEMBLY_MDB = 26 | 27 | MONO_CXXI_DLL_SOURCE=$(BUILD_DIR)/Mono.Cxxi.dll 28 | MONO_CXXI_DLL=$(BUILD_DIR)/Mono.Cxxi.dll 29 | GENERATOR_EXE_MDB= 30 | 31 | endif 32 | 33 | COMPILE_TARGET = exe 34 | 35 | AL=al2 36 | SATELLITE_ASSEMBLY_NAME=$(notdir $(basename $(ASSEMBLY))).resources.dll 37 | 38 | PROGRAMFILES = \ 39 | $(MONO_CXXI_DLL) \ 40 | $(GENERATOR_EXE_MDB) 41 | 42 | BINARIES = \ 43 | $(GENERATOR) 44 | 45 | 46 | RESGEN=resgen2 47 | 48 | all: $(ASSEMBLY) $(PROGRAMFILES) $(BINARIES) 49 | 50 | FILES = \ 51 | Access.cs \ 52 | Class.cs \ 53 | Enumeration.cs \ 54 | Field.cs \ 55 | Filter.cs \ 56 | Generator.cs \ 57 | Lib.cs \ 58 | Method.cs \ 59 | Namespace.cs \ 60 | Node.cs \ 61 | Options.cs \ 62 | Parameter.cs \ 63 | Property.cs \ 64 | Templates/Base.cs \ 65 | Templates/BaseMembers.cs \ 66 | Templates/Context.cs \ 67 | Templates/CSharp/CSharpClass.cs \ 68 | Templates/CSharp/CSharpEnum.cs \ 69 | Templates/CSharp/CSharpLanguage.cs \ 70 | Templates/CSharp/CSharpLibs.cs 71 | 72 | DATA_FILES = 73 | 74 | RESOURCES = 75 | 76 | EXTRAS = \ 77 | generator.in 78 | 79 | REFERENCES = \ 80 | ../../bin/Debug/Mono.Cxxi.dll \ 81 | System \ 82 | System.Core \ 83 | System.Xml \ 84 | System.Xml.Linq 85 | 86 | DLL_REFERENCES = 87 | 88 | CLEANFILES = $(PROGRAMFILES) $(BINARIES) 89 | 90 | include $(top_srcdir)/Makefile.include 91 | 92 | GENERATOR = $(BUILD_DIR)/generator 93 | 94 | $(eval $(call emit-deploy-target,MONO_CXXI_DLL)) 95 | $(eval $(call emit-deploy-wrapper,GENERATOR,generator,x)) 96 | 97 | 98 | $(eval $(call emit_resgen_targets)) 99 | $(build_xamlg_list): %.xaml.g.cs: %.xaml 100 | xamlg '$<' 101 | 102 | $(ASSEMBLY_MDB): $(ASSEMBLY) 103 | 104 | $(ASSEMBLY): $(build_sources) $(build_resources) $(build_datafiles) $(DLL_REFERENCES) $(build_xamlg_list) $(build_satellite_assembly_list) 105 | mkdir -p $(shell dirname $(ASSEMBLY)) 106 | $(ASSEMBLY_COMPILER_COMMAND) $(ASSEMBLY_COMPILER_FLAGS) -out:$(ASSEMBLY) -target:$(COMPILE_TARGET) $(build_sources_embed) $(build_resources_embed) $(build_references_ref) 107 | -------------------------------------------------------------------------------- /src/generator/Method.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Method.cs: Represents a C++ method 3 | // 4 | // Author: 5 | // Alexander Corrado (alexander.corrado@gmail.com) 6 | // Andreia Gaita (shana@spoiledcat.net) 7 | // Zoltan Varga 8 | // 9 | // Copyright (C) 2011 Novell Inc. 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining 12 | // a copy of this software and associated documentation files (the 13 | // "Software"), to deal in the Software without restriction, including 14 | // without limitation the rights to use, copy, modify, merge, publish, 15 | // distribute, sublicense, and/or sell copies of the Software, and to 16 | // permit persons to whom the Software is furnished to do so, subject to 17 | // the following conditions: 18 | // 19 | // The above copyright notice and this permission notice shall be 20 | // included in all copies or substantial portions of the Software. 21 | // 22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 23 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 24 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 25 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 26 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 27 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 28 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | 30 | using System; 31 | using System.Collections.Generic; 32 | 33 | using Mono.Cxxi; 34 | 35 | public class Method { 36 | 37 | public Method (Node node) { 38 | Node = node; 39 | Parameters = new List (); 40 | GenWrapperMethod = true; 41 | } 42 | 43 | public Node Node { 44 | get; set; 45 | } 46 | 47 | public Access Access { 48 | get; set; 49 | } 50 | 51 | public string Name { 52 | get; set; 53 | } 54 | 55 | public bool IsVirtual { 56 | get; set; 57 | } 58 | 59 | public bool IsStatic { 60 | get; set; 61 | } 62 | 63 | public bool IsConst { 64 | get; set; 65 | } 66 | 67 | public bool IsInline { 68 | get; set; 69 | } 70 | 71 | public bool IsArtificial { 72 | get; set; 73 | } 74 | 75 | public bool IsConstructor { 76 | get; set; 77 | } 78 | 79 | public bool IsDestructor { 80 | get; set; 81 | } 82 | 83 | public bool IsCopyCtor { 84 | get; set; 85 | } 86 | 87 | public bool GenWrapperMethod { 88 | get; set; 89 | } 90 | 91 | public CppType ReturnType { 92 | get; set; 93 | } 94 | 95 | public List Parameters { 96 | get; set; 97 | } 98 | 99 | // The C# method name 100 | public string FormattedName { 101 | get { 102 | return "" + Char.ToUpper (Name [0]) + Name.Substring (1); 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/generator/Namespace.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | public class Namespace { 5 | 6 | public Namespace (string name) 7 | { 8 | this.Name = name; 9 | } 10 | 11 | public Namespace (Node node) 12 | : this (node.Name) 13 | { 14 | this.Node = node; 15 | } 16 | 17 | public Node Node { 18 | get; set; 19 | } 20 | 21 | // Back ref to enclosing namespace (may be null) 22 | public Namespace ParentNamespace { 23 | get; set; 24 | } 25 | 26 | public string Name { 27 | get; set; 28 | } 29 | 30 | private string [] fullyQualifiedName; 31 | public string [] FullyQualifiedName { 32 | get { 33 | if (fullyQualifiedName == null) { 34 | 35 | if (ParentNamespace == null) { 36 | fullyQualifiedName = new string[] { Name }; 37 | } else { 38 | var parentFqn = ParentNamespace.FullyQualifiedName; 39 | fullyQualifiedName = new string[parentFqn.Length + 1]; 40 | Array.Copy (parentFqn, fullyQualifiedName, parentFqn.Length); 41 | fullyQualifiedName [parentFqn.Length] = Name; 42 | } 43 | } 44 | return fullyQualifiedName; 45 | } 46 | } 47 | 48 | } 49 | 50 | -------------------------------------------------------------------------------- /src/generator/Node.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Node.cs: 3 | // 4 | // 5 | // Author: 6 | // Alexander Corrado (alexander.corrado@gmail.com) 7 | // Andreia Gaita (shana@spoiledcat.net) 8 | // Zoltan Varga 9 | // 10 | // Copyright (C) 2011 Novell Inc. 11 | // 12 | // Permission is hereby granted, free of charge, to any person obtaining 13 | // a copy of this software and associated documentation files (the 14 | // "Software"), to deal in the Software without restriction, including 15 | // without limitation the rights to use, copy, modify, merge, publish, 16 | // distribute, sublicense, and/or sell copies of the Software, and to 17 | // permit persons to whom the Software is furnished to do so, subject to 18 | // the following conditions: 19 | // 20 | // The above copyright notice and this permission notice shall be 21 | // included in all copies or substantial portions of the Software. 22 | // 23 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 27 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 28 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 29 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | 31 | using System; 32 | using System.Linq; 33 | using System.Collections.Generic; 34 | 35 | 36 | // 37 | // This class represents an XML node read from the output of gccxml 38 | // 39 | public class Node { 40 | 41 | // The XML element type 42 | public string Type { 43 | get; set; 44 | } 45 | 46 | // The value of the 'id' attribute 47 | public string Id { 48 | get; set; 49 | } 50 | 51 | // The value of the 'name' attribute or null 52 | public string Name { 53 | get; set; 54 | } 55 | 56 | // Attributes 57 | public Dictionary Attributes { 58 | get; set; 59 | } 60 | 61 | // The children nodes of this node 62 | public List Children { 63 | get; set; 64 | } 65 | 66 | public string this [string key] { 67 | get { 68 | return Attributes [key]; 69 | } 70 | } 71 | 72 | // Maps ids to nodes 73 | public static Dictionary IdToNode = new Dictionary (); 74 | 75 | // For an attribute which contains an id, return the corresponding Node 76 | public Node NodeForAttr (string attr) { 77 | return IdToNode [Attributes [attr]]; 78 | } 79 | 80 | public bool IsTrue (string key) { 81 | return Attributes.ContainsKey (key) && Attributes[key] == "1"; 82 | } 83 | 84 | public bool HasValue (string key) { 85 | return Attributes.ContainsKey (key) && Attributes[key] != ""; 86 | } 87 | 88 | public bool CheckValue (string key, string name) { 89 | return Attributes.ContainsKey (key) && Attributes[key].Trim () == name.Trim (); 90 | } 91 | 92 | public bool CheckValueList (string key, string name) { 93 | return Attributes.ContainsKey (key) && Attributes[key].Split (' ').Contains (name.Trim ()); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/generator/Parameter.cs: -------------------------------------------------------------------------------- 1 | // Author: 2 | // Zoltan Varga 3 | // 4 | // Copyright (C) 2011 Novell Inc. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining 7 | // a copy of this software and associated documentation files (the 8 | // "Software"), to deal in the Software without restriction, including 9 | // without limitation the rights to use, copy, modify, merge, publish, 10 | // distribute, sublicense, and/or sell copies of the Software, and to 11 | // permit persons to whom the Software is furnished to do so, subject to 12 | // the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be 15 | // included in all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | using System; 26 | using Mono.Cxxi; 27 | 28 | public class Parameter 29 | { 30 | public Parameter (String name, CppType type) { 31 | Name = name; 32 | Type = type; 33 | } 34 | 35 | public string Name { 36 | get; set; 37 | } 38 | 39 | public CppType Type { 40 | get; set; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/generator/Property.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Property.cs: Represents a C++ property 3 | // 4 | // Author: 5 | // Zoltan Varga 6 | // 7 | // Copyright (C) 2011 Novell Inc. 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining 10 | // a copy of this software and associated documentation files (the 11 | // "Software"), to deal in the Software without restriction, including 12 | // without limitation the rights to use, copy, modify, merge, publish, 13 | // distribute, sublicense, and/or sell copies of the Software, and to 14 | // permit persons to whom the Software is furnished to do so, subject to 15 | // the following conditions: 16 | // 17 | // The above copyright notice and this permission notice shall be 18 | // included in all copies or substantial portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 24 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 25 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 26 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | 28 | using System; 29 | using System.Collections.Generic; 30 | 31 | using Mono.Cxxi; 32 | 33 | public class Property { 34 | 35 | public Property (string name, CppType type) { 36 | Name = name; 37 | Type = type; 38 | } 39 | 40 | public string Name { 41 | get; set; 42 | } 43 | 44 | public CppType Type { 45 | get; set; 46 | } 47 | 48 | public Method GetMethod { 49 | get; set; 50 | } 51 | 52 | public Method SetMethod { 53 | get; set; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/generator/Templates/Base.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Mono Runtime Version: 4.0.30319.1 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | // ------------------------------------------------------------------------------ 10 | 11 | namespace Templates { 12 | using System; 13 | 14 | 15 | public partial class Base : BaseBase { 16 | 17 | public virtual string TransformText() { 18 | this.GenerationEnvironment = null; 19 | 20 | #line 2 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/Base.tt" 21 | /* This is a dummy template that language-specific templates may inherit from */ 22 | 23 | #line default 24 | #line hidden 25 | return this.GenerationEnvironment.ToString(); 26 | } 27 | 28 | protected virtual void Initialize() { 29 | } 30 | } 31 | 32 | public class BaseBase { 33 | 34 | private global::System.Text.StringBuilder builder; 35 | 36 | private global::System.Collections.Generic.IDictionary session; 37 | 38 | private global::System.CodeDom.Compiler.CompilerErrorCollection errors; 39 | 40 | private string currentIndent = string.Empty; 41 | 42 | private global::System.Collections.Generic.Stack indents; 43 | 44 | private ToStringInstanceHelper _toStringHelper = new ToStringInstanceHelper(); 45 | 46 | public virtual global::System.Collections.Generic.IDictionary Session { 47 | get { 48 | return this.session; 49 | } 50 | set { 51 | this.session = value; 52 | } 53 | } 54 | 55 | public global::System.Text.StringBuilder GenerationEnvironment { 56 | get { 57 | if ((this.builder == null)) { 58 | this.builder = new global::System.Text.StringBuilder(); 59 | } 60 | return this.builder; 61 | } 62 | set { 63 | this.builder = value; 64 | } 65 | } 66 | 67 | protected global::System.CodeDom.Compiler.CompilerErrorCollection Errors { 68 | get { 69 | if ((this.errors == null)) { 70 | this.errors = new global::System.CodeDom.Compiler.CompilerErrorCollection(); 71 | } 72 | return this.errors; 73 | } 74 | } 75 | 76 | public string CurrentIndent { 77 | get { 78 | return this.currentIndent; 79 | } 80 | } 81 | 82 | private global::System.Collections.Generic.Stack Indents { 83 | get { 84 | if ((this.indents == null)) { 85 | this.indents = new global::System.Collections.Generic.Stack(); 86 | } 87 | return this.indents; 88 | } 89 | } 90 | 91 | public ToStringInstanceHelper ToStringHelper { 92 | get { 93 | return this._toStringHelper; 94 | } 95 | } 96 | 97 | public void Error(string message) { 98 | this.Errors.Add(new global::System.CodeDom.Compiler.CompilerError(null, -1, -1, null, message)); 99 | } 100 | 101 | public void Warning(string message) { 102 | global::System.CodeDom.Compiler.CompilerError val = new global::System.CodeDom.Compiler.CompilerError(null, -1, -1, null, message); 103 | val.IsWarning = true; 104 | this.Errors.Add(val); 105 | } 106 | 107 | public string PopIndent() { 108 | if ((this.Indents.Count == 0)) { 109 | return string.Empty; 110 | } 111 | int lastPos = (this.currentIndent.Length - this.Indents.Pop()); 112 | string last = this.currentIndent.Substring(lastPos); 113 | this.currentIndent = this.currentIndent.Substring(0, lastPos); 114 | return last; 115 | } 116 | 117 | public void PushIndent(string indent) { 118 | this.Indents.Push(indent.Length); 119 | this.currentIndent = (this.currentIndent + indent); 120 | } 121 | 122 | public void ClearIndent() { 123 | this.currentIndent = string.Empty; 124 | this.Indents.Clear(); 125 | } 126 | 127 | public void Write(string textToAppend) { 128 | this.GenerationEnvironment.Append(textToAppend); 129 | } 130 | 131 | public void Write(string format, params object[] args) { 132 | this.GenerationEnvironment.AppendFormat(format, args); 133 | } 134 | 135 | public void WriteLine(string textToAppend) { 136 | this.GenerationEnvironment.Append(this.currentIndent); 137 | this.GenerationEnvironment.AppendLine(textToAppend); 138 | } 139 | 140 | public void WriteLine(string format, params object[] args) { 141 | this.GenerationEnvironment.Append(this.currentIndent); 142 | this.GenerationEnvironment.AppendFormat(format, args); 143 | this.GenerationEnvironment.AppendLine(); 144 | } 145 | 146 | public class ToStringInstanceHelper { 147 | 148 | private global::System.IFormatProvider formatProvider = global::System.Globalization.CultureInfo.InvariantCulture; 149 | 150 | public global::System.IFormatProvider FormatProvider { 151 | get { 152 | return this.formatProvider; 153 | } 154 | set { 155 | if ((this.formatProvider == null)) { 156 | throw new global::System.ArgumentNullException("formatProvider"); 157 | } 158 | this.formatProvider = value; 159 | } 160 | } 161 | 162 | public string ToStringWithCulture(object objectToConvert) { 163 | if ((objectToConvert == null)) { 164 | throw new global::System.ArgumentNullException("objectToConvert"); 165 | } 166 | global::System.Type type = objectToConvert.GetType(); 167 | global::System.Type iConvertibleType = typeof(global::System.IConvertible); 168 | if (iConvertibleType.IsAssignableFrom(type)) { 169 | return ((global::System.IConvertible)(objectToConvert)).ToString(this.formatProvider); 170 | } 171 | global::System.Reflection.MethodInfo methInfo = type.GetMethod("ToString", new global::System.Type[] { 172 | iConvertibleType}); 173 | if ((methInfo != null)) { 174 | return ((string)(methInfo.Invoke(objectToConvert, new object[] { 175 | this.formatProvider}))); 176 | } 177 | return objectToConvert.ToString(); 178 | } 179 | } 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /src/generator/Templates/Base.tt: -------------------------------------------------------------------------------- 1 | <#@ template language="C#" #> 2 | <# /* This is a dummy template that language-specific templates may inherit from */ #> 3 | -------------------------------------------------------------------------------- /src/generator/Templates/BaseMembers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Templates { 5 | 6 | public interface ITemplate { 7 | Generator Generator { get; set; } 8 | T Current { get; set; } 9 | bool Nested { get; set; } 10 | string TransformText (); 11 | } 12 | 13 | public partial class LibsBase : Base, ITemplate> { 14 | 15 | public Generator Generator { get; set; } 16 | public ICollection Current { get; set; } 17 | public bool Nested { get; set; } 18 | public ICollection Libs { get { return Current; } set { Current = value; } } 19 | } 20 | 21 | public partial class ClassBase : Base, ITemplate { 22 | 23 | public Generator Generator { get; set; } 24 | public Class Current { get; set; } 25 | public bool Nested { get; set; } 26 | public Class Class { get { return Current; } set { Current = value; } } 27 | } 28 | 29 | public partial class EnumBase : Base, ITemplate { 30 | 31 | public Generator Generator { get; set; } 32 | public Enumeration Current { get; set; } 33 | public bool Nested { get; set; } 34 | public Enumeration Enum { get { return Current; } set { Current = value; } } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/generator/Templates/CSharp/CSharpEnum.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Mono Runtime Version: 4.0.30319.1 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | // ------------------------------------------------------------------------------ 10 | 11 | namespace Templates { 12 | using System.IO; 13 | using System.Linq; 14 | using System.Collections.Generic; 15 | using Mono.Cxxi; 16 | using System; 17 | 18 | 19 | public partial class CSharpEnum : EnumBase { 20 | 21 | public override string TransformText() { 22 | this.GenerationEnvironment = null; 23 | 24 | #line 6 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpEnum.tt" 25 | 26 | var @namespace = Generator.Lib.BaseNamespace + (Enum.ParentNamespace != null? "." + string.Join (".", Enum.ParentNamespace.FullyQualifiedName) : ""); 27 | 28 | if (!Nested) { 29 | 30 | 31 | #line default 32 | #line hidden 33 | 34 | #line 11 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpEnum.tt" 35 | this.Write("\n// -------------------------------------------------------------------------\n// Managed enum for "); 36 | 37 | #line default 38 | #line hidden 39 | 40 | #line 13 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpEnum.tt" 41 | this.Write(this.ToStringHelper.ToStringWithCulture( Enum.Name )); 42 | 43 | #line default 44 | #line hidden 45 | 46 | #line 13 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpEnum.tt" 47 | this.Write("\n// Generated from "); 48 | 49 | #line default 50 | #line hidden 51 | 52 | #line 14 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpEnum.tt" 53 | this.Write(this.ToStringHelper.ToStringWithCulture( Path.GetFileName (Generator.InputFileName) )); 54 | 55 | #line default 56 | #line hidden 57 | 58 | #line 14 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpEnum.tt" 59 | this.Write(" on "); 60 | 61 | #line default 62 | #line hidden 63 | 64 | #line 14 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpEnum.tt" 65 | this.Write(this.ToStringHelper.ToStringWithCulture( DateTime.Now )); 66 | 67 | #line default 68 | #line hidden 69 | 70 | #line 14 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpEnum.tt" 71 | this.Write("\n//\n// This file was auto generated. Do not edit.\n// -------------------------------------------------------------------------\n\nnamespace "); 72 | 73 | #line default 74 | #line hidden 75 | 76 | #line 19 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpEnum.tt" 77 | this.Write(this.ToStringHelper.ToStringWithCulture( @namespace )); 78 | 79 | #line default 80 | #line hidden 81 | 82 | #line 19 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpEnum.tt" 83 | this.Write(" {\n"); 84 | 85 | #line default 86 | #line hidden 87 | 88 | #line 20 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpEnum.tt" 89 | } /* if !Nested */ 90 | 91 | #line default 92 | #line hidden 93 | 94 | #line 21 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpEnum.tt" 95 | this.Write("\tpublic enum "); 96 | 97 | #line default 98 | #line hidden 99 | 100 | #line 21 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpEnum.tt" 101 | this.Write(this.ToStringHelper.ToStringWithCulture( Enum.Name )); 102 | 103 | #line default 104 | #line hidden 105 | 106 | #line 21 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpEnum.tt" 107 | this.Write(" {\n"); 108 | 109 | #line default 110 | #line hidden 111 | 112 | #line 22 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpEnum.tt" 113 | foreach (var item in Enum.Items) { 114 | 115 | #line default 116 | #line hidden 117 | 118 | #line 23 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpEnum.tt" 119 | this.Write("\t\t"); 120 | 121 | #line default 122 | #line hidden 123 | 124 | #line 23 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpEnum.tt" 125 | this.Write(this.ToStringHelper.ToStringWithCulture( item.Name )); 126 | 127 | #line default 128 | #line hidden 129 | 130 | #line 23 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpEnum.tt" 131 | this.Write(" = "); 132 | 133 | #line default 134 | #line hidden 135 | 136 | #line 23 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpEnum.tt" 137 | this.Write(this.ToStringHelper.ToStringWithCulture( item.Value )); 138 | 139 | #line default 140 | #line hidden 141 | 142 | #line 23 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpEnum.tt" 143 | this.Write(",\n"); 144 | 145 | #line default 146 | #line hidden 147 | 148 | #line 24 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpEnum.tt" 149 | } 150 | 151 | #line default 152 | #line hidden 153 | 154 | #line 25 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpEnum.tt" 155 | this.Write("\t}\n"); 156 | 157 | #line default 158 | #line hidden 159 | 160 | #line 26 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpEnum.tt" 161 | if (!Nested) { 162 | 163 | #line default 164 | #line hidden 165 | 166 | #line 27 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpEnum.tt" 167 | this.Write("}\n"); 168 | 169 | #line default 170 | #line hidden 171 | 172 | #line 28 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpEnum.tt" 173 | } 174 | 175 | #line default 176 | #line hidden 177 | return this.GenerationEnvironment.ToString(); 178 | } 179 | 180 | protected override void Initialize() { 181 | base.Initialize(); 182 | } 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /src/generator/Templates/CSharp/CSharpEnum.tt: -------------------------------------------------------------------------------- 1 | <#@ template language="C#" inherits="EnumBase" #> 2 | <#@ import namespace="System.IO" #> 3 | <#@ import namespace="System.Linq" #> 4 | <#@ import namespace="System.Collections.Generic" #> 5 | <#@ import namespace="Mono.Cxxi" #> 6 | <# 7 | var @namespace = Generator.Lib.BaseNamespace + (Enum.ParentNamespace != null? "." + string.Join (".", Enum.ParentNamespace.FullyQualifiedName) : ""); 8 | 9 | if (!Nested) { 10 | #> 11 | 12 | // ------------------------------------------------------------------------- 13 | // Managed enum for <#= Enum.Name #> 14 | // Generated from <#= Path.GetFileName (Generator.InputFileName) #> on <#= DateTime.Now #> 15 | // 16 | // This file was auto generated. Do not edit. 17 | // ------------------------------------------------------------------------- 18 | 19 | namespace <#= @namespace #> { 20 | <# } /* if !Nested */ #> 21 | public enum <#= Enum.Name #> { 22 | <# foreach (var item in Enum.Items) { #> 23 | <#= item.Name #> = <#= item.Value #>, 24 | <# } #> 25 | } 26 | <# if (!Nested) { #> 27 | } 28 | <# } #> -------------------------------------------------------------------------------- /src/generator/Templates/CSharp/CSharpLanguage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | using Mono.Cxxi; 6 | 7 | namespace Templates { 8 | public static class CSharpLanguage { 9 | 10 | // from https://github.com/mono/mono/blob/master/mcs/class/System/Microsoft.CSharp/CSharpCodeGenerator.cs 11 | private static string[] keywords = new string[] { 12 | "abstract","event","new","struct","as","explicit","null","switch","base","extern", 13 | "this","false","operator","throw","break","finally","out","true", 14 | "fixed","override","try","case","params","typeof","catch","for", 15 | "private","foreach","protected","checked","goto","public", 16 | "unchecked","class","if","readonly","unsafe","const","implicit","ref", 17 | "continue","in","return","using","virtual","default", 18 | "interface","sealed","volatile","delegate","internal","do","is", 19 | "sizeof","while","lock","stackalloc","else","static","enum", 20 | "namespace", 21 | "object","bool","byte","float","uint","char","ulong","ushort", 22 | "decimal","int","sbyte","short","double","long","string","void", 23 | "partial", "yield", "where" 24 | }; 25 | 26 | public static string SafeIdentifier (string proposedName) 27 | { 28 | proposedName = new string (((IEnumerable)proposedName).Select (c => char.IsLetterOrDigit (c)? c : '_').ToArray ()); 29 | return keywords.Contains (proposedName)? "@" + proposedName : proposedName; 30 | } 31 | 32 | public static string TypeName (string str, Context context) 33 | { 34 | switch (str) { 35 | case "System.Void": return "void"; 36 | case "System.Boolean": return "bool"; 37 | case "System.Byte": return "byte"; 38 | case "System.SByte": return "sbyte"; 39 | case "System.Char": return "char"; 40 | case "System.Int16": return "short"; 41 | case "System.UInt16": return "ushort"; 42 | case "System.Decimal": return "decimal"; 43 | case "System.Single": return "float"; 44 | case "System.Double": return "double"; 45 | case "System.Int32": return "int"; 46 | case "System.UInt32": return "uint"; 47 | case "System.Int64": return "long"; 48 | case "System.UInt64": return "ulong"; 49 | case "System.Object": return "object"; 50 | case "System.String": return "string"; 51 | } 52 | 53 | if (str.EndsWith ("&")) { 54 | if (context.Is (Context.Parameter)) 55 | return "ref " + TypeName (str.TrimEnd ('&'), context); 56 | if (context.Is (Context.Return)) 57 | return (context.Is (Context.Interface)? "[return: ByRef] " : "") + TypeName (str.TrimEnd ('&'), context); 58 | if (context.Is (Context.Generic)) 59 | return "IntPtr"; 60 | } 61 | 62 | // we are using System by default 63 | var lastDot = str.LastIndexOf ('.'); 64 | if (str.StartsWith ("System") && lastDot == "System".Length) 65 | return str.Substring (lastDot + 1); 66 | 67 | return str; 68 | } 69 | 70 | 71 | } 72 | } 73 | 74 | -------------------------------------------------------------------------------- /src/generator/Templates/CSharp/CSharpLibs.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Mono Runtime Version: 4.0.30319.1 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | // ------------------------------------------------------------------------------ 10 | 11 | namespace Templates { 12 | using System; 13 | 14 | 15 | public partial class CSharpLibs : LibsBase { 16 | 17 | public override string TransformText() { 18 | this.GenerationEnvironment = null; 19 | 20 | #line 2 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpLibs.tt" 21 | this.Write("// -------------------------------------------------------------------------\n// C++ library declarations\n// Generated on "); 22 | 23 | #line default 24 | #line hidden 25 | 26 | #line 4 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpLibs.tt" 27 | this.Write(this.ToStringHelper.ToStringWithCulture( DateTime.Now )); 28 | 29 | #line default 30 | #line hidden 31 | 32 | #line 4 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpLibs.tt" 33 | this.Write("\n//\n// This file was auto generated. Do not edit.\n// -------------------------------------------------------------------------\n\nusing System;\nusing Mono.Cxxi;\n\nnamespace "); 34 | 35 | #line default 36 | #line hidden 37 | 38 | #line 12 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpLibs.tt" 39 | this.Write(this.ToStringHelper.ToStringWithCulture( Generator.Lib.BaseNamespace )); 40 | 41 | #line default 42 | #line hidden 43 | 44 | #line 12 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpLibs.tt" 45 | this.Write(" {\n\n\tpublic static partial class Libs {\n"); 46 | 47 | #line default 48 | #line hidden 49 | 50 | #line 15 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpLibs.tt" 51 | foreach (var lib in Libs) { 52 | 53 | #line default 54 | #line hidden 55 | 56 | #line 16 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpLibs.tt" 57 | this.Write("\t\tpublic static readonly CppLibrary "); 58 | 59 | #line default 60 | #line hidden 61 | 62 | #line 16 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpLibs.tt" 63 | this.Write(this.ToStringHelper.ToStringWithCulture( CSharpLanguage.SafeIdentifier (lib.BaseName) )); 64 | 65 | #line default 66 | #line hidden 67 | 68 | #line 16 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpLibs.tt" 69 | this.Write(" = new CppLibrary (\""); 70 | 71 | #line default 72 | #line hidden 73 | 74 | #line 16 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpLibs.tt" 75 | this.Write(this.ToStringHelper.ToStringWithCulture( lib.BaseName )); 76 | 77 | #line default 78 | #line hidden 79 | 80 | #line 16 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpLibs.tt" 81 | this.Write("\", InlineMethods."); 82 | 83 | #line default 84 | #line hidden 85 | 86 | #line 16 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpLibs.tt" 87 | this.Write(this.ToStringHelper.ToStringWithCulture( lib.InlinePolicy )); 88 | 89 | #line default 90 | #line hidden 91 | 92 | #line 16 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpLibs.tt" 93 | this.Write(");\n"); 94 | 95 | #line default 96 | #line hidden 97 | 98 | #line 17 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpLibs.tt" 99 | } 100 | 101 | #line default 102 | #line hidden 103 | 104 | #line 18 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpLibs.tt" 105 | this.Write("\t}\n}\n"); 106 | 107 | #line default 108 | #line hidden 109 | return this.GenerationEnvironment.ToString(); 110 | } 111 | 112 | protected override void Initialize() { 113 | base.Initialize(); 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/generator/Templates/CSharp/CSharpLibs.tt: -------------------------------------------------------------------------------- 1 | <#@ template language="C#" inherits="LibsBase" #> 2 | // ------------------------------------------------------------------------- 3 | // C++ library declarations 4 | // Generated on <#= DateTime.Now #> 5 | // 6 | // This file was auto generated. Do not edit. 7 | // ------------------------------------------------------------------------- 8 | 9 | using System; 10 | using Mono.Cxxi; 11 | 12 | namespace <#= Generator.Lib.BaseNamespace #> { 13 | 14 | public static partial class Libs { 15 | <# foreach (var lib in Libs) { #> 16 | public static readonly CppLibrary <#= CSharpLanguage.SafeIdentifier (lib.BaseName) #> = new CppLibrary ("<#= lib.BaseName #>", InlineMethods.<#= lib.InlinePolicy #>); 17 | <# } #> 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/generator/Templates/Context.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Templates { 4 | [Flags] 5 | public enum Context { 6 | Generic = 0, 7 | Parameter = 1 << 0, 8 | Return = 1 << 1, 9 | Interface = 1 << 2, 10 | Wrapper = 1 << 3 11 | } 12 | public static class ContextExtensions { 13 | public static bool Is (this Context bits, Context bit) 14 | { 15 | return (bits & bit) == bit; 16 | } 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /src/generator/generator.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.50727 7 | 2.0 8 | {AD0F9378-789C-4AF1-B0DD-6DD9A63C3401} 9 | Exe 10 | generator 11 | v3.5 12 | 13 | 14 | 15 | 16 | 2.0 17 | http://localhost/generator/ 18 | true 19 | Web 20 | true 21 | Foreground 22 | 7 23 | Days 24 | false 25 | false 26 | true 27 | 0 28 | 1.0.0.%2a 29 | true 30 | false 31 | true 32 | Templates 33 | 34 | 35 | true 36 | full 37 | false 38 | ..\..\bin\Debug 39 | DEBUG 40 | prompt 41 | 4 42 | AllRules.ruleset 43 | 44 | 45 | none 46 | false 47 | ..\..\bin\Release 48 | prompt 49 | 4 50 | AllRules.ruleset 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | Base.tt 63 | 64 | 65 | 66 | CSharpClass.tt 67 | 68 | 69 | CSharpLibs.tt 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | CSharpEnum.tt 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | False 94 | .NET Framework 3.5 SP1 Client Profile 95 | false 96 | 97 | 98 | False 99 | .NET Framework 3.5 SP1 100 | true 101 | 102 | 103 | False 104 | Windows Installer 3.1 105 | true 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | {4A864586-93C5-4DC1-8A80-F094A88506D7} 126 | Mono.Cxxi 127 | 128 | 129 | 130 | 131 | TextTemplatingFilePreprocessor 132 | CSharpClass.cs 133 | 134 | 135 | TextTemplatingFilePreprocessor 136 | CSharpLibs.cs 137 | 138 | 139 | TextTemplatingFilePreprocessor 140 | Base.cs 141 | 142 | 143 | TextTemplatingFilePreprocessor 144 | CSharpEnum.cs 145 | 146 | 147 | 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /src/generator/generator.in: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | exec mono "@expanded_libdir@/@PACKAGE@/generator.exe" "$@" 4 | -------------------------------------------------------------------------------- /src/generator/generator.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 9.00 3 | # Visual Studio 2005 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "generator", "generator.csproj", "{AD0F9378-789C-4AF1-B0DD-6DD9A63C3401}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Any CPU = Debug|Any CPU 9 | Release|Any CPU = Release|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {AD0F9378-789C-4AF1-B0DD-6DD9A63C3401}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {AD0F9378-789C-4AF1-B0DD-6DD9A63C3401}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {AD0F9378-789C-4AF1-B0DD-6DD9A63C3401}.Release|Any CPU.ActiveCfg = Release|Any CPU 15 | {AD0F9378-789C-4AF1-B0DD-6DD9A63C3401}.Release|Any CPU.Build.0 = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(MonoDevelopProperties) = preSolution 18 | StartupItem = generator.csproj 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /tests/FieldTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | 4 | namespace Tests { 5 | 6 | [TestFixture] 7 | public class FieldTests { 8 | 9 | [Test] 10 | public void TestReadCppObject () 11 | { 12 | var hf1 = new HasField (1, null); 13 | var hf2 = new HasField (2, hf1); 14 | var hf3 = new HasField (3, hf2); 15 | 16 | Assert.IsNull (hf1.other, "#1"); 17 | Assert.AreEqual (1, hf1.number); 18 | 19 | Assert.AreSame (hf2.other, hf1, "#2"); 20 | Assert.AreEqual (1, hf2.other.number); 21 | 22 | Assert.AreSame (hf3.other.other, hf1, "#3"); 23 | Assert.AreEqual (1, hf3.other.other.number, "#4"); 24 | } 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /tests/InheritanceTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | 4 | namespace Tests { 5 | 6 | [TestFixture] 7 | public class InheritanceTests { 8 | 9 | [Test] 10 | public void TestVirtualCall () 11 | { 12 | var cls = new NumberClass (5); 13 | Assert.AreEqual (5, cls.Number, "#1"); 14 | Assert.AreEqual (-5, cls.NegativeNumber, "#2"); 15 | } 16 | 17 | [Test] 18 | public void TestVirtualCallOnBaseClass () 19 | { 20 | var cls = new AdderClass (8); 21 | Assert.AreEqual (8, cls.Number, "#1"); 22 | 23 | cls.Add (2); 24 | Assert.AreEqual (10, ((NumberClass)cls).Number, "#2"); 25 | } 26 | 27 | [Test] 28 | public void TestVirtualCallOnVirtualBaseClass () 29 | { 30 | var cls = new AdderClassWithVirtualBase (8); 31 | Assert.AreEqual (8, cls.Number, "#1"); 32 | 33 | cls.Add (2); 34 | Assert.AreEqual (10, ((NumberClass)cls).Number, "#2"); 35 | } 36 | 37 | [Test] 38 | public void TestMultipleBases () 39 | { 40 | var cls = new ClassWithNonVirtualBases (5, 3); 41 | Assert.AreEqual (5, cls.Number, "#1"); 42 | Assert.AreEqual (3, ((MultiplierClass)cls).Number, "#2"); 43 | 44 | cls.Add (4); 45 | Assert.AreEqual (9, cls.Number, "#3"); 46 | Assert.AreEqual (3, ((MultiplierClass)cls).Number, "#4"); 47 | 48 | cls.MultiplierClass.Multiply (10); 49 | Assert.AreEqual (9, cls.Number, "#5"); 50 | Assert.AreEqual (30, ((MultiplierClass)cls).Number, "#6"); 51 | } 52 | 53 | [Test] 54 | public void TestMultipleVirtualBases () 55 | { 56 | var cls = new ClassWithVirtualBases (4); 57 | Assert.AreEqual (4, cls.Number, "#1"); 58 | Assert.AreEqual (4, ((MultiplierClassWithVirtualBase)cls).Number, "#2"); 59 | 60 | cls.Add (5); 61 | Assert.AreEqual (9, cls.Number, "#3"); 62 | Assert.AreEqual (9, ((MultiplierClassWithVirtualBase)cls).Number, "#4"); 63 | 64 | cls.MultiplierClassWithVirtualBase.Multiply (6); 65 | Assert.AreEqual (30, cls.Number, "#5"); 66 | Assert.AreEqual (30, ((MultiplierClassWithVirtualBase)cls).Number, "#6"); 67 | } 68 | 69 | [Test] 70 | public void TestNativeOverride1 () 71 | { 72 | var cls = new ClassThatOverridesStuff (5, 3); 73 | Assert.AreEqual (3, cls.Number, "#1"); 74 | Assert.AreEqual (3, ((NumberClass)cls).Number, "#2"); 75 | Assert.AreEqual (-3, cls.NegativeNumber, "#3"); 76 | Assert.AreEqual (5, cls.BaseNumber, "#4"); 77 | } 78 | 79 | [Test] 80 | public void TestNativeOverride2 () 81 | { 82 | var cls = ClassThatOverridesStuff.GetInstance (5, 3); 83 | Assert.AreEqual (3, cls.Number, "#1"); 84 | Assert.AreEqual (3, ((NumberClass)cls).Number, "#2"); 85 | Assert.AreEqual (-3, cls.NegativeNumber, "#3"); 86 | // Assert.AreEqual (5, ((ClassThatOverridesStuff)cls).BaseNumber, "#4"); 87 | } 88 | 89 | class ManagedOverride1 : NumberClass { 90 | 91 | public ManagedOverride1 () : base (3) 92 | { 93 | } 94 | 95 | public override int Number { 96 | get { 97 | return 25; 98 | } 99 | } 100 | } 101 | 102 | [Test] 103 | public void TestManagedOverride1 () 104 | { 105 | var cls = new ManagedOverride1 (); 106 | Assert.AreEqual (-25, cls.NegativeNumber, "#1"); 107 | } 108 | 109 | class ManagedOverride2 : ClassWithNonVirtualBases { 110 | 111 | public ManagedOverride2 () : base (5, 3) 112 | { 113 | } 114 | 115 | public override int Number { 116 | get { 117 | return 25; 118 | } 119 | } 120 | 121 | // override virtual member inherited from non-primary base 122 | protected override void MultiplierClass__Multiply (int n) 123 | { 124 | base.MultiplierClass__Multiply (10); 125 | } 126 | } 127 | 128 | [Test] 129 | public void TestManagedOverride2 () 130 | { 131 | var cls = new ManagedOverride2 (); 132 | Assert.AreEqual (-25, cls.NegativeNumber, "#1"); 133 | cls.MultiplierClass.Multiply (7); 134 | Assert.AreEqual (30, ((MultiplierClass)cls).Number, "#3"); 135 | cls.CallMultiply (2); 136 | Assert.AreEqual (25, cls.Number, "#2"); 137 | Assert.AreEqual (300, ((MultiplierClass)cls).Number, "#5"); 138 | } 139 | 140 | [Test] 141 | public void TestRoundtripManagedOverride () 142 | { 143 | var managed = new ManagedOverride2 (); 144 | var roundtripper = new ClassThatRoundtrips (7, managed); 145 | 146 | // test primary base ptr from native 147 | var cls = roundtripper.GetThis (); 148 | Assert.AreSame (roundtripper, cls, "#1"); 149 | Assert.AreEqual (7, cls.Number, "#2"); 150 | 151 | // test non-primary base ptr from native 152 | cls = roundtripper.GetThat (); 153 | Assert.AreSame ((MultiplierClass)managed, cls, "#3"); 154 | Assert.AreEqual (3, cls.Number, "#4"); 155 | 156 | Assert.AreEqual (3, cls.Number, "#5"); 157 | cls.Multiply (0); 158 | Assert.AreEqual (-30, cls.NegativeNumber, "#6"); 159 | 160 | // cast to non-primary subclass 161 | Assert.IsNotNull (((ClassWithNonVirtualBases)cls) as ManagedOverride2, "#7"); 162 | } 163 | 164 | } 165 | } 166 | 167 | -------------------------------------------------------------------------------- /tests/Makefile.am: -------------------------------------------------------------------------------- 1 | top_srcdir = ../ 2 | BUILD_DIR = $(top_srcdir)/bin/Debug 3 | 4 | INTEROP_DLL = \ 5 | $(BUILD_DIR)/Mono.Cxxi.dll 6 | 7 | TEST_DLL = $(BUILD_DIR)/Test.dll 8 | 9 | NATIVE = \ 10 | MarshalingTests \ 11 | InheritanceTests \ 12 | FieldTests \ 13 | ManglingTests 14 | 15 | MANAGED = \ 16 | FieldTests.cs \ 17 | InheritanceTests.cs \ 18 | ManglingTests.cs \ 19 | MarshalingTests.cs 20 | 21 | REFERENCES = \ 22 | -pkg:mono-nunit 23 | 24 | NATIVE_SRC = \ 25 | $(addprefix Native/,$(NATIVE)) 26 | 27 | all: $(TEST_DLL) 28 | 29 | %.cpp: %.h 30 | 31 | %.xml: $(addsuffix .h,$(NATIVE_SRC)) 32 | $(GCCXML) -fxml=$@ --gccxml-cxxflags -c Native/$*.h 33 | 34 | $(BUILD_DIR)/libTest.so: $(addsuffix .cpp,$(NATIVE_SRC)) 35 | $(CXX) -fPIC --shared -m32 -o $@ $^ 36 | 37 | $(BUILD_DIR)/libTest-inline.so: $(addsuffix .cpp,$(NATIVE_SRC)) 38 | $(CXX) -fPIC --shared -m32 -fkeep-inline-functions -o $@ $^ 39 | 40 | generated: $(addsuffix .xml,$(NATIVE)) 41 | $(RM) -r generated 42 | $(foreach X,$?, \ 43 | mono --debug $(BUILD_DIR)/generator.exe -o=$@ -ns=Tests -lib=Test -inline=surrogatelib $(X) && \ 44 | ) \ 45 | $(RM) generated/__*.cs && \ 46 | echo Bindings generated successfully. 47 | 48 | $(TEST_DLL): generated $(MANAGED) $(BUILD_DIR)/libTest.so $(BUILD_DIR)/libTest-inline.so 49 | $(GMCS) -debug -out:$@ -target:library -unsafe $(REFERENCES) -r:$(INTEROP_DLL) generated/*.cs $(MANAGED) 50 | 51 | clean: 52 | $(RM) -rf $(TEST_DLL) generated $(BUILD_DIR)/libTest.so $(BUILD_DIR)/libTest-inline.so $(addsuffix .xml,$(NATIVE)) 53 | 54 | run: $(TEST_DLL) 55 | nunit-console -nologo $(TEST_DLL) 56 | -------------------------------------------------------------------------------- /tests/ManglingTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | 4 | namespace Tests { 5 | 6 | [TestFixture] 7 | public class ManglingTests { 8 | 9 | [Test] 10 | public void TestCompression () 11 | { 12 | Compression.Test1 (null, "foo", null, "bar"); 13 | } 14 | 15 | [Test] 16 | public void TestNamespaced () 17 | { 18 | Ns1.Namespaced.Test1 (); 19 | Ns1.Namespaced.Test2 (null); 20 | } 21 | 22 | [Test] 23 | public void TestNamespaced2 () 24 | { 25 | var cls = new Ns1.Ns2.Namespaced2 (); 26 | cls.Test1 (); 27 | cls.Test2 (null); 28 | } 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /tests/MarshalingTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | 4 | namespace Tests { 5 | 6 | [TestFixture] 7 | public class MarshalingTests { 8 | 9 | [Test] 10 | public void TestClassReturn () 11 | { 12 | // Section 3.1.4: 13 | // Classes with non-default copy ctors/destructors are returned using a hidden 14 | // argument 15 | var c = ClassWithCopyCtor.Return (42); 16 | Assert.AreEqual (42, c.GetX (), "#1"); 17 | 18 | var c2 = ClassWithDtor.Return (43); 19 | Assert.AreEqual (43, c2.GetX (), "#2"); 20 | 21 | // This class is returned normally 22 | var c3 = ClassWithoutCopyCtor.Return (44); 23 | Assert.AreEqual (44, c3.GetX (), "#3"); 24 | } 25 | 26 | // An object as ref argument 27 | [Test] 28 | public void TestClassArg () 29 | { 30 | var c1 = new Class (4); 31 | var c2 = new Class (5); 32 | 33 | c1.CopyTo (c2); 34 | Assert.AreEqual (4, c2.GetX (), "#1"); 35 | } 36 | 37 | // A null object as ref argument 38 | [Test] 39 | public void TestClassArgNull () 40 | { 41 | var c1 = new Class (4); 42 | Assert.That (c1.IsNull (null), "#1"); 43 | } 44 | 45 | // An object as byval argument 46 | [Test] 47 | public void TestClassArgByval () 48 | { 49 | var c1 = new Class (4); 50 | var c2 = new Class (5); 51 | 52 | c1.CopyFromValue (c2); 53 | Assert.AreEqual (5, c1.GetX (), "#1"); 54 | } 55 | 56 | // A null object as byval argument 57 | [Test] 58 | [ExpectedException (typeof (ArgumentException))] 59 | public void TestClassArgByvalNull () 60 | { 61 | var c1 = new Class (4); 62 | c1.CopyFromValue (null); 63 | } 64 | 65 | [Test] 66 | public void TestByRefReturn () 67 | { 68 | var c1 = new Class (7); 69 | Assert.AreEqual (7, c1.GetXRef ()); 70 | } 71 | 72 | } 73 | 74 | } -------------------------------------------------------------------------------- /tests/Native/FieldTests.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "FieldTests.h" 3 | 4 | HasField::HasField (int number, HasField* other) 5 | { 6 | this->number = number; 7 | this->other = other; 8 | } -------------------------------------------------------------------------------- /tests/Native/FieldTests.h: -------------------------------------------------------------------------------- 1 | 2 | class HasField { 3 | public: 4 | int number; 5 | HasField* other; 6 | HasField (int number, HasField* other); 7 | }; 8 | -------------------------------------------------------------------------------- /tests/Native/InheritanceTests.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "InheritanceTests.h" 3 | 4 | NumberClass::NumberClass (int n) 5 | : num (n) 6 | { 7 | } 8 | int NumberClass::Number () const 9 | { 10 | return this->num; 11 | } 12 | int NumberClass::NegativeNumber () const 13 | { 14 | return -(this->Number ()); 15 | } 16 | NumberClass::~NumberClass () 17 | { 18 | this->num = 0; 19 | } 20 | 21 | 22 | AdderClass::AdderClass (int n) 23 | : NumberClass (n) 24 | { 25 | } 26 | void AdderClass::Add (int n) 27 | { 28 | this->num += n; 29 | } 30 | 31 | AdderClassWithVirtualBase::AdderClassWithVirtualBase (int n) 32 | : NumberClass (n) 33 | { 34 | } 35 | void AdderClassWithVirtualBase::Add (int n) 36 | { 37 | this->num += n; 38 | } 39 | 40 | 41 | MultiplierClass::MultiplierClass (int n) 42 | : NumberClass (n) 43 | { 44 | } 45 | void MultiplierClass::Multiply (int n) 46 | { 47 | this->num *= n; 48 | } 49 | 50 | MultiplierClassWithVirtualBase::MultiplierClassWithVirtualBase (int n) 51 | : NumberClass (n) 52 | { 53 | } 54 | void MultiplierClassWithVirtualBase::Multiply (int n) 55 | { 56 | this->num *= n; 57 | } 58 | 59 | 60 | ClassThatOverridesStuff::ClassThatOverridesStuff (int num, int my) 61 | : NumberClass (num), myNum (my) 62 | { 63 | } 64 | int ClassThatOverridesStuff::Number () const 65 | { 66 | return this->myNum; 67 | } 68 | int ClassThatOverridesStuff::BaseNumber () const 69 | { 70 | return this->NumberClass::Number (); 71 | } 72 | ClassThatOverridesStuff::~ClassThatOverridesStuff () 73 | { 74 | this->myNum = 0; 75 | } 76 | NumberClass* ClassThatOverridesStuff::GetInstance (int num, int my) 77 | { 78 | return new ClassThatOverridesStuff (num, my); 79 | } -------------------------------------------------------------------------------- /tests/Native/InheritanceTests.h: -------------------------------------------------------------------------------- 1 | 2 | class NumberClass { 3 | protected: 4 | int num; 5 | public: 6 | NumberClass (int n); 7 | virtual int NegativeNumber () const; 8 | virtual int Number () const; 9 | virtual ~NumberClass (); 10 | }; 11 | 12 | class AdderClass : public NumberClass { 13 | public: 14 | AdderClass (int n); 15 | virtual void Add (int n); 16 | }; 17 | class AdderClassWithVirtualBase : public virtual NumberClass { 18 | public: 19 | AdderClassWithVirtualBase (int n); 20 | virtual void Add (int n); 21 | }; 22 | 23 | class MultiplierClass : public NumberClass { 24 | public: 25 | MultiplierClass (int n); 26 | virtual void Multiply (int n); 27 | }; 28 | class MultiplierClassWithVirtualBase : public virtual NumberClass { 29 | public: 30 | MultiplierClassWithVirtualBase (int n); 31 | virtual void Multiply (int n); 32 | }; 33 | 34 | class ClassWithNonVirtualBases : public AdderClass, public MultiplierClass { 35 | public: 36 | // num is not shared between AdderClass and MultiplierClass; Add and Multiply should operate on different numbers 37 | ClassWithNonVirtualBases (int addN, int multN) : AdderClass (addN), MultiplierClass (multN) {} 38 | virtual void CallMultiply (int n) { this->Multiply (n); } 39 | }; 40 | class ClassWithVirtualBases : public AdderClassWithVirtualBase, public MultiplierClassWithVirtualBase { 41 | public: 42 | // num is shared between AdderClass and MultiplierClass; Add and Multiply should both operate on n 43 | ClassWithVirtualBases (int n) : NumberClass (n-2), AdderClassWithVirtualBase (n-1), MultiplierClassWithVirtualBase (n) {} 44 | }; 45 | 46 | 47 | class ClassThatOverridesStuff : public NumberClass { 48 | protected: 49 | int myNum; 50 | public: 51 | ClassThatOverridesStuff (int num, int my); 52 | virtual int Number () const; 53 | virtual ~ClassThatOverridesStuff (); 54 | virtual int BaseNumber () const; 55 | static NumberClass* GetInstance (int num, int my); 56 | }; 57 | 58 | class ClassThatRoundtrips : public MultiplierClass { 59 | protected: 60 | MultiplierClass* that; 61 | public: 62 | ClassThatRoundtrips (int n, MultiplierClass* managed) : MultiplierClass (n) { this->that = managed; } 63 | virtual MultiplierClass* GetThat () { return this->that; } 64 | virtual MultiplierClass* GetThis () { return this; } 65 | }; -------------------------------------------------------------------------------- /tests/Native/ManglingTests.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "ManglingTests.h" 3 | #include 4 | 5 | void Compression::Test1 (const Compression* a1, const char* a2, const Compression* a3, const char* a4) 6 | { 7 | printf ("Compression::Test1"); 8 | } 9 | 10 | void Ns1::Namespaced::Test1 () 11 | { 12 | printf ("Ns1::Namespaced::Test1"); 13 | } 14 | 15 | void Ns1::Namespaced::Test2 (const Compression* a1) 16 | { 17 | printf ("Ns1::Namespaced::Test2"); 18 | } 19 | 20 | Ns1::Ns2::Namespaced2::Namespaced2 () 21 | { 22 | printf ("Ns1::Ns2::Namespaced2::Namespaced2"); 23 | } 24 | 25 | void Ns1::Ns2::Namespaced2::Test1 () 26 | { 27 | printf ("Ns1::Ns2::Namespaced2::Test1"); 28 | } 29 | 30 | Ns1::Ns2::Namespaced2* Ns1::Ns2::Namespaced2::Test2 (Compression* a1) 31 | { 32 | printf ("Ns1::Ns2::Namespaced2::Test2"); 33 | } -------------------------------------------------------------------------------- /tests/Native/ManglingTests.h: -------------------------------------------------------------------------------- 1 | 2 | class Compression { 3 | public: 4 | static void Test1 (const Compression* a1, const char* a2, const Compression* a3, const char* a4); 5 | }; 6 | 7 | namespace Ns1 { 8 | class Namespaced { 9 | public: 10 | static void Test1 (); 11 | static void Test2 (const Compression* a1); 12 | }; 13 | } 14 | 15 | namespace Ns1 { namespace Ns2 { 16 | class Namespaced2 { 17 | public: 18 | Namespaced2 (); 19 | void Test1 (); 20 | Namespaced2* Test2 (Compression* a1); 21 | }; 22 | }} -------------------------------------------------------------------------------- /tests/Native/MarshalingTests.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "MarshalingTests.h" 3 | 4 | ClassWithCopyCtor::ClassWithCopyCtor(const ClassWithCopyCtor& f) { 5 | x = f.x; 6 | } 7 | 8 | ClassWithCopyCtor 9 | ClassWithCopyCtor::Return (int x) { 10 | return ClassWithCopyCtor (x); 11 | } 12 | 13 | int 14 | ClassWithCopyCtor::GetX () { 15 | return x; 16 | } 17 | 18 | ClassWithDtor 19 | ClassWithDtor::Return (int x) { 20 | return ClassWithDtor (x); 21 | } 22 | 23 | int 24 | ClassWithDtor::GetX () { 25 | return x; 26 | } 27 | 28 | ClassWithoutCopyCtor 29 | ClassWithoutCopyCtor::Return (int x) { 30 | return ClassWithoutCopyCtor (x); 31 | } 32 | 33 | int 34 | ClassWithoutCopyCtor::GetX () { 35 | return x; 36 | } 37 | -------------------------------------------------------------------------------- /tests/Native/MarshalingTests.h: -------------------------------------------------------------------------------- 1 | 2 | class ClassWithCopyCtor { 3 | int x; 4 | 5 | public: 6 | ClassWithCopyCtor(int xarg) { 7 | x = xarg; 8 | } 9 | 10 | ClassWithCopyCtor(const ClassWithCopyCtor& f); 11 | 12 | static ClassWithCopyCtor Return (int x); 13 | 14 | int GetX (); 15 | }; 16 | 17 | class ClassWithDtor { 18 | int x; 19 | 20 | public: 21 | ClassWithDtor(int xarg) { 22 | x = xarg; 23 | } 24 | 25 | ~ClassWithDtor () { 26 | } 27 | 28 | static ClassWithDtor Return (int x); 29 | 30 | int GetX (); 31 | }; 32 | 33 | 34 | class ClassWithoutCopyCtor { 35 | int x; 36 | 37 | public: 38 | ClassWithoutCopyCtor(int xarg) { 39 | x = xarg; 40 | } 41 | 42 | static ClassWithoutCopyCtor Return (int x); 43 | 44 | int GetX (); 45 | }; 46 | 47 | class Class { 48 | int x; 49 | 50 | public: 51 | Class (int xarg) { 52 | x = xarg; 53 | } 54 | 55 | void CopyFromValue (Class c) { 56 | x = c.x; 57 | } 58 | 59 | void CopyTo (Class *c) { 60 | c->x = x; 61 | } 62 | 63 | bool IsNull (Class *c) { 64 | return !c ? true : false; 65 | } 66 | 67 | int GetX () { 68 | return x; 69 | } 70 | 71 | int& GetXRef () { 72 | return x; 73 | } 74 | }; 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /tests/Native/NUnit.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // NUnit.cpp: Bridges the NUnit Assert methods to C++ 3 | // 4 | // Author: 5 | // Alexander Corrado (alexander.corrado@gmail.com) 6 | // 7 | // Copyright (C) 2010 Alexander Corrado 8 | // 9 | 10 | #include "NUnit.h" 11 | 12 | NUnit* NUnit::Assert; 13 | 14 | extern "C" { 15 | 16 | void SetNUnitInterface (NUnit* nunit) 17 | { 18 | NUnit::Assert = nunit; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /tests/Native/NUnit.h: -------------------------------------------------------------------------------- 1 | // 2 | // NUnit.h: The NUnit C++ interface 3 | // 4 | // Author: 5 | // Alexander Corrado (alexander.corrado@gmail.com) 6 | // 7 | // Copyright (C) 2010 Alexander Corrado 8 | // 9 | 10 | #ifndef _CPPINTEROP_NUNIT_H_ 11 | #define _CPPINTEROP_NUNIT_H_ 12 | 13 | #ifdef __GNUC__ 14 | #define EXPORT 15 | #elif defined(_MSC_VER) 16 | #define EXPORT __declspec(dllexport) 17 | #else 18 | #error Unknown compiler! 19 | #endif 20 | 21 | typedef const char* string; 22 | typedef unsigned int uint; 23 | typedef unsigned long ulong; 24 | 25 | class NUnit { 26 | public: 27 | static NUnit* Assert; 28 | 29 | virtual void Fail (string message); 30 | virtual void Fail (); 31 | virtual void IsTrue (bool condition, string message); 32 | virtual void IsTrue (bool condition); 33 | virtual void IsFalse (bool condition, string message); 34 | virtual void IsFalse (bool condition); 35 | virtual void IsEmpty (string aString, string message); 36 | virtual void IsEmpty (string aString); 37 | virtual void IsNotEmpty (string aString, string message); 38 | virtual void IsNotEmpty (string aString); 39 | virtual void AreEqual (int expected, int actual, string message); 40 | virtual void AreEqual (int expected, int actual); 41 | virtual void AreEqual (long expected, long actual, string message); 42 | virtual void AreEqual (long expected, long actual); 43 | virtual void AreEqual (uint expected, uint actual, string message); 44 | virtual void AreEqual (uint expected, uint actual); 45 | virtual void AreEqual (ulong expected, ulong actual, string message); 46 | virtual void AreEqual (ulong expected, ulong actual); 47 | virtual void AreEqual (double expected, double actual, double delta, string message); 48 | virtual void AreEqual (double expected, double actual, double delta); 49 | virtual void AreEqual (float expected, float actual, float delta, string message); 50 | virtual void AreEqual (float expected, float actual, float delta); 51 | virtual void AreNotEqual (int expected, int actual, string message); 52 | virtual void AreNotEqual (int expected, int actual); 53 | virtual void AreNotEqual (long expected, long actual, string message); 54 | virtual void AreNotEqual (long expected, long actual); 55 | virtual void AreNotEqual (uint expected, uint actual, string message); 56 | virtual void AreNotEqual (uint expected, uint actual); 57 | virtual void AreNotEqual (ulong expected, ulong actual, string message); 58 | virtual void AreNotEqual (ulong expected, ulong actual); 59 | virtual void AreNotEqual (double expected, double actual, string message); 60 | virtual void AreNotEqual (double expected, double actual); 61 | virtual void AreNotEqual (float expected, float actual, string message); 62 | virtual void AreNotEqual (float expected, float actual); 63 | virtual void Greater (int expected, int actual, string message); 64 | virtual void Greater (int expected, int actual); 65 | virtual void Greater (long expected, long actual, string message); 66 | virtual void Greater (long expected, long actual); 67 | virtual void Greater (uint expected, uint actual, string message); 68 | virtual void Greater (uint expected, uint actual); 69 | virtual void Greater (ulong expected, ulong actual, string message); 70 | virtual void Greater (ulong expected, ulong actual); 71 | virtual void Greater (double expected, double actual, string message); 72 | virtual void Greater (double expected, double actual); 73 | virtual void Greater (float expected, float actual, string message); 74 | virtual void Greater (float expected, float actual); 75 | virtual void Less (int expected, int actual, string message); 76 | virtual void Less (int expected, int actual); 77 | virtual void Less (long expected, long actual, string message); 78 | virtual void Less (long expected, long actual); 79 | virtual void Less (uint expected, uint actual, string message); 80 | virtual void Less (uint expected, uint actual); 81 | virtual void Less (ulong expected, ulong actual, string message); 82 | virtual void Less (ulong expected, ulong actual); 83 | virtual void Less (double expected, double actual, string message); 84 | virtual void Less (double expected, double actual); 85 | virtual void Less (float expected, float actual, string message); 86 | virtual void Less (float expected, float actual); 87 | virtual void GreaterOrEqual (int expected, int actual, string message); 88 | virtual void GreaterOrEqual (int expected, int actual); 89 | virtual void GreaterOrEqual (long expected, long actual, string message); 90 | virtual void GreaterOrEqual (long expected, long actual); 91 | virtual void GreaterOrEqual (uint expected, uint actual, string message); 92 | virtual void GreaterOrEqual (uint expected, uint actual); 93 | virtual void GreaterOrEqual (ulong expected, ulong actual, string message); 94 | virtual void GreaterOrEqual (ulong expected, ulong actual); 95 | virtual void GreaterOrEqual (double expected, double actual, string message); 96 | virtual void GreaterOrEqual (double expected, double actual); 97 | virtual void GreaterOrEqual (float expected, float actual, string message); 98 | virtual void GreaterOrEqual (float expected, float actual); 99 | virtual void LessOrEqual (int expected, int actual, string message); 100 | virtual void LessOrEqual (int expected, int actual); 101 | virtual void LessOrEqual (long expected, long actual, string message); 102 | virtual void LessOrEqual (long expected, long actual); 103 | virtual void LessOrEqual (uint expected, uint actual, string message); 104 | virtual void LessOrEqual (uint expected, uint actual); 105 | virtual void LessOrEqual (ulong expected, ulong actual, string message); 106 | virtual void LessOrEqual (ulong expected, ulong actual); 107 | virtual void LessOrEqual (double expected, double actual, string message); 108 | virtual void LessOrEqual (double expected, double actual); 109 | virtual void LessOrEqual (float expected, float actual, string message); 110 | virtual void LessOrEqual (float expected, float actual); 111 | }; 112 | 113 | 114 | #endif /* _CPPINTEROP_NUNIT_H_ */ 115 | -------------------------------------------------------------------------------- /tests/README: -------------------------------------------------------------------------------- 1 | This directory contains tests for the cpp binding. To run them, type 'make run'. 2 | -------------------------------------------------------------------------------- /tests/Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.50727 7 | 2.0 8 | {3C290CBE-CA39-47F6-B3A0-ACD16C5A38C8} 9 | Library 10 | Tests 11 | Test 12 | v3.5 13 | 14 | 15 | 16 | 17 | 2.0 18 | http://localhost/Tests/ 19 | true 20 | Web 21 | true 22 | Foreground 23 | 7 24 | Days 25 | false 26 | false 27 | true 28 | 0 29 | 1.0.0.%2a 30 | true 31 | false 32 | true 33 | 34 | 35 | true 36 | full 37 | false 38 | ..\bin\Debug 39 | DEBUG 40 | prompt 41 | 4 42 | AllRules.ruleset 43 | 44 | 45 | none 46 | false 47 | ..\bin\Release 48 | prompt 49 | 4 50 | AllRules.ruleset 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | False 62 | 63 | 64 | False 65 | 66 | 67 | False 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | False 100 | 101 | 102 | 103 | 104 | 105 | {4A864586-93C5-4DC1-8A80-F094A88506D7} 106 | Mono.Cxxi 107 | 108 | 109 | {AD0F9378-789C-4AF1-B0DD-6DD9A63C3401} 110 | generator 111 | 112 | 113 | --------------------------------------------------------------------------------