summary refs log tree commit diff stats
path: root/tests/cpp/tvirtual.nim
diff options
context:
space:
mode:
Diffstat (limited to 'tests/cpp/tvirtual.nim')
-rw-r--r--tests/cpp/tvirtual.nim126
1 files changed, 126 insertions, 0 deletions
diff --git a/tests/cpp/tvirtual.nim b/tests/cpp/tvirtual.nim
new file mode 100644
index 000000000..385d052b8
--- /dev/null
+++ b/tests/cpp/tvirtual.nim
@@ -0,0 +1,126 @@
+discard """
+  targets: "cpp"
+  cmd: "nim cpp $file"
+  output: '''
+hello foo
+hello boo
+hello boo
+Const Message: hello world
+NimPrinter: hello world
+NimPrinterConstRef: hello world
+NimPrinterConstRefByRef: hello world
+'''
+"""
+
+{.emit:"""/*TYPESECTION*/
+#include <iostream>
+  class CppPrinter {
+  public:
+    
+    virtual void printConst(char* message) const {
+        std::cout << "Const Message: " << message << std::endl;
+    }
+    virtual void printConstRef(char* message, const int& flag) const {
+        std::cout << "Const Ref Message: " << message << std::endl;
+    }  
+    virtual void printConstRef2(char* message, const int& flag) const {
+        std::cout << "Const Ref2 Message: " << message << std::endl;
+    }  
+    
+};
+""".}
+
+proc newCpp*[T](): ptr T {.importcpp:"new '*0()".}
+type 
+  Foo = object of RootObj
+  FooPtr = ptr Foo
+  Boo = object of Foo
+  BooPtr = ptr Boo
+  CppPrinter {.importcpp, inheritable.} = object
+  NimPrinter {.exportc.} = object of CppPrinter
+
+proc salute(self: FooPtr) {.virtual.} = 
+  echo "hello foo"
+
+proc salute(self: BooPtr) {.virtual.} =
+  echo "hello boo"
+
+let foo = newCpp[Foo]()
+let boo = newCpp[Boo]()
+let booAsFoo = cast[FooPtr](newCpp[Boo]())
+
+#polymorphism works
+foo.salute()
+boo.salute()
+booAsFoo.salute()
+let message = "hello world".cstring
+
+proc printConst(self: CppPrinter, message: cstring) {.importcpp.}
+CppPrinter().printConst(message)
+
+#notice override is optional. 
+#Will make the cpp compiler to fail if not virtual function with the same signature if found in the base type
+proc printConst(self: NimPrinter, message: cstring) {.virtual:"$1('2 #2) const override".} =
+  echo "NimPrinter: " & $message
+
+proc printConstRef(self: NimPrinter, message: cstring, flag: int32) {.virtual:"$1('2 #2, const '3& #3 ) const override".} =
+  echo "NimPrinterConstRef: " & $message
+
+proc printConstRef2(self: NimPrinter, message: cstring, flag {.byref.}: int32) {.virtual:"$1('2 #2, const '3 #3 ) const override".} =
+  echo "NimPrinterConstRefByRef: " & $message
+
+NimPrinter().printConst(message)
+var val : int32 = 10
+NimPrinter().printConstRef(message, val)
+NimPrinter().printConstRef2(message, val)
+
+#bug 22269
+type Doo = object
+proc naiveMember(x: Doo): int {. virtual .} = 2
+discard naiveMember(Doo())
+
+#asmnostackframe works with virtual
+{.emit:"""/*TYPESECTION*/
+  template<typename T>
+  struct Box {
+      T* first;
+     
+      Box(int x){
+        first = new T(x);
+      };
+  };
+  struct Inner {
+    int val;
+    //Coo() = default;
+    Inner(int x){
+      val = x;
+    };
+  };
+  struct Base {
+    virtual Box<Inner> test() = 0;
+  };
+""".}
+
+type 
+  Inner {.importcpp.} = object
+  Base {.importcpp, inheritable.} = object
+  Child  = object of Base
+  Box[T] {.importcpp, inheritable.} = object
+    first: T
+
+proc makeBox[T](x:int32): Box[T] {.importcpp:"Box<'0>(@)", constructor.}
+
+proc test(self: Child): Box[Inner] {.virtual, asmnostackframe.} = 
+  let res {.exportc.} = makeBox[Inner](100)
+  {.emit:"return res;".}
+  
+
+discard Child().test() 
+
+import virtualptr
+
+#We dont want to pull Loo directly by using it as we are testing that the pointer pulls it. 
+proc makeMoo(): Moo {.importcpp:"{ new Loo() }".}
+
+makeMoo().loo.salute()
+