Note that there are some explanatory texts on larger screens.

plurals
  1. POWhat is the correct P/Invoke signature of double*& which points to an unmanaged array?
    primarykey
    data
    text
    <p>I am wrapping a c++ dll which does high quality sample rate conversion in c# and I am not sure what kind of type I should use for the <strong>op0</strong> parameter. A C++ wrapper would call it like this:</p> <pre><code>int _cdecl process(double* const ip0, int l, double*&amp; op0) </code></pre> <p>The documentation says about the parameter:</p> <p>"@param[out] op0 This variable receives the pointer to the resampled data. This pointer may point to the address within the "ip0" input buffer, or to *this object's internal buffer. In real-time applications it is suggested to pass this pointer to the next output audio block and consume any data left from the previous output audio block first before calling the process() function again. The buffer pointed to by the "op0" on return may be owned by the resampler, so it should not be freed by the caller."</p> <p>What I would like to do is the following:</p> <pre><code> [DllImport("r8bsrc.dll", EntryPoint="process", CallingConvention = CallingConvention.Cdecl)] public static extern int Process([in] double[] ip0, int length, [out] double[] op0); </code></pre> <p>But I am pretty sure this would not work, since the marshaller cannot know how big the memory behind <strong>op1</strong> is, or am I wrong?</p> <p>So I guess I have to copy the values behind op1 back to a managed array myself. Maybe:</p> <pre><code> [DllImport("r8bsrc.dll", EntryPoint="process", CallingConvention = CallingConvention.Cdecl)] public static extern int Process([in] double[] ip0, int length, out IntPtr op0); //or do i need out double* ? </code></pre> <p>And then wrap it again with:</p> <pre><code> private IntPtr FOutBufferPtr; //reuse it as recommeded public int Process(double[] input, out double[] output) { var outSamples = R8BrainDLLWrapper.Process(input, input.Length, out FOutBufferPtr); output = new double[outSamples]; Marshal.Copy(FOutBufferPtr, output, 0, outSamples); } </code></pre> <p>What is the optimal way which involves the least number of copies?</p> <p>EDIT2:</p> <p>This is the current code, it works perfectly:</p> <pre><code> public int Process(double[] input, ref double[] output) { //pin the input during process var pinnedHandle = GCHandle.Alloc(input, GCHandleType.Pinned); //resample var outSamples = R8BrainDLLWrapper.Process(FUnmanagedInstance, pinnedHandle.AddrOfPinnedObject(), input.Length, out FOutBufferPtr); //copy to output array if(output.Length &lt; outSamples) output = new double[outSamples]; Marshal.Copy(FOutBufferPtr, output, 0, outSamples); //free pin pinnedHandle.Free(); return outSamples; } </code></pre> <p>The signature is now:</p> <pre><code> [DllImport("r8bsrc.dll", EntryPoint="r8b_process", CallingConvention = CallingConvention.Cdecl)] public static extern int Process(IntPtr instance, IntPtr ip0, int length, out IntPtr op0); </code></pre>
    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.
 

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