将属性传递给非托管DLL时在何处使用"out","ref"或什么都不使用 [英] Where to use 'out', 'ref', or nothing when passing attributes to Unmanaged DLL

查看:101
本文介绍了将属性传递给非托管DLL时在何处使用"out","ref"或什么都不使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从CF相机拍摄照片时,我在调用DLL中的方法时遇到了问题,该方法会输出3个参数.

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.

每当我在下面的byte []之前放入out或ref时,应用程序就会崩溃,但是如果我不这样做,我将得到一个0字节的数组.另外,无论我在UInt32之前放了什么,我仍然什么也得不到.如果我没有在byte []之前插入或引用ref,那么返回的布尔值将被视为成功.

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); 

很明显,我已经正确初始化了Cam,并在尝试捕获之前进行了设置,但是不知道我在做什么错.

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.

下面的内容直接来自稀疏的doco.关于方法.

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

BOOL Capture_A_Frame(LPBYTE pretBuff, DWORD *pdSize);

参数

pretBuff [out] long pointer to preview data.

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

Return Value
TRUE indicates success. FALSE indicates failure.

###回复戴维###

关闭,但不要抽雪茄,尽管您已经帮助代码将内存中的字节编组为字节[].

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

问题是,当我在第一个参数pretBuff上使用out关键字时,应用程序将完全崩溃,无法捕获任何异常.有点像我代码中的顶出座椅.我已经附上了下面的屏幕抓取器,尽管不确定是否会有用.

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.

我也尝试过使用[Out]而不是在PInvoke本身上使用,但无济于事.这样,我从方法中返回了true,但是没有指向内存地址的指针,也没有长度. [Out]和out之间有什么区别.

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.

###在大约19:15 25/11/09(GMT)回复戴维的帖子###

再次感谢戴维,另一个迅速的回应.

Thanx again Davey, for another swift response.

不幸的是,这给了我一个true的结果,但是IntPtr和int都设置为"0".我已附上以下IntPtr的QuickWatch清单.然后,显然,Marshal.Copy返回ArgumentNullException.还有什么想法吗?

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. =]

推荐答案

有尝试使用IntPtr作为第一个参数,但没有输出?
Have you tried using an IntPtr for the first parameter but without the out?
[DllImport("FlyCAMm1_AV.dll")]
private static extern bool Capture_A_Frame(
    IntPtr pretBuff,
    out int pdSize);

IntPtr pretBuff = IntPtr.Zero;
int pdSize;
bool result = Capture_A_Frame(pretBuff, out pdSize);

尝试此操作并检查resultpretBuff.如果在函数调用后返回true并且pretBuff不为零,则表示该部分正常.

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.


如果我理解您的正确发布,第一个参数是由API在内存中创建的字节数组的指针.如果是这种情况,那么可能无法确定将值传递给它(通过使用ref或不执行任何操作)-您可能需要在其中使用out.这样做的问题是,您将需要使用Marshal类从非托管数组中复制数据,以便能够访问它.

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:

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);
}

可以像这样使用:

CapturedFrame capturedFrame = CapturedFrame.CaptureFrame();
if (capturedFrame.Buffer != null)
{
    // data in capturedFrame.Buffer
}


在这种情况下,它要求的是指向现有字节数组及其大小的指针,而不是像在文档中.

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:

[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:

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;
}

然后您可以这样称呼:

byte[] frameBuffer = new byte[256];
if (CaptureAFrame(frameBuffer))
{
    // Data is now in frameBuffer...
}

单独给您高分

  ;:咧嘴:没问题!

 :grin: No problem!


这篇关于将属性传递给非托管DLL时在何处使用"out","ref"或什么都不使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