Note that there are some explanatory texts on larger screens.

plurals
  1. POMarshalling plain structures: does C# copy them onto heap?
    primarykey
    data
    text
    <p>I have a native DLL, written in Delphi, actively using callback mechanism: a callback function is "registered" and later called from inside of the DLL:</p> <pre><code>function RegisterCallback(CallbackProc: TCallbackProc): Integer; stdcall; </code></pre> <p>Most of the callback functions are passing plain structures by reference, like the following:</p> <pre><code>TCallbackProc = procedure(Struct: PStructType); stdcall; </code></pre> <p>where PStructType is declared as</p> <pre><code>TStructType = packed record Parameter1: array[0..9] of AnsiChar; Parameter2: array[0..19] of AnsiChar; Parameter3: array[0..29] of AnsiChar; end; PStructType = ^TStructType; </code></pre> <p>This DLL is consumed by a .NET application, written in C#. The C# code is written very negligently and the application as a whole behaves unreliably, showing hard-to-identify exceptions, raised in different places from run to run.</p> <p>I do not have reasons to suspect the DLL, because it had already proved itself as a quite robust piece of software, used in many other applications. What I am currently concerned about is the way how those structures are used in C#.</p> <p>Let's assume, that the record from above is re-declared in C# as follows:</p> <pre><code>[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] public struct TStructType { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)] public string Parameter1; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)] public string Parameter2; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 30)] public string Parameter3; } </code></pre> <p>and the callback is declared as</p> <pre><code>[UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate void CallbackProc(ref TStructType Struct); </code></pre> <p>Now something interesting begins. Let's assume, that in the DLL, the registered callbacks are called in this way:</p> <pre><code>var Struct: TStructType; begin // Struct is initialized and filled with values CallbackProc(@Struct); end; </code></pre> <p>But what I see in the C# application, and what I do not like at all, that the marshaled structure is saved aside as a pointer for future use:</p> <pre><code>private void CallbackProc(ref TStructType Struct) { SomeObjectList.Add(Struct); // !!! WTF? } </code></pre> <p>As I understand, Struct variable is that created on Delphi's stack deep inside in the DLL, and storing pointer to it on heap in client application - is a sheer adventure. </p> <p>I am not a big fan/expert of C#, so please excuse my naive question, does the marshaller do something behind the scene, like copy structures onto heap or something like that, or the fact that the application sometimes works is a matter of pure chance?</p> <p>Thank you in advance.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload