Click here to Skip to main content
15,867,568 members
Please Sign up or sign in to vote.
5.00/5 (2 votes)
See more:

I've been having problems with call a method in a DLL that outputs 3 parameters when taking a photo from a CF-Camera.

Basically, I know the types that are to be returned from the method schematic at the bottom of this post, but am having a hard time figuring when to use out, ref, or nothing before the attributes.

When ever I put an out, or ref before the byte[] below, the application will crash, but if I don't I have a 0 byte array. Also, regardless of what I put before the UInt32 I still get nothing back. If I do not put out or ref before the byte[] I get a bool returned as successful.

[DllImport("FlyCAMm1_AV.dll")]

public static extern bool Capture_A_Frame(byte[] pretBuff, ref UInt32 pdSize); 

Obviously I have initialised the Cam properly, and set the settings prior to trying to capture, but don't know what I am doing wrong.

Below is directly from the sparse doco. about the Method.

BOOL Capture_A_Frame(LPBYTE pretBuff, DWORD *pdSize);

Parameters

pretBuff [out] long pointer to preview data.

pdSize
[out] long pointer to the size of pretBuff.

Return Value
TRUE indicates success. FALSE indicates failure.

###Reply to Davey###

Close, but no cigar, although you have helped a fella out with the code to Marshal the bytes from memory to a byte[].

The problem is that when I use the out keyword on the first param, pretBuff, the application will crash out completely with no way to catch any exception. Kinda like an ejector seat from my code. I've attached the screen grab below, though uncertain it will be of any use.

I've also tried using [Out] rather than out on the PInvoke itself, but to no avail. This way, I get a return of true from the method, but no pointer to the memory address, nor length. What is the difference between [Out] and out.

###Response to Davey's post at approx 19:15 25/11/09 (GMT)###

Thanx again Davey, for another swift response.

Unfortunately, this gives me a result of true, but the IntPtr and int are both set to '0'. I've attached a grab of the QuickWatch listing for the IntPtr below. The Marshal.Copy then, obviously, returns an ArgumentNullException. Any ideas further?

Thanx again for persevering on this one, I'm almost inclined to give you high ratings for that alone. =]

Posted
Updated 26-Nov-09 3:31am
v8

Have you tried using an IntPtr for the first parameter but without the out?
C#
[DllImport("FlyCAMm1_AV.dll")]
private static extern bool Capture_A_Frame(
    IntPtr pretBuff,
    out int pdSize);
C#
IntPtr pretBuff = IntPtr.Zero;
int pdSize;
bool result = Capture_A_Frame(pretBuff, out pdSize);
Try this and examine result and pretBuff. If it returns true and pretBuff isn't zero after the function call then that part is OK.
 
Share this answer
 

If I understand what you've posted correctly, the first parameter is the pointer to a byte array that is created in memory by the API. If this is the case then passing a value to it (by using ref or nothing) will probably not suceed - you may need an out there. The problem with this is you will need to copy the data from the unmanaged array using the Marshal class to be able to access it.

Try this, I think it will work:

C#
public class CapturedFrame
{
    private byte[] buffer;

    private CapturedFrame()
    { }

    /// <summary>
    /// Gets a captured frame.
    /// </summary>
    /// <remarks>The Buffer property will contain the data, or null if capture was unsuccessful.</remarks>
    /// <returns>A CapturedFrame instance with the data (if any) in the Buffer property.</returns>
    public static CapturedFrame CaptureFrame()
    {
        CapturedFrame result = new CapturedFrame();
        IntPtr pretBuff;
        int pdSize;
        if(Capture_A_Frame(out pretBuff, out pdSize))
        {
            result.buffer = new byte[pdSize];
            Marshal.Copy(pretBuff, result.buffer, 0, pdSize);
        }
        return result;
    }

    public byte[] Buffer
    {
        get { return buffer; }
    }

    [DllImport("FlyCAMm1_AV.dll")]
    private static extern bool Capture_A_Frame(
        out IntPtr pretBuff,
        out int pdSize);
}
This can be used like this:
C#
CapturedFrame capturedFrame = CapturedFrame.CaptureFrame();
if (capturedFrame.Buffer != null)
{
    // data in capturedFrame.Buffer
}
 
Share this answer
 
v2

In that case it is asking for the pointer to an existing byte array and it's size, not creating one as was implied by the [Out] in the documentation.

So, what you need it seems is to create a byte array, get it's pointer and pass that along with it's size. The function declaration will be:

C#
[DllImport("FlyCAMm1_AV.dll")]
private static extern bool Capture_A_Frame(IntPtr pretBuff, int pdSize);

To wrap this method you will need something like this:

C#
public static bool CaptureAFrame(byte[] buffer)
{
    GCHandle gcHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
    bool result = Capture_A_Frame(gcHandle.AddrOfPinnedObject(), buffer.Length);
    gcHandle.Free();
    return result;
}

You can then call this like:

C#
byte[] frameBuffer = new byte[256];
if (CaptureAFrame(frameBuffer))
{
    // Data is now in frameBuffer...
}
give you high ratings for that alone

 :grin: No problem!

 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900