Skip to content

Commit

Permalink
Fixed MemoryTests
Browse files Browse the repository at this point in the history
added notes to read me.
  • Loading branch information
OlegJakushkin committed Oct 8, 2015
1 parent e69304c commit 0bb4d4d
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 38 deletions.
8 changes: 8 additions & 0 deletions CSharp/Tests/Objects/CSharpB.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
using System;
using System.Collections.Generic;
using LibraryNamespace;

namespace Tests {
internal class CSharpB: B {

// One Must replecate an object keept via shared_ptr in Proxy language object (for GC not to eat it);
// Use List for multiple delegates (this will probably add a lock to client code!)
// ReSharper disable once NotAccessedField.Local
private A _keeperOfA;
public override void SetA( A p ) {
Console.WriteLine( "C# ruls." );
_keeperOfA = p;
base.SetA( p );
}

}
}
42 changes: 17 additions & 25 deletions CSharp/Tests/Tests/MemoryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,30 @@
namespace Tests {
[TestClass]
public class MemoryTests {
private void ClearGC() {
GC.Collect();
GC.Collect( GC.MaxGeneration );
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForFullGCApproach();
GC.WaitForFullGCComplete();
GC.Collect();
}

[TestMethod]
public void TestSharedPointerLiveCicleWithUsing() {
public void TestWithUsing() {
using ( var a = new CSharpAwithDestructor() ) {
using ( var b = new CSharpB() ) {
using ( var a = new CSharpAwithDestructor() ) {
a.SetName( "rar" );
b.SetA( a );

Assert.AreEqual( "C++ Call A:C# Hell!", b.CallA() );
}
Assert.AreEqual( "C++ Call A:C# Hell!", b.CallA() );
}
GC.Collect();
GC.WaitForFullGCComplete();
ClearGC();
Assert.AreEqual( CSharpAwithDestructor.State.Destroyed, CSharpAwithDestructor.LastState );
}


private void TestInnerScope(CSharpB b) {
var a = new CSharpAwithDestructor();
a.SetName( "rar" );
Expand All @@ -32,32 +39,17 @@ void TestScope() {
var b = new CSharpB();
{
TestInnerScope(b);
ClearGC();
Assert.AreEqual( "C++ Call A:C# Hell!", b.CallA() );
}

GC.Collect();
GC.Collect( GC.MaxGeneration );
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForFullGCApproach();
GC.WaitForFullGCComplete();
GC.Collect();

ClearGC();
Assert.AreEqual( "C++ Call A:C# Hell!", b.CallA() ); // How to keep shared_ptr passed object as long as C++ needs it?
}

[TestMethod]
public void TestSharedPointerLiveCicleWithNew() {
public void TestWithNew() {
TestScope();

GC.Collect();
GC.Collect(GC.MaxGeneration);
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForFullGCApproach();
GC.WaitForFullGCComplete();
GC.Collect();

ClearGC();
Assert.AreEqual( CSharpAwithDestructor.State.Destroyed, CSharpAwithDestructor.LastState );
}
}
Expand Down
28 changes: 15 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
# TestSWIG
SWIG+CSharp samples
SWIG + CSharp samples
Structure:
----
CPP -> Main library
CSharp -> C++ library proxy (wrapper)
-> C# Library
-> C# Tests

Loosely based on [CSharpOdeLibrary](https://github.com/OlegJakushkin/CSharpOdeLibrary ) and my NEC'2015 talk.
Loosely based on [CSharpOdeLibrary](https://github.com/OlegJakushkin/CSharpOdeLibrary ) and my NEC'2015 talk.
Requires SWIG 3 installed in your path.


Steps to reproduce:
----
- you create C++ library
- you minimize its interface and build its dll+lib into Build folder
- you create a SWIG .i wrapper
- you ran SWIG code generator
- You create C++ library
- You minimize its interface and build its dll+lib into Build folder
- You create a SWIG .i wrapper
- You ran SWIG code generator
- create a C++ wrapper dll based on generated files, connect it to your library, and build its dll into Build folder
- create a C# wrapper library based on generated files, and build its dll into Build folder
- create a C# tests project to test C# library and build it into Build folder

So you shall get:

- a pure C++ library with no exports (build for all platforms you need)
- a C++ wrapper library with exports for each language you support, (build for all platforms you need)
- a library in target language
- a test case library
- a bench mark library if required
- A pure C++ library with no exports (build for all platforms you need)
- A C++ wrapper library with exports for each language you support, (build for all platforms you need)
- A library in target language
- A test case library
- A bench mark library if required

General Notes:
----
Expand All @@ -43,11 +43,13 @@ SWIG .i notes:
----
- use ```%module(directors="1") ModuleName;``` and ```%feature("director");``` to get inheritance
- use template specialization alike ```%template(StateType) std::vector<double>;``` inside .i file in conjunction with type defenitions alike ```typedef std::vector<T> StateType;``` in your C++ interface
- use ```%shared_ptr(ClassName)``` for an object to be passable as shared_ptr, note that manual shared_ptr into needed type conversion is required on C# side! Stuff like SWIGTYPE_p_std__shared_ptrT_%TYPE_NAME%_t into TYPE_NAME replacement
- use ```%shared_ptr(ClassName)``` for an object to be passable as shared_ptr, if done correctly Stuff like SWIGTYPE_p_std__shared_ptrT_%TYPE_NAME%_t should not appear - lock for the order
- In case of ```shared_ptr``` use, note that GC collectable objects that inherit from C++ code will be bound to GC rules! Thus if you have a ```shared_ptr``` in object ```B``` C++ code you must create an object ```BTargetLanguage``` that would keep a reference in target language to that ```shared_ptr``` (see ```BSharp``` implementation and ```TestWithNew``` for reference).
- Write ```shared_ptr(A)``` before ```%feature("director") A;```

C++ Notes:
----
- Write events/delegates using virtual class functions (no C pointers, std::function's etc)
- Write Interfaces as pure virtual classes
- Use single inheritance trees
- Wrap all non **std** library objects needed externaly
- Wrap all non **std** library objects needed externally

0 comments on commit 0bb4d4d

Please sign in to comment.