gpt4 book ai didi

c# - 将位图从 C++ DLL 传回 C# 时的行为不一致

转载 作者:行者123 更新时间:2023-11-28 08:10:11 26 4
gpt4 key购买 nike

我有一个 C# 应用程序需要获取从 C++ DLL 传回的可变长度数据。通常,我按如下方式解决此问题:对于每个实体类型(例如字符串或位图),我都有一个适当类型的持久 C++ 变量。然后,C# 应用程序调用类似“QueryBitmapByName(string bitmapName)”的内容,而“约定”是 C# 必须在调用 C++ DLL 中的另一个函数之前处理此变量。这在过去一直有效,但最近我在返回多个位图时遇到了一个我不明白的绊脚石。在 Release 模式下,行为很好,但在 Debug 模式下,如果快速连续查询位图,位图传递将无法正确复制像素数据。

C#代码片段:

[StructLayout(LayoutKind.Sequential), Serializable]
public struct BCBitmapInfo
{
[MarshalAs(UnmanagedType.U4)] public int width;
[MarshalAs(UnmanagedType.U4)] public int height;
[MarshalAs(UnmanagedType.SysInt)] public IntPtr colorData;
}

const string BaseCodeDLL = "BaseCode.dll";
[DllImport(BaseCodeDLL)] private static extern IntPtr BCQueryBitmapByName(IntPtr context, [In, MarshalAs(UnmanagedType.LPStr)] String bitmapName);

private Bitmap GetBitmap(String bitmapName)
{
IntPtr bitmapInfoUnmanaged = BCQueryBitmapByName(baseCodeDLLContext, bitmapName);
if (bitmapInfoUnmanaged == (IntPtr)0) return null;

BCBitmapInfo bitmapInfo = (BCBitmapInfo)Marshal.PtrToStructure(bitmapInfoUnmanaged, typeof(BCBitmapInfo));

return new Bitmap(bitmapInfo.width, bitmapInfo.height, bitmapInfo.width * 4, System.Drawing.Imaging.PixelFormat.Format32bppRgb, bitmapInfo.colorData);
}

private void UpdateReplayImages()
{
pictureBoxSprites.Image = (Image)GetBitmap("replaySprites");
pictureBoxTiles.Image = (Image)GetBitmap("replayTiles");
}

C++代码片段:

struct BCBitmapInfo
{
UINT width;
UINT height;
BYTE *colorData;
};
class App
{
...
BCBitmapInfo _queryBitmapInfo;
Bitmap _queryBitmapDataA;
Bitmap _queryBitmapDataB;
};

BCBitmapInfo* App::QueryBitmapByNameBad(const String &s)
{
const Bitmap *resultPtr = &_queryBitmapDataA;

if(s == "replayTiles") _queryBitmapDataA = MakeTilesBitmap();
else if(s == "replaySprites") _queryBitmapDataA = MakeSpritesBitmap();

_queryBitmapInfo.width = resultPtr->Width();
_queryBitmapInfo.height = resultPtr->Height();
_queryBitmapInfo.colorData = (BYTE*)resultPtr->Pixels();
return &_queryBitmapInfo;
}

BCBitmapInfo* App::QueryBitmapByNameGood(const String &s)
{
const Bitmap *resultPtr = NULL;

if(s == "replayTiles")
{
resultPtr = &_queryBitmapDataA;
_queryBitmapDataA = MakeTilesBitmap();
}
else if(s == "replaySprites")
{
resultPtr = &_queryBitmapDataB;
_queryBitmapDataB = MakeSpritesBitmap();
}

_queryBitmapInfo.width = resultPtr->Width();
_queryBitmapInfo.height = resultPtr->Height();
_queryBitmapInfo.colorData = (BYTE*)resultPtr->Pixels();
return &_queryBitmapInfo;
}

在 Debug模式下运行此代码并使用 QueryBitmapByNameBad 时,首先查询的位图将具有正确的尺寸,但像素数据将全部为浅绿色(第二个位图将呈现良好); QueryBitmapByNameGood 工作正常,因为它为每个可能的查询使用不同的容器。我不明白为什么 QueryBitmapByNameBad 在单线程应用程序中的行为不正确:不应该

new Bitmap(bitmapInfo.width, ..., bitmapInfo.colorData);

在它返回之前被迫将 bitmapInfo.colorData 复制出来?是否需要为每个变长查询创建一个新的“本地存储容器”?显然,对于可以从多个线程调用的 DLL,这很复杂,但对于单线程,上述方法似乎就足够了。

最佳答案

文档非常清楚地表明 Bitmap 将继续使用该内存,直到它(Bitmap 对象)被释放:

The caller is responsible for allocating and freeing the block of memory specified by the scan0 parameter. However, the memory should not be released until the related Bitmap is released.

来自 Bitmap Constructor (Int32, Int32, Int32, PixelFormat, IntPtr)

关于c# - 将位图从 C++ DLL 传回 C# 时的行为不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9345055/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com