[Mono-list] Registering threads with the garbage collector

2004-07-09 Thread Patrick Hartling
I am mixing managed and unmanaged code using Mono 1.0, and I am having
problems with the garbage collector crashing due to unregistered
threads.  The unmanaged code does spawn threads of its own that call
back into the managed code.  Prior to calling into the managed code,
mono_thread_attach() is invoked as described in the documentation for
embedding Mono.  mono_thread_attach() does not seem to be telling the
garbage collector about the externally spawned thread, however.  Is
there another function (or set of functions) to call in addition to
mono_thread_attach() that will register the thread with the garbage
collector?

 -Patrick


-- 
Patrick L. Hartling | Research Assistant, VRAC
http://www.137.org/patrick/ | 2274 Howe Hall Room 2624
PGP: http://tinyurl.com/ywd54   | http://www.vrac.iastate.edu/



signature.asc
Description: This is a digitally signed message part


[Mono-list] Missing type declarations in Mono installation

2004-07-09 Thread Patrick Hartling
Is there a reason that the headers containing declarations for types
such as _MonoClass, _MonoAssembly, and _MonoMethod are not included with
a Mono installation?  This appears to have changed between Mono 0.96 and
0.97.  I don't understand how Mono embedding is supposed to be
accomplished without declarations for these types.  Or is it that the
members of these types not supposed to be accessed directly by user
code?

 -Patrick


-- 
Patrick L. Hartling | Research Assistant, VRAC
http://www.137.org/patrick/ | 2274 Howe Hall Room 2624
PGP: http://tinyurl.com/ywd54   | http://www.vrac.iastate.edu/



signature.asc
Description: This is a digitally signed message part


[Mono-list] Using ld wrapping with Boehm GC

2004-06-29 Thread Patrick Hartling
I am working on a project that mixes native code with the CLI, and I am
having problems with threading.  The problems arise because the native
code creates its own threads, and those threads can call into the CLI
universe.  To handle this, I have code that bridges between the native
code and the CLI, and in places where a thread spawned by the native
code will call into the CLI universe, mono_thread_attach() is called
first.  Unfortunately, this does not seem to be sufficient.

What I am seeing is that my code can run for a few seconds, but then it
crashes consistently at the end of the Boehm GC function
pthread_push_all_stacks().  The full stack trace of the crash is
attached.  (Note that I am using Mono 0.97 on Fedora Core 1 with the
Boehm GC code that comes bundled with the Mono runtime source.)  The
crash appears to occur because Boehm GC does not know about at least one
of the threads created by the aforementioned native code.

I cannot modify the native code to use GC_pthread_create() and friends,
so I am trying to find a way to let Boehm GC know about the threads
created by the native code.  I have done a little bit of digging, and I
see that Boehm GC can use the function call wrapping feature of GNU ld. 
However, I do not see anything in the Mono build process that enables or
takes advantage of this feature.

I am prepared to take steps to try out this capability of Boehm GC and
GNU ld, but before I do, I am curious to know if there is something in
Mono's API that I can call to register externally created threads with
the garbage collector.  mono_thread_attach() by itself does not appear
to be quite enough for my case, but I may be missing something.  Is
there another Mono API call I can make or some Boehm GC thread
registration call?  If not, I will go ahead with the function call
wrapping via ld in hopes of getting my code to work.

 -Patrick


