[Mono-list] Registering threads with the garbage collector
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
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
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?
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!
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
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
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
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
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?
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
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
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},