test asymmetric type marshalling - out attribute for ctype, imtype and cstype typemaps.

also test fix for garbage collection problem where the proxy class was being collected before an unmanaged function that used the object returned - problem was most visible in multithreaded environment, so the test kicks off a few threads


git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@7173 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
William S Fulton 2005-04-28 22:03:50 +00:00
commit b504f37f90
3 changed files with 184 additions and 0 deletions

View file

@ -14,6 +14,7 @@ top_builddir = @top_builddir@../
CPP_TEST_CASES = \
csharp_exceptions \
csharp_typemaps \
enum_thorough_simple \
enum_thorough_typesafe

View file

@ -0,0 +1,108 @@
using System;
using System.Threading;
using csharp_typemapsNamespace;
public class runme
{
static void Main()
{
// Test the C# types customisation by modifying the default char * typemaps to return a single char
Things things = new Things();
System.Text.StringBuilder initialLetters = new System.Text.StringBuilder();
char myChar = things.start("boo");
initialLetters.Append(myChar);
myChar = Things.stop("hiss");
initialLetters.Append(myChar);
myChar = csharp_typemaps.partyon("off");
initialLetters.Append(myChar);
myChar = csharp_typemaps.STRINGCONSTANT;
initialLetters.Append(myChar);
if (initialLetters.ToString() != "bhox")
throw new Exception("initial letters failed");
if (csharp_typemaps.go != "zzz")
throw new Exception("go variable failed");
// Eager garbage collector test
{
const int NUM_THREADS = 8;
Thread[] threads = new Thread[NUM_THREADS];
TestThread[] testThreads = new TestThread[NUM_THREADS];
// invoke the threads
for (int i=0; i<NUM_THREADS; i++) {
testThreads[i] = new TestThread(i);
threads[i] = new Thread(new ThreadStart(testThreads[i].Run));
threads[i].Start();
}
// wait for the threads to finish
for (int i=0; i<NUM_THREADS; i++) {
threads[i].Join();
}
for (int i=0; i<NUM_THREADS; i++) {
if (testThreads[i].Failed) throw new Exception("Test Failed");
}
}
}
}
public class TestThread {
private int threadId;
public bool Failed;
public TestThread(int id) {
threadId = id;
}
public void Run() {
Failed = false;
try {
// Older versions of SWIG used IntPtr instead of HandleRef to hold the underlying
// C++ pointer, so this test would (usually) fail as the garbage collector would
// sometimes collect the Number class while it was being used in unmanaged code
for (int i=0; i<5000; i++) { // run test for a few seconds
{
Obj obj = new Obj();
Number n = new Number(i);
Number triple = obj.triple(n);
if (triple.Value != i*3)
throw new ApplicationException("triple failed: " + triple.Value);
}
{
Obj obj = new Obj();
Number n = new Number(i);
Number times6 = obj.times6(n);
if (times6.Value != i*6)
throw new ApplicationException("times6 failed: " + times6.Value);
}
{
Obj obj = new Obj();
Number n = new Number(i);
Number times9 = obj.times9(n);
if (times9.Value != i*9)
throw new ApplicationException("times9 failed: " + times9.Value);
}
{
Number n = new Number(i);
Number quadruple = csharp_typemaps.quadruple(n);
if (quadruple.Value != i*4)
throw new ApplicationException("quadruple failed: " + quadruple.Value);
}
{
Number n = new Number(i);
Number times8 = csharp_typemaps.times8(n);
if (times8.Value != i*8)
throw new ApplicationException("times8 failed: " + times8.Value);
}
{
Number n = new Number(i);
Number times12 = csharp_typemaps.times12(n);
if (times12.Value != i*12)
throw new ApplicationException("times12 failed: " + times12.Value);
}
}
} catch (Exception e) {
Console.Error.WriteLine("Test failed (thread " + threadId + "): " + e.Message);
Failed = true;
}
}
}

View file

@ -0,0 +1,75 @@
%module csharp_typemaps
// Test the C# types customisation by modifying the default char * typemaps to return a single char
%typemap(imtype, out="char /*imtype out override*/") char * "string"
%typemap(cstype, out="char /*cstype out override*/") char * "string"
%typemap(ctype, out="char /*ctype out override*/") char * "char *"
%typemap(out) char * %{
// return the 0th element rather than the whole string
$result = SWIG_csharp_string_callback($1)[0];
%}
%typemap(csout, excode=SWIGEXCODE) char * {
char ret = $imcall;$excode
return ret;
}
%typemap(csvarout, excode=SWIGEXCODE2) char *, char[ANY], char[] %{
get {
string ret = new string($imcall, 3);$excode
return ret;
} %}
%inline %{
namespace Space {
class Things {
public:
char* start(char *val) { return val; }
static char* stop(char *val) { return val; }
};
char* partyon(char *val) { return val; }
#define STRINGCONSTANT "xyz string"
char *go = "zap";
}
// Number and Obj are for the eager garbage collector runtime test
struct Number {
Number(double value) : Value(value) {}
double Value;
};
class Obj {
public:
Number triple(Number n) {
n.Value *= 3;
return n;
}
Number times6(const Number& num) {
Number n(num);
n.Value *= 6;
return n;
}
Number times9(const Number* num) {
Number n(*num);
n.Value *= 9;
return n;
}
};
Number quadruple(Number n) {
n.Value *= 4;
return n;
};
Number times8(const Number& num) {
Number n(num);
n.Value *= 8;
return n;
};
Number times12(const Number* num) {
Number n(*num);
n.Value *= 12;
return n;
};
%}