-- 
Patrick L. Hartling | Research Assistant, VRAC
http://www.137.org/patrick/ | 2274 Howe Hall Room 2624
PGP: http://tinyurl.com/ywd54   | http://www.vrac.iastate.edu/
#0  0x0031ac32 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
#1  0x00840989 in raise () from /lib/tls/libc.so.6
#2  0x00842342 in abort () from /lib/tls/libc.so.6
#3  0x00d85467 in GC_abort (msg=0xdd2fe0 Collecting from unknown thread.)
at misc.c:1071
#4  0x00d8a467 in pthread_push_all_stacks () at pthread_stop_world.c:270
#5  0x00d8a4fc in GC_push_all_stacks () at pthread_stop_world.c:277
#6  0x00d863d6 in GC_default_push_other_roots () at os_dep.c:2048
#7  0x00d846ee in GC_push_roots (all=1, cold_gc_frame=0x48e31f8 \034??)
at mark_rts.c:648
#8  0x00d82592 in GC_mark_some (cold_gc_frame=0x48e31f8 \034??) at mark.c:304
#9  0x00d7c896 in GC_stopped_mark (stop_func=0xd7c11c GC_never_stop_func)
at alloc.c:520
#10 0x00d7c562 in GC_try_to_collect_inner (
stop_func=0xd7c11c GC_never_stop_func) at alloc.c:367
#11 0x00d7d2c8 in GC_collect_or_expand (needed_blocks=1, ignore_off_page=0)
at alloc.c:998
#12 0x00d7d4ba in GC_allocobj (sz=28, kind=1) at alloc.c:1073
#13 0x00d810be in GC_generic_malloc_inner (lb=112, k=1) at malloc.c:136
#14 0x00d811bb in GC_generic_malloc (lb=112, k=1) at malloc.c:192
#15 0x00d8145d in GC_malloc (lb=112) at malloc.c:297
#16 0x00d1be8f in mono_array_new_full (domain=0x9617980,
array_class=0x99b4a38, lengths=0x98714c8, lower_bounds=0x0)
at object.c:1659
#17 0x00cc534d in mono_array_new_va (cm=0x99b4a00) at jit-icalls.c:420
#18 0x0067908e in ?? ()
#19 0x099b4a00 in ?? ()
#20 0x0006 in ?? ()
#21 0x0004 in ?? ()
#22 0x3f7c1c5c in ?? ()
#23 0x0039d8c8 in __JCR_LIST__ ()
   from 
/home/users/patrick/src/Juggler/main/juggler/build.linux-fc1.posix.gcc33/instlinks/lib/i686/libvrj.so
#24 0x048e33e8 in ?? ()
#25 0x00355c54 in __normal_iterator (this=0x9685f80, [EMAIL PROTECTED])
at stl_iterator.h:593
#26 0x00531a14 in ?? ()
#27 0x09685f80 in ?? ()


signature.asc
Description: This is a digitally signed message part


[Mono-list] Custom marshaler lookup regression?

2004-05-26 Thread Patrick Hartling
The problems I reported two days ago with incorrect values being passed
into unmanaged code from custom marshalers have been fixed in CVS, but
now I have run up against something that feels very familiar.  Four
months ago, I reported a problem in Mono 0.29 with inter-assembly
lookups of custom marshalers associated with delegates:

http://lists.ximian.com/archives/public/mono-list/2004-January/017851.html

This was fixed in Mono 0.30.  However, with today's 0.92 snapshot
(mono-0.92.20040526), I am having *exactly* the same problems I did back
in January.  Essentially, my custom marshalers are not being found if
they are not all in the same assembly.  Is this a regression in Mono, or
am I doing something wrong?  I have recompiled everything I am using
with the runtime from today's snapshot.

 -Patrick


-- 
Patrick L. Hartling | Research Assistant, VRAC
[EMAIL PROTECTED]| 2274 Howe Hall Room 2624
http://www.137.org/patrick/ | http://www.vrac.iastate.edu/
PGP: http://wwwkeys.gpg.cz:11371/pks/lookup?op=getsearch=0xEBF86398



signature.asc
Description: This is a digitally signed message part


Re: [Mono-list] mcs hangs on FreeBSD!

2004-03-31 Thread Patrick Hartling
On Tue, 2004-03-30 at 13:59, Swaroop C H wrote:
 Hello all,
 
 I searched the list archives but I couldn't find a solution
 to this problem I am facing.
 
 I was able to successfully compile and install Mono 0.30.2
 from source on a FreeBSD box, but however mcs hangs whenever I
 try to compile a simple HelloWorld program. It even shows the
 version number for 'mcs --version' but then it just goes into
 some sort of infinite loop i.e. it hangs. I have to hit Ctrl-C to
 stop it.
 
 Can anyone point out what I am doing wrong?

What version of FreeBSD are you using?  With garbage collection enabled,
Mono has behaved this way for me for quite some time on FreeBSD 5.x.  If
you have the Ports Collection, /usr/ports/lang/mono is marked as broken
for all 5.x versions up to and including 5.2-current.  With FreeBSD 4.x,
I believe that Mono works fine.  This behavior is something I have been
wanting to try to fix for a while, but Linux systems are readily
available enough to me that getting FreeBSD fixed is not a very high
priority (even though I prefer to use FreeBSD).

 -Patrick


