Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I am assuming trust that the DLL has a function that deallocates the <code>recipe</code> struct. That's something that you can't possibly hope to do from C#. More on this point later on.</p> <p>A Delphi dynamic array is not a valid interop type. It really should only used internally to Delphi code compiled with a single version of the compiler. Exposing it publically is akin to exporting C++ classes from a DLL.</p> <p>In an ideal world you would re-work the Delphi code so that it exported the array using a proper interop type. However, in this case it is actually relatively easy for you to do the marshalling without adjusting the Delphi code.</p> <p>Delphi dynamic arrays were introduced way back in Delphi 4 and their implementation has remained unchanged since then. The <code>array of T</code> dynamic array variable is effectively a pointer to the first element. The elements are laid out sequentially in memory. The dynamic array variable also maintains (at negative offsets) a reference count and the size of the array. You can safely ignore these since you are neither modifying the dynamic array nor needing to ascertain its size.</p> <p>Using <code>IntPtr</code> for the <code>Parameters</code> field is perfect. Because <code>TParameter</code> contains just a single 32 bit integer you can use <code>Marshal.Copy</code> to copy it straight to an <code>int[]</code> array.</p> <p>So, when the Delphi DLL returns, you can do the final marshalling step using <a href="http://msdn.microsoft.com/en-us/library/ms146635.aspx" rel="nofollow"><code>Marshal.Copy</code></a>.</p> <pre><code>if (theRecipe.paramCount&gt;0) { int[] parameters = new int[theRecipe.paramCount]; Marshal.Copy(theRecipe.parameters, parameters, 0, theRecipe.paramCount); ... do something with parameters } </code></pre> <hr> <p>That deals with the dynamic array, but as it happens you have another problem with your code as it stands. You are declaring the two strings as <code>string</code> in the C# struct. This means that the marshaller will take responsibility for freeing the memory returned by the Delphi DLL in the two <code>PAnsiChar</code> fields. It will do so by calling <code>CoTaskMemFree</code>. I'm fairly sure that's not going to match the allocation of the <code>PAnsiChar</code> fields made in the Delphi code.</p> <p>As stated above, I would expect that the contract for this interface is that you call a further DLL function to deallocate the heap memory referenced by the <code>recipe</code> struct. That is, the two strings, and the dynamic array.</p> <p>To deal with this issue from C# you need to make sure that the marshaller does not attempt to deallocate the <code>PAnsiChar</code> fields. You can achieve that by declaring them as <code>IntPtr</code> in the C# struct. Then call <a href="http://msdn.microsoft.com/en-us/library/7b620dhe.aspx" rel="nofollow"><code>Marshal.PtrToStringAnsi</code></a> to convert to a C# string.</p> <hr> <p>I've had to make a few assumptions about the contract between the Delphi code and the C# code in order to write the above. If any of my assumptions are incorrect please update the question and I'll try to make this answer match! I hope this helps.</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. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      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