困难的编组DirectX数组结构从C到C#

困难的编组DirectX数组结构从C到C#,第1张

概述目标:Marshal C(指向?)的结构数组到C#. C:CreateVertexDeclaration() HRESULT CreateVertexDeclaration( [in] const D3DVERTEXELEMENT9 *pVertexElements, [out, retval] IDirect3DVertexDeclaration9 ** 目标:Marshal C(指向?)的结构数组到C#.

C:CreateVertexDeclaration()@H_419_3@

HRESulT CreateVertexDeclaration(     [in]           const D3DVERTEXELEMENT9 *pVertexElements,[out,retval]  IDirect3DVertexDeclaration9 **ppDecl   );

C#:@H_419_3@

我正在使用this来定义D3DVERTEXELEMENT9结构. SharpDX是一个托管的DirectX库generated directly from the DirectX SDK C++ headers,因此它可以与COM互 *** 作完全兼容.我实际上已经有10个其他钩子完美地工作了,但这是第一个带有指向结构数组的指针.@H_419_3@

为了防止SharpDX的结构定义不起作用,我也尝试用我自己的定义替换它:@H_419_3@

[StructLayout(LayoutKind.Sequential,Pack = 1)]    public class D3DVERTEXELEMENT9    {        public short Stream;        public short Offset;        public DeclarationType Type;      // Enum        public DeclarationMethod Method;  // Enum        public DeclarationUsage Usage;    // Enum        public byte UsageIndex;    }

我尝试了以下C#方法签名:@H_419_3@

注意:将IntPtr devicePointer作为第一个参数应该不是问题.我有10个其他成功的钩子.@H_419_3@

注意:这些是Direct3D API挂钩.所以我的程序正在传递我需要从非托管C环境编组到托管C#环境的数据.@H_419_3@

1:@H_419_3@

CreateVertexDeclaration(IntPtr devicePointer,D3DVERTEXELEMENT9 [] vertexElements,out IntPtr vertexDeclaration)@H_419_3@

结果:数组有一个元素,但其值是默认值(没有意义).这意味着短流,短偏移,类型,方法,用法和用法索引都是0(枚举取其第一个值).@H_419_3@

2:@H_419_3@

CreateVertexDeclaration(IntPtr devicePointer,ref D3DVERTEXELEMENT9 [] vertexElements,out IntPtr vertexDeclaration)@H_419_3@

结果:数组本身为null.@H_419_3@

3:@H_419_3@

CreateVertexDeclaration(IntPtr devicePointer,[In,Out] D3DVERTEXELEMENT9 [] vertexElements,out IntPtr vertexDeclaration)@H_419_3@

与1.相同.没有任何好处.@H_419_3@

4:@H_419_3@

CreateVertexDeclaration(IntPtr devicePointer,D3DVERTEXELEMENT9 vertexElements,out IntPtr vertexDeclaration)@H_419_3@

与1相同,不会改变任何东西.我得到一个默认的结构.如果我调用新的D3DVERTEXELEMENT9(),也是如此.@H_419_3@

5:@H_419_3@

CreateVertexDeclaration(IntPtr devicePointer,ref D3DVERTEXELEMENT9 vertexElements,out IntPtr vertexDeclaration)@H_419_3@

我忘记了结果,但它没有用.我认为它实际上已经破坏了钩子.@H_419_3@

6:@H_419_3@

CreateVertexDeclaration(IntPtr devicePointer,IntPtr vertexElements,out IntPtr vertexDeclaration)@H_419_3@

我认为这个#6或#1 /#2应该是正确的.我可能搞砸了这个方法的实现?@H_419_3@

我试着用它来代码:@H_419_3@

var vertex = (D3DVERTEXELEMENT9)Marshal.PtrToStructure(vertexElements,typeof(D3DVERTEXELEMENT9));

但它不起作用!它与#1相同.我编组的指针结构是一个默认结构,就像我调用新的D3DVERTEXELEMENT9()一样.@H_419_3@

7:@H_419_3@

CreateVertexDeclaration(IntPtr devicePointer,ref IntPtr vertexElements,out IntPtr vertexDeclaration)@H_419_3@

零或零;无效.@H_419_3@

对于方法#6(使用IntPtr),我尝试在Visual Studio中查看内存区域.接下来的50个字节左右都是零.在50个零的字段中可能有一个2字节.但是从提供给该方法的IntPtr开始,它几乎是49个字节的零.@H_419_3@

这不是问题吗?这是不是意味着提供的指针已经不正确?所以我认为这意味着我有错误的方法签名.问题是我一直在尝试各种可能的组合,它们要么崩溃程序,要么给我一个默认数组,就像我调用新的D3DVERTEXELEMENT9()一样.@H_419_3@

问题:正确编组从C到C#的pVertexElements结构数组的解决方案是什么,为什么我当前的签名不正确?@H_419_3@

附加说明:在C中,此特定数组的长度由suffixing a D3DDECL_END定义.我不知道如何在没有某种传递长度参数的情况下在C#中获取相应的数组长度.@H_419_3@

其他工作钩:@H_419_3@

C :@H_419_3@

BeginScene(LPDIRECT3DDEVICE9 pDevice)BeginStateBlock(LPDIRECT3DDEVICE9 pDevice)Clear(LPDIRECT3DDEVICE9 pDevice,DWORD Count,CONST D3DRECT* pRects,DWORD Flags,D3Dcolor color,float Z,DWORD Stencil)colorFill(LPDIRECT3DDEVICE9 pDevice,IDirect3DSurface9* pSurface,CONST RECT* pRect,D3Dcolor color)CreateAdditionalSwapChain(LPDIRECT3DDEVICE9 pDevice,D3DPRESENT_ParaMETERS* pPresentationParameters,IDirect3DSwapChain9** pSwapChain)CreateCubeTexture(LPDIRECT3DDEVICE9 pDevice,UINT EdgeLength,UINT Levels,DWORD Usage,D3DFORMAT Format,D3DPOol Pool,IDirect3DCubeTexture9** ppCubeTexture,HANDLE* pSharedHandle)

…@H_419_3@

C#:@H_419_3@

注意:我为所有这些代表使用SharpDX枚举和结构,它们工作正常.它们也都以IntPtr devicePointer开头.@H_419_3@

BeginSceneDelegate(IntPtr devicePointer);BeginStateBlocKDelegate(IntPtr devicePointer);ClearDelegate(IntPtr devicePointer,int count,IntPtr rects,ClearFlags flags,colorBGRA color,float z,int stencil);colorFillDelegate(IntPtr devicePointer,IntPtr surface,IntPtr rect,colorBGRA color);CreateAdditionalSwapChainDelegate(IntPtr devicePointer,Out] PresentParameters presentParameters,out SwapChain swapChain);CreateCubeTextureDelegate(IntPtr devicePointer,int edgeLength,int levels,Usage usage,Format format,Pool pool,out IntPtr cubeTexture,IntPtr sharedHandle);...