-- 
Patrick L. Hartling | Research Assistant, VRAC
[EMAIL PROTECTED]| 2274 Howe Hall Room 2624
http://www.137.org/patrick/ | http://www.vrac.iastate.edu/
PGP: http://wwwkeys.gpg.cz:11371/pks/lookup?op=getsearch=0xEBF86398



signature.asc
Description: This is a digitally signed message part


[Mono-list] Finding assemblies with embedded Mono and MONO_PATH

2004-03-23 Thread Patrick Hartling
I am learning how to use the Mono embedding API, and I have run into an
issue with loading assemblies that I cannot seem to get past.  My goal
is to be able to take advantage of the $MONO_PATH environment variable
when loading assemblies into application domains, but as far as I can
tell, the suggested function call, mono_domain_assembly_open(), ignores
$MONO_PATH completely.  After tracing through the code a few times, I
found that mono_assembly_load() searches $MONO_PATH, and I can load my
test assembly using that function.  However, I cannot figure out how to
add the newly loaded assembly to my application domain.

My question basically boils down to this: is it valid for me to use
mono_assembly_load() instead of mono_domain_assembly_open(), and if so,
how do I add the loaded assembly to an application domain?  If it is not
a good idea for my code to call mono_assembly_load(), should I emulate
the relevant calls in mono/metadata/assembly.c so that my code searches
$MONO_PATH prior to each call to mono_domain_assembly_open()?

 -Patrick


-- 
Patrick L. Hartling | Research Assistant, VRAC
[EMAIL PROTECTED]| 2274 Howe Hall Room 2624
http://www.vrac.iastate.edu/~patrick/   | http://www.vrac.iastate.edu/
PGP: http://wwwkeys.gpg.cz:11371/pks/lookup?op=getsearch=0xEBF86398



signature.asc
Description: This is a digitally signed message part


Re: [Mono-list] Calls to CIL code from native threads

2004-01-27 Thread Patrick Hartling
On Tue, 2004-01-27 at 09:52, Paolo Molaro wrote:
 On 01/26/04 Patrick Hartling wrote:
  I am working on a project that mixes CIL code with natively compiled C
  and C++ in a multi-threaded environment.  The natively compiled code may
  make calls into the CIL universe from different threads, and I am trying
  to figure out how to manage that with Mono's C API.  In the
  documentation about embedding Mono, I see a reference to the function
  mono_thread_attach().  My (very preliminary) testing has allowed me to
  make a call from a native thread other than the primordial thread into
  the CIL universe by calling mono_thread_attach() first.  I pass in a
  pointer to a MonoDomain object allocated on the heap by the calling
  thread via mono_domain_create().
 
 Are you really using multiple domains in your app?

My understand of application domains is still very limited, so I am not
sure I can answer this question definitively.  If threads spawned by
native code each need their own domain, then yes, I am using multiple
domains.  Is there something different that I could call besides
mono_domain_create() to get a valid MonoDomain* to hand off to
mono_thread_attach()?

 If that's not the case you should pass the MonoDomain you get back from
 mono_jit_init().

I may not have described my situation in enough detail.  I have a C#
class with a static Main() function that I execute using Mono.  That
class instantiates an object that (conceptually) derives from a native
C++ object.  The C# object is handed off to C++ code where callbacks are
invoked from a thread spawned by the native code.  The end result is
that a C# object is handled polymorphically by C++ code.  The primary
thread of control in the C# Main() function blocks until the C++ code
shuts down.

At this point, I do not have code of my own that calls mono_jit_init(). 
In the long term, I probably will, but for now, I am concentrating on
making C# applications that can activate and utilize the native C++
libraries I am exposing for use with CLS-compliant languages.

  After the call into the CIL code returns, however, I appear to get into
  a deadlock state later when I make another call to
  mono_thread_attach().  I have successfully dealt with a similar
 
 mono_thread_attach() should be called only once per-thread.
 If you're using multiple application domains, you may get all sort of
 issues, since the mono_thread_attach() implementation is broken in that
 case, there is already a bug filed about that.

