什么是此C ++代码的C#等价物(使用InPtr)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了什么是此C ++代码的C#等价物(使用InPtr)相关的知识,希望对你有一定的参考价值。

我正在用C#实现一个Custom Credential Provider。我正在使用C ++项目作为示例。这段C ++代码为Windows提供了一个图像。我看到它的方式phbmp是指向图像位图的指针。代码更新指针使其指向新的位图(从Resource读取)或者将位图加载到phbmp指向的地址。我不确定指针本身是否改变了。

// Get the image to show in the user tile
HRESULT CSampleCredential::GetBitmapValue(DWORD dwFieldID, _Outptr_result_nullonfailure_ HBITMAP *phbmp)
{
    HRESULT hr;
    *phbmp = nullptr;

    if ((SFI_TILEIMAGE == dwFieldID))
    {
        HBITMAP hbmp = LoadBitmap(HINST_THISDLL, MAKEINTRESOURCE(IDB_TILE_IMAGE));
        if (hbmp != nullptr)
        {
            hr = S_OK;
            *phbmp = hbmp;
        }
        else
        {
            hr = HRESULT_FROM_WIN32(GetLastError());
        }
    }
    else
    {
        hr = E_INVALIDARG;
    }

    return hr;
}

下面是我正在实现的C#等价物:

public int GetBitmapValue(uint dwFieldID, IntPtr phbmp)
{
    if (dwFieldID == 2)
    {
        Bitmap image = Resource1.TileImage;

        ImageConverter imageConverter = new ImageConverter();
        byte[] bytes = (byte[])imageConverter.ConvertTo(image, typeof(byte[]));

        Marshal.Copy(bytes, 0, phbmp, bytes.Length);

        return HResultValues.S_OK;
    }

    return HResultValues.E_INVALIDARG;
}

我正在尝试做什么:

  1. 从资源加载图像(这有效,它具有正确的长度)
  2. 将位图转换为字节数组
  3. 将这些字节复制到phbmp指向的地址

这是崩溃,我假设因为内存分配。

此方法中的参数由接口定义(在CredentialProvider.Interop.dll中,由Microsoft提供 - 我认为)。所以我很确定它是正确的,phbmp不是一个超出参数。

因为它不是一个超出参数我不能改变phbmp让它指向我的位图,对吧?我已经将phbmp分配给Bitmap.GetHbitmap()并且它不会崩溃,但它也无法正常工作。我假设对phbmp的更改仅在此方法中是本地的。

我可以理解,不可能将内存分配给预定义的地址。反过来说:你分配内存并获得指向它的指针。但随后这种变化再次出现在本地。这是如何运作的?

答案

虽然有些人同意IntPtr应该是一个超出参数(参见https://syfuhs.net/2017/10/15/creating-custom-windows-credential-providers-in-net/的评论),答案实际上是:

var bmp = new Bitmap(imageStream);  
Marshal.WriteIntPtr(phbmp, bmp.GetHbitmap()); 

以上是关于什么是此C ++代码的C#等价物(使用InPtr)的主要内容,如果未能解决你的问题,请参考以下文章

什么是 C 的 *char 的 Java 等价物

等效于嵌入式 C 中的 NOP?

01_JNI是什么,为什么使用,怎么用JNI,Cygwin环境变量配置,NDK案例(使用Java调用C代码),javah命令使用

C语言中函数的作用

什么是使用递归计算根的最佳方法C#

为什么使用%c进行格式化而不是%d [重复]