其他挂钩的传递参数的日志:@H_419_3@

DLL injection suceeded.Setting up Direct3D 9 hooks...Activating Direct3D 9 hooks...CreateDepthstencilsurface(IntPtr devicePointer: 147414976,Int32 wIDth: 1346,Int32 height: 827,Format format: D24S8,MultisampleType multiSampleType: None,Int32 multiSampleQuality: 0,Boolean discard: False,IntPtr& surface: (out),IntPtr sharedHandle: 0)CreateDepthstencilsurface(IntPtr devicePointer: 147414976,IntPtr sharedHandle: 0)Clear(IntPtr devicePointer: 147414976,Int32 count: 0,IntPtr rects: (Empty),ClearFlags flags: Target,colorBGRA color: A:0 R:0 G:0 B:0,Single z: 1,Int32 stencil: 0)Clear(IntPtr devicePointer: 147414976,Int32 stencil: 0)BeginScene(IntPtr devicePointer: 147414976)Clear(IntPtr devicePointer: 147414976,ClearFlags flags: ZBuffer,Int32 stencil: 0)BeginScene(IntPtr devicePointer: 147414976)

与此CreateVertexDeclaration()最相似的方法签名似乎是Clear().这是我对Clear()的实现:@H_419_3@

private Result Clear(IntPtr devicePointer,int stencil)        {            try            {                var structSize = Marshal.SizeOf(typeof (Rectangle));                var structs = new Rectangle[count];                for (int i = 0; i < count; i++)                {                    structs[i] = (Rectangle) Marshal.PtrToStructure(rects,typeof (Rectangle));                }                // Seems to work fine,not sure why it doesn't work for CreateVertexDeclaration                var rectangles = structs;                Log.LogMethodSignatureTypesAndValues(devicePointer,count,rectangles.PrintTypesnamesValues(),flags,color,z,stencil);                GetorCreateDevice(devicePointer);                if (rectangles.Length == 0)                    Device.Clear(flags,stencil);                else                    Device.Clear(flags,stencil,rectangles);            }            catch (Exception ex)            {                Log.Warn(ex.ToString());            }            return Result.Ok;        }
解决方法 首先,SharpDX中的声明使用Pack = 2(而不是Pack = 1):
    [StructLayout(LayoutKind.Sequential,Pack = 2 )]    public  partial struct VertexElement {       ...    }

此外,如果你想确定元帅,更喜欢使用不安全的Marshal.StructuretoPtr或任何其他的编组方法(当结构直接映射到C#等价物时).您将避免Marshal性能问题,并且您将确定内存布局(假设结构在c#中正确声明)@H_419_3@

public unsafe static voID CreateVertexDeclaration(IntPtr devicePointer,IntPtr vertexElementsPtr,out IntPtr vertexDeclaration){    var vertexElements = (VertexElement*)vertexElementsPtr;    // Access to all VertexElement (last element is specifIEd by Cmacro D3DDECL_END() in d3d9types.h)    ...}
总结

以上是内存溢出为你收集整理的困难的编组DirectX数组结构从C到C#全部内容,希望文章能够帮你解决困难的编组DirectX数组结构从C到C#所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1240726.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存