I think that my analysis regarding a deadlock was wrong.  The
application was hanging, but I do not know where.  I modified things so
that mono_thread_attach() is called precisely once pre thread, and
things appear to be working quite well now.

  situation using Python/C where the Global Interpreter Lock (GIL) must be
  acquired and released to allow native code threads to call into the
  Python interpreter.  I am wondering if calling mono_thread_attach() has
  the effect of acquiring a mutex somewhere that needs to be released by
  my code when I no longer need to hold it.  Is that the case?  If so,
  what is the call to make this happen?  Or am I just on the wrong track
  entirely?
 
 If you're using multiple appdomains you're hitting a mono bug. If you're
 not, just try using mono_thread_attach() once per thread.
 
  Lastly, is there any documentation for doing multi-threaded programming
  with Mono?  So far, I have mostly been looking through the code trying
  to find types and functions that look roughly like what I need.
 
 The API is supposed to be thread-safe, so there should be no particular
 thing to do apart from calling mono_thread_attach() in threads not
 created by mono. Please, see the suggestions above and report bavk if
 they solve your issue.
 Thanks.

Your suggestion of calling mono_thread_attach() once per thread appears
to have put things into good working order.  Thanks for the help.

 -Patrick


-- 
Patrick L. Hartling | Research Assistant, VRAC
[EMAIL PROTECTED]| 2274 Howe Hall Room 2624
http://www.vrac.iastate.edu/~patrick/   | http://www.vrac.iastate.edu/
PGP: http://wwwkeys.gpg.cz:11371/pks/lookup?op=getsearch=0xEBF86398



signature.asc
Description: This is a digitally signed message part


RE: [Mono-list] Delegates and inter-assembly custom marshale

2004-01-23 Thread Patrick Hartling
Zoltan,
I tried today's snapshot (0.30-1.20040123), but the results are the
same.  Mono still hits the same assertion failure.  Is there something
that I could be doing wrong?

 -Patrick


On Thu, 2004-01-22 at 14:32, Varga Zoltan wrote:
Hi,
 
Fixed in CVS.
 
 Zoltan
 
  -Original Message-
  From: [EMAIL PROTECTED]
  [mailto:[EMAIL PROTECTED] Behalf Of ext
 Patrick
  Hartling
  Sent: January 21,2004 22:06
  To: [EMAIL PROTECTED]
  Subject: [Mono-list] Delegates and inter-assembly custom
 marshaler
  lookup
  
  
  I have run across what I think is a bug in Mono's lookup
 of custom
  marshalers associated with delegates.  The problem occurs
 when a
  delegate defined in a base class (A.Base in assembly A.dll) 
  has a custom
  marshaler for a parameter.  If a class drived from A.Base in 
  a different
 
 
 
 ___
 Mono-list maillist  -  [EMAIL PROTECTED]
 http://lists.ximian.com/mailman/listinfo/mono-list
-- 
Patrick L. Hartling | Research Assistant, VRAC
[EMAIL PROTECTED]| 2274 Howe Hall Room 2624
http://www.vrac.iastate.edu/~patrick/   | http://www.vrac.iastate.edu/
PGP: http://wwwkeys.gpg.cz:11371/pks/lookup?op=getsearch=0xEBF86398



signature.asc
Description: This is a digitally signed message part


[Mono-list] Delegates and inter-assembly custom marshaler lookup

2004-01-21 Thread Patrick Hartling
I have run across what I think is a bug in Mono's lookup of custom
marshalers associated with delegates.  The problem occurs when a
delegate defined in a base class (A.Base in assembly A.dll) has a custom
marshaler for a parameter.  If a class drived from A.Base in a different
assembly (B.Derived in assembly B.dll) tries to pass the delegate as a
function pointer to native code, Mono 0.29 hits an assertion failure on
line 2069 of mono/metadata/marshal.c (line 2082 for today's snapshot).

At a high level, mono_reflection_type_from_name() is returning NULL for
the custom marshaler type in question, though I have not nailed down
exactly why this is happening.  In mono_reflection_type_from_name(),
info.assembly.name comes back NULL after the call to
mono_reflection_parse_type().  I think that if info.assembly.name were
not NULL, the correct assembly image would be found to get the custom
marshaler.

I have attached C# and C++ code with a makefile that can be used to
repeat the problem I am running into.  I have verified that this code
works with the .NET Framework versions 1.0 and 1.1 (compiling the C++
code with Visual C++ 7.0 and 7.1 to match the .NET Framework version
accordingly).  The code is more complicated than I would like it to be,
but to the best of my current understanding, it is the least amount of
code I can come up with to demonstrate the crash.  Note that in B.cs, a
custom marshaler from the assembly A is used for a P/Invoke call, and it
works fine.  For that reason, I concluded that the lookup problem is
related to delegates.

Looking through Bugzilla, it looks as though the first C# attachment
with Bug 43351
(http://bugzilla.ximian.com/showattachment.cgi?attach_id=4400) is
related to what I am running into, but that code runs correctly with
Mono 0.29.  My guess is that the difference between the two cases is
that I am trying to access a delegate in an external assembly whereas
Marcus' example is contained within a single assembly.

 -Patrick


-- 
Patrick L. Hartling | Research Assistant, VRAC
[EMAIL PROTECTED]| 2274 Howe Hall Room 2624
http://www.vrac.iastate.edu/~patrick/   | http://www.vrac.iastate.edu/
PGP: http://wwwkeys.gpg.cz:11371/pks/lookup?op=getsearch=0xEBF86398

using System;
using System.Runtime.InteropServices;

namespace A
{

public class Arg
{
   protected internal IntPtr mRawObject = IntPtr.Zero;

   internal Arg(IntPtr obj)
   {
  mRawObject = obj;
   }

   [DllImport(a_native, CharSet = CharSet.Ansi)]
   private extern static IntPtr new_Arg();

   public Arg()
   {
  mRawObject = new_Arg();
   }

   [DllImport(a_native, CharSet = CharSet.Ansi)]
   private extern static IntPtr Arg_go(IntPtr obj);

   public void go()
   {
  Arg_go(mRawObject);
   }
}

// Custom marshaler for the type A.Arg which will be used as an attribute to
// a delegate parameter in the class A.Base.
public class ArgMarshaler : ICustomMarshaler
{
   public void CleanUpManagedData(Object obj) { }

   public void CleanUpNativeData(IntPtr nativeData) { }

   public int GetNativeDataSize()
   {
  return -1;
   }

   public IntPtr MarshalManagedToNative(Object obj)
   {
  return ((A.Arg) obj).mRawObject;
   }

   public Object MarshalNativeToManaged(IntPtr nativeObj)
   {
  return new Arg(nativeObj);
   }

   public static ICustomMarshaler GetInstance(string cookie)
   {
  return mInstance;
   }

   private static ArgMarshaler mInstance = new ArgMarshaler();
}

public abstract class Base
{
   protected internal IntPtr mRawObject = IntPtr.Zero;

   internal Base(IntPtr obj)
   {
  mRawObject = obj;
   }

   [DllImport(a_native, CharSet = CharSet.Ansi)]
   private extern static IntPtr new_BaseAdapter(
  [MarshalAs(UnmanagedType.FunctionPtr)] f_delegate fCallback);

   protected Base()
   {
  m_f_delegate = new f_delegate(f);

  // Mono crashes when handling the following call when invoked from a
  // derived class constructor in a different assembly.
  mRawObject = new_BaseAdapter(m_f_delegate);
   }

   // Delegate with a custom marshaler for the parameter a.  This causes Mono
   // to crash when m_f_delegate is passed to a native function as a function
   // pointer.
   public delegate void f_delegate(
  [MarshalAs(UnmanagedType.CustomMarshaler,
 MarshalTypeRef = typeof(ArgMarshaler))] Arg a);
   protected f_delegate m_f_delegate;

   public abstract void f(Arg a);
}

public class BaseMarshaler : ICustomMarshaler
{
   private class DummyBase : Base
   {
  public DummyBase(IntPtr obj)
  {
 mRawObject = obj;
  }

  public override void f(Arg a) { }
   }

   public void CleanUpManagedData(Object obj) { }

   public void CleanUpNativeData(IntPtr nativeData) { }

   public int GetNativeDataSize()
   {
  return -1;
   }

   public IntPtr MarshalManagedToNative(Object obj)
   {
  return ((A.Base) obj).mRawObject;
   }

   public Object MarshalNativeToManaged(IntPtr nativeObj)
  

Re: [Mono-list] python?

2004-01-21 Thread Patrick Hartling
On Tue, 2004-01-20 at 08:20, Neal D. Becker wrote:
 Can I use mono to interop between C++ and python?

If all you want to have talking is C++ and Python talking (no .NET
languages such as C# or VB.NET thrown into the mix), then I highly
recommend Boost.Python:

   http://www.boost.org/libs/python/doc/
   http://www.python.org/sigs/c++-sig/

This software is completely unrelated to Mono, however, and it won't
provide interoperability with any .NET language by itself.

 -Patrick


-- 
Patrick L. Hartling | Research Assistant, VRAC
[EMAIL PROTECTED]| 2274 Howe Hall Room 2624
http://www.vrac.iastate.edu/~patrick/   | http://www.vrac.iastate.edu/
PGP: http://wwwkeys.gpg.cz:11371/pks/lookup?op=getsearch=0xEBF86398



signature.asc
Description: This is a digitally signed message part


Re: [Mono-list] Strange behavior with P/Invoke and return values

2003-08-28 Thread Patrick Hartling
Paolo Molaro wrote:
On 08/25/03 Patrick Hartling wrote:

I am experimenting with mapping C++ to C# via P/Invoke and Mono 0.26 on 
Red Hat 8.0, and I have run into something odd when a native function 
returns a C++ object by value.  From the way it is behaving, it appears 
that something is going wrong in the allocation of memory on the stack 
for the return value.

I have attached some code that demonstrates the problem.  My intent is to 
use a custom marshaler to make a copy of the return value object in a 
freshly allocated C# object reference.  (The validity of this technique 
is what I am evaluating, so it's possible I am going down the wrong road 
with this.)
[...]

  [DllImport(return_copy)]
  [return : MarshalAs(UnmanagedType.CustomMarshaler,
  MarshalTypeRef = typeof(ReferenceDataMarshaler))]
  private static extern ReferenceData Marshal_getReferenceCopy(IntPtr instPtr);


Does your code work under the MS runtime?
As you point out below, there was a mismatch in the code, but with a 
modification, it did work with the MS runtime.  It doesn't fix the 
problems with Mono, unfortunately.

I'm not sure it's supposed to work.
ReferenceData in C# is a class, so by default the marshal code in mono
(check metadata/marshal.c) assumes the unmanaged function returns a
pointer. The C++ code, though returns the data by value, so you have a
mismatch. You may try to define a C# struct that matches ReferenceData
and use that as the type returned from Marshal_getReferenceCopy().
In a wrapper you create a ReferenceData obj and copy the fields from the
struct.
That sounds like a good idea.  Thanks for the tip.

 -Patrick

--
Patrick L. Hartling | Research Assistant, VRAC
[EMAIL PROTECTED]| 2624 Howe Hall: 1.515.294.4916
http://www.137.org/patrick/ | http://www.vrac.iastate.edu/
___
Mono-list maillist  -  [EMAIL PROTECTED]
http://lists.ximian.com/mailman/listinfo/mono-list


[Mono-list] Strange behavior with P/Invoke and return values

2003-08-25 Thread Patrick Hartling
I am experimenting with mapping C++ to C# via P/Invoke and Mono 0.26 on 
Red Hat 8.0, and I have run into something odd when a native function 
returns a C++ object by value.  From the way it is behaving, it appears 
that something is going wrong in the allocation of memory on the stack 
for the return value.

I have attached some code that demonstrates the problem.  My intent is to 
use a custom marshaler to make a copy of the return value object in a 
freshly allocated C# object reference.  (The validity of this technique 
is what I am evaluating, so it's possible I am going down the wrong road 
with this.)

The output from running the C# application is the following:

Marshal::Marshal()
new_Marshal() -- mb: 0x80f0580
new_Marshal() -- mb-mRef.x: 51
DataUser.DataUser() -- mRawObject: 0x80f0580
DataUser.getReferenceCopy() -- mRawObject: 0x80f0580
Marshal_getReferenceCopy() -- self_: 0x80c3d20
Marshal_getReferenceCopy() -- self_-mRef.x: 135533516
MarshalNativeToManaged() -- nativeObj: 0x80f0580
MarshalNativeToManaged() -- obj's value: 135533516
Reference copy value: 135533516
mRawObject (C#) and self_ (C/C++) should always have the same value, but 
notice that when DataUser.getReferenceCopy() is called, the value of the 
pointer changes from 0x80f0580 to 0x80c3d20, but my custom marshaler's 
MarshalNativeToManaged() gets 0x80f0580 as the value of its argument, 
nativeObj.

By adding a second garbage argument to Marshal_getReferenceCopy(), I was 
able to determine that the first argument is what gets passed to my 
custom marshaler and the second is the value of mRawObject.  Am I 
misunderstanding something about how to marshal return values?  Is my 
approach to C++ object return value copying fubared?  Is there a specific 
place in the Mono source I could examine to try get a more in-depth 
understanding of Mono is trying to do here?

 -Patrick

--
Patrick L. Hartling | Research Assistant, VRAC
[EMAIL PROTECTED]| 2624 Howe Hall: 1.515.294.4916
http://www.137.org/patrick/ | http://www.vrac.iastate.edu/
// To compile:
//c++ -o libreturn_copy.so return_copy.cpp

#include iostream
#include iomanip


class ReferenceData
{
public:
   ReferenceData() : x(0)
   {
   }

   unsigned int x;
};

class Marshal
{
public:
   Marshal()
   {
  std::cout  Marshal::Marshal()  std::endl;
  mRef.x = 51;
   }

   ReferenceData getReferenceCopy()
   {
  return mRef;
   }

private:
   ReferenceData mRef;
};

extern C
{

Marshal* new_Marshal()
{
   Marshal* mb = new Marshal;
   std::cout  new_Marshal() -- mb:   std::hex  mb  std::dec
  std::endl;
   std::cout  new_Marshal() -- mb-mRef.x:   mb-getReferenceCopy().x
  std::endl;
   return (Marshal*) mb;
}

ReferenceData Marshal_getReferenceCopy(Marshal* self_)
{
   std::cout  Marshal_getReferenceCopy() -- self_:   std::hex
  self_  std::dec  std::endl;
   std::cout  Marshal_getReferenceCopy() -- self_-mRef.x: 
  self_-getReferenceCopy().x  std::endl;
   return self_-getReferenceCopy();
}

}
// To compile:
//   mcs return_copy.cs

using System;
using System.Runtime.InteropServices;


namespace test
{

[StructLayout(LayoutKind.Sequential)]
class ReferenceData
{
   public override string ToString()
   {
  return x.ToString();
   }

   public uint x;
};

class ReferenceDataMarshaler : ICustomMarshaler
{
   public void CleanUpManagedData(Object obj)
   {
   }

   public void CleanUpNativeData(IntPtr nativeData)
   {
   }

   public int GetNativeDataSize()
   {
  return -1;
   }

   public IntPtr MarshalManagedToNative(Object obj)
   {
  return new IntPtr((int) ((ReferenceData) obj).x);
   }

   public Object MarshalNativeToManaged(IntPtr nativeObj)
   {
  ReferenceData obj = new ReferenceData();
  obj.x = (uint) Marshal.ReadInt32(nativeObj);
  Console.WriteLine(MarshalNativeToManaged() -- nativeObj: 0x{0:x},
nativeObj.ToInt32());
  Console.WriteLine(MarshalNativeToManaged() -- obj's value:  + obj);
  return obj;
   }

   public static ICustomMarshaler GetInstance(string cookie)
   {
  return mInstance;
   }

   private static ReferenceDataMarshaler mInstance = new ReferenceDataMarshaler();
};

class DataUser
{
   protected internal IntPtr mRawObject;

   [DllImport(return_copy, CharSet=CharSet.Ansi)]
   private static extern IntPtr new_Marshal();

   public DataUser()
   {
  mRawObject = new_Marshal();
  Console.WriteLine(DataUser.DataUser() -- mRawObject: 0x{0:x},
mRawObject.ToInt32());
   }

   [DllImport(return_copy)]
   [return : MarshalAs(UnmanagedType.CustomMarshaler,
   MarshalTypeRef = typeof(ReferenceDataMarshaler))]
   private static extern ReferenceData Marshal_getReferenceCopy(IntPtr instPtr);

   public ReferenceData getReferenceCopy()
   {
  Console.WriteLine(DataUser.getReferenceCopy() -- mRawObject: 0x{0:x},